Bookmarklet to show anchors

Recently found this bookmarklet that visualizes anchor tags in a web page (elements with an ID and anchor tags with a name). Unfortunately Chrome doesn’t like it because it loads jQuery. It also contains a base64 image of anchor. Nowadays you don’t need jQuery for simple tasks and there’s probably an emoji that suits your needs. So, there you go, a simpler bookmarklet:

javascript:Array.prototype.filter.call(document.querySelectorAll('[id],a'),function(e){if(e.nodeName!='A'||e.getAttribute('name')){e.insertAdjacentHTML('beforebegin','<a href="#'+(e.id?e.id:'')+(e.name?e.name:'')+'">&'+'#x2693;</a>')}});

Updated: added an anchor tag around the anchor emoji with the actual bookmark.

Advertisements

What is Node.js?

It took me some time to get my head around the peculiarities of Node.js so here’s my take on explaining it.

What is Node?

Node(.js) is a program that allows you to run programs written in JavaScript.

But I heard it is a Web Server?

Well a Web Server is a program; you can write one in JavaScript with Node.

Why is it so popular?

Well web developers like to create tools in JavaScript because they are using that language already for programming the browser. For that reason it is also a compelling web server. Some frameworks even allow you to run the same code on the server and the browser. But Node has another advantage.

How come Node beats established web servers?

Node uses a novel approach at dealing with concurrency, that is all the requests and responses a web server needs to process.

So how does Node deal with concurrency?

Well it’s like comparing a large crossing to a roundabout. If a crossing is complicated and busy it needs traffic lights to start and stop the flows that would otherwise collide. With a roundabout however, all flows merge into a large loop and traffic ramps off at the various exits.

Another analogy is a restaurant serving several customers. To deal with all the cooking involved you could:

  • Have multiple kitchens. This is like multiple processes.
  • Have several cooks working in the same kitchen. This is like multithreading.
  • Split the work into small steps that complete quickly. When there is waiting involved (for the oven to finish or water to boil) move on to the next task and continue when the waiting is over.

Traditional web servers use multiple processes and multithreading. The third option is obvious for cooking but not for web servers.

The main downside of each method is:

  • Multiple processes requires a lot of memory and switching and communication between processes requires considerable CPU time.
  • Multithreading is hard when resources are shared. Also each thread requires memory and switching requires CPU time.
  • Splitting programs into small steps requires a language to split code into small parts while still being able to see the flow of tasks.

To be fair Node is not the first web server doing things this way, but it sure made it popular.

Why JavaScript?

Well, besides being able to use the same language in the browser JavaScript has two advantages:

  • It has lambdas, useful for splitting programs into small parts.
  • It has nothing else for handling concurrency, so there’s less confusion.

Using XmlReader.Read() with ReadElementContentAs*()

Most samples of using an XmlReader use a Read in a while loop like this:

var value1 = 0;
var value2 = 0;
var value3 = 0;
while (reader.Read())
{
    if(reader.IsStartElement())
    {
        switch(reader.Name)
        {
            case "Element1":
                value1 = reader.ReadElementContentAsInt();
                break;
            case "Element2":
                value2 = reader.ReadElementContentAsInt();
                break;
             case "Element3":
                value3++;
                break;
         }
    }
}

However, this pattern may fail if elements are not separated by whitespace. The culprits are the ReadElementContentAs* methods. Without separating whitespace they leave the reader at the start of the next element. The Read at the top of the loop moves it past this next start element and it will be skipped completely.

This is particularly nasty because it works well with nicely formatted XML, which you’ll probably use while testing, because it has whitespace between elements. However, dense XML generated by a feeding system will trip it up.

Instead you can use something like this:

var value1 = 0;
var value2 = 0;
var value3 = 0;
while (!reader.EOF)
{
    if(reader.IsStartElement())
    {
        switch(reader.Name)
        {
            case "Element1":
                value1 = reader.ReadElementContentAsInt();
                continue;
            case "Element2":
                value2 = reader.ReadElementContentAsInt();
                continue;
            case "Element3":
                value3++;
                break;
        }
    }
    reader.Read();
}

The Read at the top of the loop is replaced by an EOF check and moved to the bottom. This allows skipping it with the continue keyword after using a ReadElementContentAs* method or anything else that leaves the reader at the start of the next element. Anything else is followed by a break to move the reader forward.

Please note the use of continue instead of break is rather subtle so a comment is probably in order.

BTW, if you want to test XML documents without having to edit terse XML files load pretty formatted XML in an XDocument and then open an XmlReader from it. Apparently this reads the XML without the whitespace nodes.

Responsive Bootstrap and AngularJS routing

Update: If you’re combinding Bootstrap with AngularJS you might want to consider using Angular UI Bootstrap project. Basically this removes the dependency on jQuery. I haven’t tried it yet but it looks promising.

Just noticed a problem with the awesome Responsive Bootstrap template when combined with AngularJS and routing.

The ‘collapse button’ in the navbar that appears with small device widths no longer works when you’re using AngularJS routing. This is because the collapse button is actually an anchor tag and in the default template it has an empty href attribute. In practice this means that if you click it the browser stays on the home page.

But when AngularJS appends ‘#/’ to the home URL this anchor tag directs the browser to the home page. Then AngularJS appends ‘#/’ again and this confuses the browser.

The solution is to edit the boilerplate bootstrap HTML and to edit bootstrap.js.

In the boilerplate HTML find this:

<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
 <span class="icon-bar"></span>
 <span class="icon-bar"></span>
 <span class="icon-bar"></span>
</a>

then add href=”#” to the anchor tag.

Then in bootstrap.js find this:

/* COLLAPSIBLE DATA-API
 * ==================== */
$(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) {
 var $this = $(this), href
 , target = $this.attr('data-target')
 || e.preventDefault()
 || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
 , option = $(target).data('collapse') ? 'toggle' : $this.data()
 $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
 $(target).collapse(option)
})

and add ‘return false;’ before the last line with the closing braces:

This prevents the anchor tag’s default behavior, the navigation.

Hope this helps!