0
\$\begingroup\$

I've written a simple bookmarklet to go to the YouTube channel RSS feed URL from at least any video or channel page:

javascript:(function () {
    var newLocation = function () {
        var url;
        Array.prototype.slice.call(document.getElementsByTagName('link')).forEach(function (element) {
            if (element.getAttribute('type') === 'application/rss+xml') {
                console.log('Found direct feed link');
                url = element.getAttribute('href');
            }
        });
        if (!url) {
            Array.prototype.slice.call(document.getElementsByTagName('meta')).forEach(function (element) {
                if (element.getAttribute('itemprop') === 'channelId') {
                    console.log('Found channel ID');
                    url = 'https://www.youtube.com/feeds/videos.xml?channel_id=' + element.getAttribute('content');
                }
            });
        }
        return url;
    }();
    if (newLocation === undefined) {
        console.log('Could not find a channel RSS feed from ' + location.href);
    } else {
        location.href = newLocation;
    }
})();

Some questions which come to mind:

  • Is this the simplest way to find an element with a specific attribute value?
  • Does this work with recent browsers other than Firefox?
  • Does it use any non-standard/deprecated features?
  • Are there any YouTube pages this does not work on, where it should?
\$\endgroup\$
1
\$\begingroup\$

Is this the simplest way to find an element with a specific attribute value?

"simple" is subjective. It could mean anything, like lesser lines, fewer keystrokes, lesser complexity. To me, what I consider simple is code that's short, concise and one that I can understand without running the code.

Does this work with recent browsers other than Firefox?

With regards to the code, I don't see why not. However, I'm not sure how bookmarklets work with browsers these days. That part you might want to check.

Does it use any non-standard/deprecated features?

Nothing out of the ordinary. You might want to check MDN or Kangax's compatibility table for more info about what APIs are available to which browsers.

Are there any YouTube pages this does not work on, where it should?

Not something you'd normally ask in Code Review. That's up to you to find out.


You could substitute array.forEach with find. That way, it bails out on the first item found and not go through the entire array.

Next, you can use template literals instead of string concatenation. It's much more concise and lessens the chance that you'll miss a quote or a + somewhere.

Next, your logic has a lot of if statements. You could try to invert the logic and bail out early. You can also split your logic into functions, that way you can maintain extraction methods with clear separation. Then call them in sequence with || between. That way, the script uses the return value of first call that returns a value, or tries the next if the previous fails. Same conditional effect without the use of if and a lot of nested code.

Something along these lines:

javascript:(function(){
  const slice = Array.prototype.slice;

  function getUrlFromRss(){
    const links = slice.call(document.getElementByTagName('link'));
    const link = links.find(l => l.getAttribute('type') === 'application/rss+xml');
    return link ? link.getAttribute('href') : '';
  }

  function getUrlFromMeta(){
    const metas = slice.call(document.getElementsByTagName('meta'));
    const meta = metas.find(m => m.getAttribute('itemprop') === 'channelId');
    const id = meta ? meta.getAttribute('content') : '';
    return id ? `https://www.youtube.com/feeds/videos.xml?channel_id=${id}` : '';
  }

  const url = getUrlFromRss() || getUrlFromMeta() || '';

  if(!url) return console.log(`Could not find a channel RSS feed from ${location.href}`)

  location.href = url;
})();
\$\endgroup\$
0
\$\begingroup\$

Remarks to your code

  • Is this the simplest way to find an element with a specific attribute value?

    No, this is luckily much easier. You could use JS function querySelector() and CSS attribute selector link[type="application/rss+xml"] to achieve the same in one line. Example use is in my rewrite of your code at the bottom of this answer.

  • Does this work with recent browsers other than Firefox?

    Your code should work even on IE8.

  • Does it use any non-standard/deprecated features?
    Are there any YouTube pages this does not work on, where it should?

    See last bullet point below my code.

  • I don't see the need to break out part of your code into separate newLocation() function.
  • Instead of iterating through HTMLCollection using forEach(), you should use find() which would return on match instead of iterating to the end of collection despite satisfying condition.
  • element.getAttribute('type') could be replaced with element.type.

My rewrite

javascript:(function() {
  var url = (document.querySelector('link[type="application/rss+xml"]') || '').href;
  if (url !== undefined) {
    return location.href = url;
  }
  try {
    var channelId = ytplayer.config.args.ucid;
    location.href = 'https://www.youtube.com/feeds/videos.xml?channel_id=' + channelId;
  }
  catch (TypeError) {
    console.error('YouTube RSS feed bookmarklet: Could not find a channel RSS feed');
  }
})();
  • In url variable, we use JS function querySelector() and CSS attribute selector link[type="application/rss+xml"] to get the right element. However this function could return null. Trying to get .href property of null would throw an error, hence the || ''. That way if querySelector() returns null, we will ask for .href property of an empty string, which will give us undefined, but not an error.
  • ytplayer.config.args.ucid stores the same channelId value that one of <meta> tags does, so it is used instead. However if something suddenly changed, it could throw TypeError and that's why this block is enclosed in try {…} catch(…) {…}.
  • Answering your initial questions: this uses the simplest way to find an element with a specific attribute value, it works for IE9+, it doesn't uses any deprecated features (although bookmarklets themselves are not too famous these days) and I think it should work on pages where you would be willing to invoke it, although this is just an assumption and wishful thinking.
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.