Best html questions in November 2011

Can vim highlight matching HTML tags like Notepad++?

63 votes

VIM has support for matching pairs of curly brackets, parentheses, and square brackets. This is great for editing C-style languages like PHP and Javascript. But what about matching HTML tags?

Notepad++ has had this feature for as long as I've been using it. Being able to spot where blocks of HTML begin and end is very useful. What I'm looking for is something like this for vim (see the green div tags):

(a bonus feature: highlighting unclosed HTML tags, like the red tag in this screenshot).

matchit has been proposed as a next-best-thing, but it requires an extra keystroke to use its functionality. I'd like be able to see where the blocks of HTML begin and end without an extra keypress.

I've trawled the internet to find something like this for vim. Apparently, I'm not the only one, according to 2 other StackOverflow questions and nabble.

I've almost resigned myself to vim not being able to visually match html tags. Is it possible for vim to do this?

Addendum: If it is not currently possible to do this with any existing plugins, does any vimscript wizard out there have any pointers on how to approach writing a suitable plugin?

I had to work with some HTML today so thought I would tackle this. Added a ftplugin to vim.org that should solve your problem.

You can get it here on vim.org.

You can get it here on github.

Hope it works for you. Let me know if you have any problems.

JavaScript <!-- //--> are required?

22 votes

I just like to ask what the title says. The following string required into HTML script tags?

<!--
//-->

If I don't use them what would happen?

Not unless you are targeting browsers that predate the <script> element (i.e. Netscape 1 and friends). (Hint: You aren't).

If you don't use them, and a browser that old (so old it can't even cope with the HTTP Host header which is needed for sites that use virtual hosts) tries to access the site, then the content of the <script> element will be treated as text to be displayed.

Further reading: Comments and CDATA: The mysterious history of script and style in HTML

Workaround for lack of CSS feature to "suppress inherited styles" (and backgrounds?)

21 votes

I have a DOM situation that looks like this:

  • A is an ancestor of B, which is in turn an ancestor of C

  • Initially, A has styles that inherit to B and C

  • I wish to temporarily highlight B by giving it a highlighted class

    ...however...

  • I want to "escape" the highlighting on C so it changes as little as possible

It seems this is not possible within the cascading paradigm of CSS. The only way to "un-apply" a style is to apply an overriding style. My problem is that the highlight code is in a plugin that wants to play well with an arbitrary page's existing CSS...my selectors are like this:

/* http://www.maxdesign.com.au/articles/multiple-classes/ */
.highlighted.class1 {
    background-color: ...
    background-image: ...
    ...
}
.highlighted.class2 {
   ...
}
/* ... */
.highlighted.classN {
   ...
}

Background is a tricky one...because although it is not an inherited CSS property, changing an ancestor's background can alter a descendant's appearance (if they have transparent backgrounds). So it's an example of something that causes the kind of disruption I'm trying to negate. :-/

Are there any instances of how people have suppressed the inheritance of changes in this fashion? Perhaps using tricks such as caching computed styles? I'm looking for any default technique that can be at least a little smarter than a function-level hook that says "hey, the plugin highlighted this node...do what you need to visually compensate."


UPDATE I have created a basic JsFiddle of this scenario to help make the discussion clearer:

http://jsfiddle.net/HostileFork/7ku3g/

Manage all CSS changes in javascript so that they're easily reversible. As you said, it's not possible in pure CSS, but you can cache the styles via javascript.

In steps:

  1. define what kind of elements will be ignored inside the highlight
  2. check if you have a background-image in any of the parents
  3. if you do, save the image and that element's offset()
  4. grab the descendant elements
  5. save their current CSS styles (before the highlight)
  6. apply the highlight styles to the target
  7. re-apply the saved styles for the descendants
  8. if there was a parent with a background image, calculate and offset the image accordingly

This keeps all styles for the inner elements intact, and accounts for background images that "fall through" transparent backgrounds.

Here's a test: http://jsfiddle.net/W4Yfm/2/

This leaves a messy sea of style attributes behind though, you might want to clean it up. There are probably unnacounted edge cases too.

To be most reliable you should use a technique like @Jan pointed out (draw the highlight on canvas), but you won't have support in IE < 9, and it's probably too slow for mobile.

Could a Malicious Hacker Alter a Hidden Post Variable

20 votes

I know that a POST can be spoofed in terms of originating domain, but what about being able to change the variables of the hidden POST variables in my HTML? I am concerned that someone could alter the "amount" value in my PayPal form from this:

<input type="hidden" name="amount" value="1.00">

to this:

<input type="hidden" name="amount" value="0.01">

or something similar. Thanks.

Yes, it is trivially easy for anyone to modify your form variables. Whether they are GET or POST doesn't matter at all.

Web security rule #1: Never trust any user input. Also stated as "All users are malicious hackers" or some variant thereof.

answer to comment: The solution is to know all of the correct values on the server side, without having to pass them through the client side (Javascript). So regardless of what the form says, you already know the price. Just use the same value you used to populate the form in the first place.

Snake-alike fluid layout algorithm

15 votes

The goal is to produce a fluid layout as show below.

enter image description here

So far I have a working function moveBox(lastBox, "east") that keeps track of the row and column indexes.

function moveBox(box, where) {
  switch (where) {
    case "north":
      lastTopOffset -= BOX_HEIGHT + BOX_MARGIN;
      box.style.top  = lastTopOffset  + 'px';
      box.style.left = lastLeftOffset + 'px';
      rowIndex -= 1;
      break;
    //  ...    
  }

My current code,

(function () {
    var i, lastBox,
      MAX_DIVS       = 72,
      BOX_HEIGHT     = 50,
      BOX_WIDTH      = 100,
      BOX_MARGIN     = 5,
      field          = document.getElementById('fieldPerimeter'),
      fieldHeight    = field.offsetHeight,
      maxRows        = Math.floor(fieldHeight / (BOX_HEIGHT + BOX_MARGIN)),
      rowIndex       = 0,
      colIndex       = 0,
      lastLeftOffset = 0,
      lastTopOffset  = 0;

  function moveBox(box, where) {
    switch (where) {
      case "north":
        lastTopOffset -= BOX_HEIGHT + BOX_MARGIN;
        box.style.top  = lastTopOffset  + 'px';
        box.style.left = lastLeftOffset + 'px';
        rowIndex -= 1;
        break;

      case "east":
        lastLeftOffset += BOX_WIDTH + BOX_MARGIN;
        box.style.top  = lastTopOffset  + 'px';
        box.style.left = lastLeftOffset + 'px';
        colIndex += 1;
        break;

      case "south":
        lastTopOffset += BOX_HEIGHT + BOX_MARGIN;
        box.style.top  = lastTopOffset  + 'px';
        box.style.left = lastLeftOffset + 'px';
        rowIndex += 1;
        break;

      default:
        break;
    }
  }

  for (i = 0; i < MAX_DIVS; i += 1) {
    lastBox = document.createElement('div');
    lastBox.className = 'box';
    lastBox.innerHTML = i;
    field.appendChild(lastBox);      

    //delete me 
    if( (i + 1) % 2 === 0 || (i + 1)% 3 === 0){ 
      moveBox(lastBox, "east");
    } else {
      moveBox(lastBox, "south");
    }
    //delete me      

//    if(rowIndex < maxRows && rowIndex > 0){
//    if (colIndex % 4 === 0){
//      moveBox(lastBox, "south");
//    } else if (colIndex % 2 === 0){
//      moveBox(lastBox, "north");
//    } else {
//     moveBox(lastBox, "east");
//    }
//  } 

  }      
})();

appends divs to a container and then moves it. The code below shows part of my attempts for specifing when to move North or South. But I'm struggling with achiving the desired layout.

 if      (colIndex % 4 === 0) { moveBox(lastBox, "south"); } 
 else if (colIndex % 2 === 0) { moveBox(lastBox, "north"); }
 else                         { moveBox(lastBox, "east");  }

enter image description here

Here is the working fiddle, http://jsfiddle.net/efortis/zuY74/

Note I hardcoded the offsetHeight in order to work on the fiddle and also added a lastMove variable at the top.

  for (i = 0; i < MAX_DIVS; i += 1) {
    lastBox = document.createElement('div');
    lastBox.className = 'box';
    lastBox.innerHTML = i;
    field.appendChild(lastBox);

    if (i === 0) {
      rowIndex += 1;
    } else {
      if (colIndex % 4 === 0 && rowIndex < maxRows) {
        moveBox(lastBox, "south");
        lastMove = "south";
      } else if (colIndex % 2 === 0 && rowIndex !== 1 && lastMove !== "south") {
        moveBox(lastBox, "north");
        lastMove = "north";
      } else {
        moveBox(lastBox, "east");
        lastMove = "east";
      }
    }
  }

What is the best HTML approach when form inputs are spread throughout the page?

11 votes

I am building a faceted search system that has inputs in a sidebar (the facets are check boxes), and an input in the header of the page (the main query box). All of these inputs are submitted simultaneously when the user submits a search.

The only way I can think of to make this work is to wrap the entire page in an HTML form tag. Something like the following pseudo-html:

<form>
  <div id='header'>
    <logo/>
    <input id='q'/>
    <!-- a bunch more stuff -->
  </div>
  <div id='sidebar'>
    <div id='sidebar-facets-subsection'>
      <input id='facet1'/>
      <input id='facet2'/>
      <input id='facet3'/>
      <!-- a bunch more stuff -->
    </div>
    <div id='sidebar-form-subsection'>
      <form id='unrelated-form'>
        <input id='unrelated-input-1'/>
        <input id='unrelated-input-2'/>
      </form>
    </div>
  </div>
  <!-- a bunch more stuff -->
</form>

This would work, except for three things:

  1. I need to use other forms in the page, as I've indicated above.
  2. I use different django templates to generate the header and the sidebar, making the templates have dependencies on each other.
  3. It's a real mess since the sidebar is in reality about 100 lines, not three.

Is there a more clever way of doing this that I'm not aware of, or is creating huge HTML forms the norm? In circumstances like this, is it better to use Javascript to somehow generate the input entries in a more normal form? Or is that the only option?

Any creative solutions or ideas?

You can make it work with Javascript without sacrifying accesibility

  1. Put all the checkboxes in the header and wrap them in div
  2. Set up and empty but clean side bar
  3. Using Javascript, move you checkboxes from the header into the side bar
  4. Attach a callback to the form.submit event, and when the user submit the form, cancel the event then, take the data from the search field and the checkboxes and send it as an Ajax POST request.

Using a framework like jQuery, it's a 15 minutes job.

If the user has JS enable, the form will post the request and everything will work. If the user doesn't have javascript enable, the checkboxes will be in the header and so they will work, at just the price of a slightly less elegant design.

But people with Javascript disable are used to design changes so it's ok.

Can this be done by CSS only?

9 votes

Can the following be achieved by using CSS only, that is, without using any images? In the second case, one can round the green corners on the left side of the div and not round them on the right side. However, is there a solution for the first and third case without resorting to an external image?

Note, that there should be a smooth transition from the bar being completely empty to being completely green.

If you put the green bar inside the grey container and set overflow: hidden on the grey container then the green bar will be clipped when you give the container rounded corners.

Make a list of values line up with a textarea and labels

9 votes

Here's some CSS and HTML to make a textarea below a list of data points:

form label {
  width: 140px;
  float: left;
}
form ol li {
  background: #98c8dc;
  list-style: none;
  padding: 5px 10px;
}

<form>
<ol>
<li>
  <label><br/><br/><br/><br/>Recent data</label>
  <ol>
  <li>3 99</li>
  <li>5 98</li>
  <li>15 97</li>
  <li>28 96</li>
  </ol>
</li>
<li>
  <label>New data</label>
  <textarea placeholder="30 95" rows="4"></textarea>
</li>
</ol>
</form>

It renders like this:

enter image description here

How would you recommend I get it to line up just right? Namely, "Recent data" should line up with the "28 96" line and, perhaps trickiest, the "30 95", despite being in the textarea, should line up as if it's just another row that comes after the "28 96".

This is a good case for CSS positioning. Elements with position:absolute are positioned relative to their closest positioned parent. That means we can anchor the labels to the top/left of their containers using position:relative on the <ol>, and position:absolute on the label.

Example here: http://jsfiddle.net/YhQYS/1/

HTML:

<form action="." method="post">
    <ol>
        <li class="recent-data">
          <strong>Recent data</strong>
          <ol>
              <li>3 99</li>
              <li>5 98</li>
              <li>15 97</li>
              <li>28 96</li>
          </ol>
        </li>
        <li class="new-data">
          <label>New data</label>
          <textarea placeholder="30 95" rows="4"></textarea>
        </li>
    </ol>
</form>

CSS:

form > ol {
    background: #98c8dc;
    font-family: serif;
}
.recent-data > ol,
.new-data > ol {
    list-style: none;
    padding: 5px 10px 5px 0;
    line-height:20px;
}
.recent-data li { padding-left:5px; }
.recent-data,
.new-data {
    position:relative;
    padding-left:140px;
}
.recent-data strong,
.new-data label {
    position:absolute;
    left:10px;
    line-height:20px;
}
.recent-data strong { bottom:5px; }
.new-data label { top:5px; }
.new-data textarea {
    font-family:serif;
    font-size:100%;
    padding:4px;
}

This is very simple to reason about, and reliable cross-browser. Note that you shouldn't use a <label> that doesn't have a correspondent form control.


But that stuff looks like tabular data... it's your choice, we don't have enough context to know what mark-up is more appropriate. So here is a more semantically correct approach using tables, rowspan and vertical-align:

HTML:

<form action="." method="post">
    <table id="results">
        <tbody>
            <tr>
                <th rowspan="4" scope="row" class="recent-label">Recent data</th>
                <td>2</td>
                <td>47</td>
            </tr>
            <tr>
                <td>3</td>
                <td>99</td>
            </tr>
            <tr>
                <td>5</td>
                <td>98</td>
            </tr>
            <tr>
                <td>5</td>
                <td>98</td>
            </tr>
            <tr>
                <th rowspan="1" scope="row" class="new-label">New data</th>
                <td colspan="2" class="new-data">
                    <textarea>23</textarea>
                </td>
            </tr>
        </tbody>
    </table>
</form>

CSS:

form {
    background: #98c8dc;
    font-family: serif;
}
#results th,
#results td {
    padding:3px 5px;
}

#results .recent-label {
    vertical-align:bottom;
}
#results .new-label {
    vertical-align:top;
}
#results .new-data {
    padding-left:0px;
}
#results textarea {
    padding:4px; // +1px border
    font-size:100%;
    font-family:serif;
}

Sample at http://jsfiddle.net/quqf8/1/

Specify parent divs opacity but make it not affect children HTML elements

8 votes

I have a paragraph element inside a div. The div has an opacity of 0.3 & the paragraph has an opacity of 1.

When I show the elements, it appears the paragraph is transparent, like it has an opacity of 0.3.

Is there a way to make the paragraph inside the div have full opacity? Maybe I can set a CSS value for this?

<div style="opacity: 0.3; background-color: red;">
   <p style="opacity: 1;">abcde</p>
</div>

You can't, the opacity level is relative to the parent's opacity, always. So 1.0 inside 0.3 would be 100% of 0.3, which is 0.3, and 0.5 inside 0.3 would be 50% of 0.3 which is 0.15. If you're only using opacity for the background color, you can specify the color using the RGBA method so that the red will be opaque and not the content (and thus the paragraph inside it).

<div style="background-color: rgba(255, 0, 0, 0.3);">
   <p>abcde</p>
</div>

See here.

In Javascript how can I set rgba without specifying the rgb?

8 votes

I have an HTML element whose background colour is set with rgba()

<div style="background-color: rgba(2,100,100,0);"> </div>

Then I have a timer that makes the background slowly fade in by changing the opacity value of the element in javascript

myEle.style.backgroundColor = "rgba(x,x,x,0.1)"; // I have to know the rgb values to update the alpha value

Is there a way to set the a value of rgba() without changing/knowing the rgb values?

Maybe I can do something like this?

var r = myEle.style.r;
var g = myEle.style.g;
var b = myEle.style.b;
myEle.style.backgroundColor = "rgba("+r+","+g+","+b+",0.1)";

After some playing around, and the discovery of getComputedStyle, I have put together this.

<!DOCTYPE HTML>
<html>
  <head>
    <style type="text/css">
      #element {
        background-color: rgb(10,10,10);
        background-color: rgba(10,10,10,1);
      }
    </style>
    <script type="text/javascript">      
      HTMLElement.prototype.alpha = function(a) {
        current_color = getComputedStyle(this).getPropertyValue("background-color");
        match = /rgba?\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*\d+[\.\d+]*)*\)/g.exec(current_color)
        a = a > 1 ? (a / 100) : a;
        this.style.backgroundColor = "rgba(" + [match[1],match[2],match[3],a].join(',') +")";
      }
    </script>
  </head>
  <body>
    <div id="element">
      This is some content.
    </div>
    <script type="text/javascript">
      e = document.getElementById('element');
      e.alpha(20);
    </script>
  </body>
</html>
  • Make sure you define in your css your values, and cascade because RGBA is CSS3.
  • Also see that you can pass in a number >1 for alpha and it will divide by 100 for you (I hate working with decimals when thinking percentages).
  • Enjoy!

CSS/HTML : how to make something become absolute positioned once you scroll by it

8 votes

I'm new to CSS and HTML here and I'm trying to learn how to make something become absolutely positioned once you scroll by it on the page.

Here's an example of what I mean: http://fab.com/help/ (you don't need an account to scroll). When you scroll down, the black menu bar at the top disappears and the white menu bar with "How can we help you" becomes absolutely positioned.

I created a an example with a similar menu system,

http://jsfiddle.net/jkdbP/

but I don't know where to start to make it become absolutely positioned once it's scrolled by, thanks a lot for any insights!

See this jsFiddle: http://jsfiddle.net/jkdbP/2/

var menuTop = $('.menu').offset().top;
var menuClone = $('.menu').clone().addClass('fixed');

$(window).bind('scroll', function() {
    var scrollY = window.pageYOffset;

    if(scrollY > menuTop) {
        if(menuClone.parent().length === 0) {
            menuClone.appendTo($('.menu').parent());
        }
    } else if(menuClone.parent().length > 0) {
        menuClone.remove();
    }
});

You can use jQuery's .offset().top to get the Y-position of your menu, and window.pageYOffset (or document.body.scrollTop for old IE compatibility) to get the page's scroll offset. You can then handle the window's scroll event.

How do I dynamically insert an SVG image into HTML?

6 votes

I have some code that retrieves a scripted svg image from a server via Ajax. I can get the image text back into the browser, but I can't find a way to insert it into the DOM that will actually display it. Can anyone help with this? The svg looks likes this:

<svg id="chart" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="init(evt)">
<script type="application/ecmascript">
<![CDATA[
...lots of code, changes on each Ajax request
//]]>
</script>
<script type="application/ecmascript" xlink:href="js-on-server-1.js"/>
<script type="application/ecmascript" xlink:href="js-on-server-2.js"/>
</svg>

I've tried various things. If I do this:

// xmlhttp.onreadystatechange:
addImage(xmlhttp.responseXML, "somewhere");
...
function addImage(txt, dst_id) {
   var scr = document.createElement("div");

   if("textContent" in scr)
      scr.textContent = txt;  // everybody else
   else
      scr.text = txt;         // IE

   document.getElementById(dst_id).appendChild(scr);
}

Then Opera and Chrome do nothing, and F/F complains "[object XMLDocument]". If I change 'responseXML' to 'responseText', then Opera/Chrome correctly display the entire svg text (not image) in the right place, and F/F still gives the same warning. I've also tried assigning the response to an innerHTML, but that does nothing. Any ideas? Thanks.

EDIT

In response to Phrogz'z answer below - I've added two simple svg files. The first is a 'standard' simple svg, displaying a circle. The second is a scripted svg, displaying a rectangle. You should be able to view both directly in any browser, except IE8-. If I edit Phrogz'z code to use the circle file (replace 'stirling4.svg' with the name of this file), then it works, but if I want the scripted rectangle instead, it doesn't. Tested on F/F, Opera, Chromium, but doesn't work anyway on (my) Chromium.

File 1, circle:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
</svg>

File 2, rectangle:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="init(evt)">
<script type="application/ecmascript">
<![CDATA[
var svgDocument;
var svgns = "http://www.w3.org/2000/svg";
function init(evt) {
  if(window.svgDocument == null)
    svgDocument = evt.target.ownerDocument;
   var lbox = svgDocument.createElementNS(svgns, "rect");
   lbox.setAttributeNS(null, "x",                10);
   lbox.setAttributeNS(null, "y",                10);
   lbox.setAttributeNS(null, "width",            30);
   lbox.setAttributeNS(null, "height",           30);
   lbox.setAttributeNS(null, "stroke",           "#8080ff");
   lbox.setAttributeNS(null, "stroke-width",     2);
   lbox.setAttributeNS(null, "fill-opacity",     0);
   lbox.setAttributeNS(null, "stroke-opacity",   1);
   lbox.setAttributeNS(null, "stroke-dasharray", 0);
   svgDocument.documentElement.appendChild(lbox);
}
//]]>
</script>
</svg>

Presumably the answer is to get the script into the header??

In general, the problem is twofold threefold:

  1. HTML is not XHTML, and support for SVG in HTML is shoddy and poorly-defined as of this writing. The solution is to use a real XHTML document where SVG-namespaced elements are actually treated as SVG.

  2. The responseXML is in another DOM document, and you can't normally just move nodes from one document to another. You are supposed to use document.importNode to import a node from one document to another.

  3. Loading an SVG file with onload event handlers will not have those handlers invoked by either creating the node or appending it to the document. Code inside the script block will be run, however, so you need to rewrite your scripts in a manner that works standalone and also with the dynamic loading.


Here's a simple example that works in Chrome, Safari, and Firefox...but not IE9:

var xhr = new XMLHttpRequest;
xhr.open('get','stirling4.svg',true);
xhr.onreadystatechange = function(){
  if (xhr.readyState != 4) return;
  var svg = xhr.responseXML.documentElement;
  svg = document.importNode(svg,true); // surprisingly optional in these browsers
  document.body.appendChild(svg);
};
xhr.send();

See it in action here: http://phrogz.net/SVG/import_svg.xhtml


Unfortunately IE9 does not properly support document.importNode. To work around this, we write our own cloneToDoc function that creates an equivalent structure for any given node by recursively crawling the hierarchy. Here's a full working example:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head> 
  <meta http-equiv="content-type" content="application/xhtml+xml;charset=utf-8"/>
  <title>Fetch and Include SVG in XHTML</title>
  <script type="text/ecmascript"><![CDATA[
    setTimeout(function(){
      var xhr = new XMLHttpRequest;
      xhr.open('get','stirling4.svg',true);
      xhr.onreadystatechange = function(){
        if (xhr.readyState != 4) return;
        var svg = cloneToDoc(xhr.responseXML.documentElement);
        document.body.appendChild(svg);
      };
      xhr.send();
    },1000);
    function cloneToDoc(node,doc){
      if (!doc) doc=document;
      var clone = doc.createElementNS(node.namespaceURI,node.nodeName);
      for (var i=0,len=node.attributes.length;i<len;++i){
        var a = node.attributes[i];
        if (/^xmlns\b/.test(a.nodeName)) continue; // IE can't create these
        clone.setAttributeNS(a.namespaceURI,a.nodeName,a.nodeValue);
      }
      for (var i=0,len=node.childNodes.length;i<len;++i){
        var c = node.childNodes[i];
        clone.insertBefore(
          c.nodeType==1 ? cloneToDoc(c,doc) : doc.createTextNode(c.nodeValue),
          null
        ); }
      return clone;
    }
  ]]></script>
</head><body></body></html>

See it in action here: http://phrogz.net/SVG/import_svg_ie9.xhtml


Edit 2: As suspected, the problem is that the onload event does not fire when dynamically adding script. Here's a paired solution that works:

  1. Rewrite your script to remove the onload event handler. Instead, trust that document exists.
  2. Rewrite your script to ask for a global svgRoot; if it doesn't exist, use document.documentElement.
  3. When fetching the SVG set a global svgRoot to the new svg element after you import it into the document.

Here's the code in action:

And, in case my site is down, here is the code for posterity:

script-created.svg

<svg xmlns="http://www.w3.org/2000/svg">
  <script type="text/javascript"><![CDATA[
    function createOn( root, name, a ){
      var el = document.createElementNS(svgNS,name);
      for (var n in a) if (a.hasOwnProperty(n)) el.setAttribute(n,a[n]);
      return root.appendChild(el);
    }
    // Trust someone else for the root, in case we're being
    // imported into another document
    if (!window.svgRoot) svgRoot=document.documentElement;
    var svgNS = svgRoot.namespaceURI;
    createOn(svgRoot,'rect',{
      x:10, y:10, width:30, height:30,
      stroke:'#8080ff', "stroke-width":5,
      fill:"none"
    });
  ]]></script>
</svg>

import_svg_with_script.xhtml

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head> 
  <meta http-equiv="content-type"
        content="application/xhtml+xml;charset=utf-8" />
  <title>Fetch and Include Scripted SVG in XHTML</title>
  <script type="text/ecmascript"><![CDATA[
    setTimeout(function(){
      var xhr = new XMLHttpRequest;
      xhr.open('get','script-created.svg',true);
      xhr.onreadystatechange = function(){
        if (xhr.readyState != 4) return;
        var svg = xhr.responseXML.documentElement;
        svg = cloneToDoc(svg);
        window.svgRoot = svg; // For reference by scripts
        document.body.appendChild(svg);
        delete window.svgRoot;
      };
      xhr.send();
    },1000);
    function cloneToDoc(node,doc){
      if (!doc) doc=document;
      var clone = doc.createElementNS(node.namespaceURI,node.nodeName);
      for (var i=0,len=node.attributes.length;i<len;++i){
        var a = node.attributes[i];
        if (/^xmlns\b/.test(a.nodeName)) continue; // IE can't create these
        clone.setAttributeNS(a.namespaceURI,a.nodeName,a.nodeValue);
      }
      for (var i=0,len=node.childNodes.length;i<len;++i){
        var c = node.childNodes[i];
        clone.insertBefore(
          c.nodeType==1 ? cloneToDoc(c,doc) : doc.createTextNode(c.nodeValue),
          null
        )
      }
      return clone;
    }
  ]]></script>
</head><body></body></html>

How does GitHub to avoid lag / blink on page loading?

6 votes

When I navigate into my GitHub dashboard, It look like the page is not reloaded, but only the content which changed.

So my first thought was that it is a classic ajax trick, but when I change the content of the page (change header title via the google debugger for example) that is not supposed to be reloaded (as in the ajax hypothesis), and I click to a link, my change is reset, so this part of the page is reloaded as well, BUT it doesn't blink at all, so how do they do it?

https://github.com/defunkt/jquery-pjax will give you all of the magic, as a jQuery plugin