Skip to content

Instantly share code, notes, and snippets.

@ergoithz
Last active August 29, 2015 13:56
Show Gist options
  • Save ergoithz/9112265 to your computer and use it in GitHub Desktop.
Save ergoithz/9112265 to your computer and use it in GitHub Desktop.
Micro AJAX snipped with hashbang urls (for browser history) with zero dependencies. Converts every link with 'ajax' class into a ajax link (for gracefully degrading) and only loads data from selected tags (section#content or body) into #content (for ajax using static files).
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Example</title>
<script src="uajax.js"></script>
</head>
<body>
<nav>
<ul>
<li><a class="ajax" href="index.html">Index</a></li>
<li><a class="ajax" href="test1.html">Test1</a></li>
<li><a class="ajax" href="test2.html">Test2</a></li>
</ul>
</nav>
<section id="content">
<p>Index page</p>
</section>
<script>window.uajax.start();</script>
</body>
</html>
window.uajax={};
window.uajax.start=function(){
var links=document.getElementsByTagName("a"), curhash="#!/", baseurl,
findmany=function(str, subs, many){
// Return all or given 'many' positions of substring in string
var s=0, r=[], l=str.length, m=many||l, p;
while((m--)&&(s<l)){
p=str.substring(s).search(subs);
if(p==-1) break;
r.push((s+=p+1)-1);
}
return r;
},
firstof=function(str, alternatives){
// Return first element of alternatives found in string
var minpos=str.length, minchar=0, pos;
for(var i=0,l=alternatives.length;i<l;i++){
pos=str.search(alternatives[i]);
if((-1<pos)&&(pos<minpos)){
minpos=pos;
minchar=i;
}
}
return minchar;
},
subpart=function(str, chr){
// Substr with character instead of index
return str.substr(str.search(chr)+chr.length);
},
tagcontent=function(obj, tagname, id){
// Return content of tag in xml string
var starts=findmany(obj, "<"+tagname),
endings=findmany(obj, "</"+tagname),
salts=[" id=\""+(id||"")+"\"", ">"],
pos=id?null:0, epos;
if(id) // Move pos to start with given id
for(var i=0,l=starts.length;i<l;i++)
if(firstof(obj.substr(starts[i]), salts)==0){
pos=i;
break;
}
if(pos===null) return "";
// Find matching ending
console.log([starts, endings]);
for(var i=0,l=Math.min(starts.length-pos,endings.length);i<l;i++)
if(starts[pos+i]>endings[i]) break;
epos=(pos+i<starts.length)?undefined:(endings[i-1]-starts[pos]);
return subpart(obj.substr(starts[pos],epos), ">");
}
ajaxcback=function(ajax){
// Ajax callback
var data="", r=unescape(ajax.responseText);
if (ajax.readyState==4)
data = tagcontent(r, "section", "content") || tagcontent(r, "body");
else{
if(ajax.readyState==404) data="Not found.";
else data="XMLHttpRequest:"+ajax.readyState.toString();
}
document.getElementById("content").innerHTML = data;
},
addevent=function(el, evt, cback){
// Crossbrowser add event
if(el.addEventListener)
el.addEventListener(evt, cback, false);
else if(el.attachEvent)
el.attachEvent('on'+evt, cback);
},
clickevent=function(evt){
// Click callback
var e=evt||window.event;
ajaxload(this.href);
e.cancelBubble=true;
if(e.preventDefault) e.preventDefault();
if(e.stopPropagation) e.stopPropagation();
},
ajaxload=function(loc){
// Load url using ajax
var xhr=null;
if(XMLHttpRequest) xhr=new XMLHttpRequest();
else if(ActiveXObject)
try{xhr=new ActiveXObject("Msxml2.XMLHTTP");}
catch(e3){
try{xhr=new ActiveXObject("Microsoft.XMLHTTP");}
catch(e2){}
}
loc=loc.replace(baseurl, "/");
if(loc=="/"){
document.location.hash="";
curhash="#!/";
}else document.location.hash=curhash="#!"+loc;
try{
xhr.open("GET", loc.substr(1), true);
xhr.onreadystatechange=function(){ajaxcback(xhr);};
xhr.send(null);
}catch(e){console.log(e);};
},
checkhash=function(){
// Check if current shebang does not match
var h=(document.location.hash||"#!/");
if((h.substr(0,3)=="#!/")&&(h!=curhash))
ajaxload(h.substr(2));
};
baseurl=""+document.location.href;
baseurl=baseurl.substr(0, baseurl.length-document.location.hash.length); // remove hash
baseurl=baseurl.substr(0, baseurl.lastIndexOf("/")+1); // remove last part
// Attach click event on ajax links
for(var i=0,l=links.length;i<l;i++)
if((links[i].href)&&(links[i].className.indexOf("ajax")>-1))
addevent(links[i], "click", clickevent);
// Check hash changes (history)
setInterval(checkhash, 500);
checkhash();
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment