Clib – a basic javascript library
December 17, 2009
Comments off
Notice: This class is subject to change.
/**
* Clib - a basic javascript library
*
* @author Costin Trifan
* @copyright 2009 Costin Trifan
* @licence MIT License http://en.wikipedia.org/wiki/MIT_License
* @version 1.0
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
============================================================*/
/**
* PROTOTYPES
*
* @see $().ajax()
*/
if ( ! Array.prototype.inArray )
{
Array.prototype.inArray = function ( theArray ) {
var i;
for (i=0; i < this.length; i++) {
if (this[i] === theArray) {
return true;
}
}
return false;
};
}
/**
* Clib library - Simple Ajax/Dom/Events/Cookie library
*
*/
(function()
{
/******************************
* AJAX RELATED
******************************/
var xhr = null; /*[ will hold the instance of the XmlHttp object ]*/
var _createRequest = function()
{
try { return new XMLHttpRequest ; } catch(e) {}
try { return new ActiveXObject('MSXML2.XMLHTTP.3.0') ; } catch(e) {}
try { return new ActiveXObject('MSXML2.XMLHTTP') ; } catch(e) {}
try { return new ActiveXObject('Microsoft.XMLHTTP') ; } catch(e) { throw new Error("Details: AJAX is not supported!"); }
};
/**
* Create an image loader
* @return object the created DOM Element
*/
var _createImageLoader = function( imgSrc, parentCtl, loadingText )
{
var el = document.createElement("img");
with (el)
{
setAttribute("src", imgSrc);
setAttribute("title", loadingText);
setAttribute("alt", loadingText);
style.width = 'auto';
style.height = 'auto';
style.display = 'block';
}
parentCtl.appendChild(el);
return el;
};
/*>> End AJAX related stuff *******************************************************************************/
/**
* Populate the this.elements array
* @access private
*/
function _$( els )
{
this.elements = [];
for (var i= 0; i < els.length; ++i)
{
var e = els[i];
if (typeof(e) === "string") {
e = document.getElementById(e);
}
this.elements.push(e);
}
}
_$.prototype =
{
/*==============================
* UTILITY
==============================*/
/**
* Check to see whether the provided object is an array
* @return bool
*/
isArray : function ( obj )
{
return (obj.constructor.toString().indexOf("Array") >= 0 );
},
/**
* Execute a given function for each of the elements from the this.elements array
* @return this
*/
each : function( fn )
{
if (this.elements.length == 0) { return this; }
for (var i= 0; i < this.elements.length; ++i)
{
fn.call(this, this.elements[i]);
}
return this;
},
/*==============================
* COOKIE
==============================*/
/*[ Source: http://www.dustindiaz.com/top-ten-javascript/ ]*/
getCookie : function( name )
{
var start = document.cookie.indexOf( name + "=" );
var len = start + name.length + 1;
if ( ( !start ) && ( name != document.cookie.substring( 0, name.length ) ) ) {
return null;
}
if ( start == -1 ) return null;
var end = document.cookie.indexOf( ';', len );
if ( end == -1 ) { end = document.cookie.length; }
return unescape( document.cookie.substring( len, end ) );
},
setCookie : function( name, value, expires, path, domain, secure )
{
var today = new Date();
today.setTime( today.getTime() );
if ( expires ) { expires = expires * 1000 * 60 * 60 * 24; }
var expires_date = new Date( today.getTime() + (expires) );
document.cookie = name+'='+escape( value )
+ ( expires ? ';expires='+expires_date.toGMTString() : '' )
+ ( path ? ';path=' + path : '' )
+ ( domain ? ';domain=' + domain : '' )
+ ( secure ? ';secure' : '' );
},
deleteCookie : function( name, path, domain )
{
if ( this.getCookie( name ) )
{
document.cookie = name + '=' +
( (path) ? ';path=' + path : '') +
( (domain) ? ';domain=' + domain : '' ) +
';expires=Thu, 01-Jan-1970 00:00:01 GMT';
}
},
/*==============================
* EVENTS
==============================*/
/**
* Attach an event listener to each of the elements from the this.elements array
* @return this
*/
on : function( type, fn )
{
var _add = function( el )
{
if (window.addEventListener) {
el.addEventListener(type, fn, false);
}
else if (window.attachEvent) {
el.attachEvent("on"+type, fn);
}
};
this.each(function(el) { _add(el); });
return this;
},
/**
* Remove an event listener from each of the elements of the this.elements array
* @return this
*/
removeEvent : function( type, fn )
{
var _remove = function( el )
{
if (window.removeEventListener) {
el.removeEventListener(type, fn, false);
}
else if (window.detachEvent) {
el.detachEvent("on"+type, fn);
}
};
this.each(function(el) { _remove(el); });
return this;
},
/**
* Prevent the default action from occurring
* @return this
*/
preventDefault : function( ev )
{
ev = ev || window.event;
if (ev.preventDefault) {
ev.preventDefault();
}
else {
ev.returnValue = false;
}
return this;
},
/**
* Stop the propagation of the event
* @return this
*/
stopPropagation : function( ev )
{
ev = ev || window.event;
if (ev.stopPropagation) {
ev.stopPropagation();
}
else {
ev.cancelBubble = true;
}
return this;
},
/**
* Prevent the default action from occurring
* @return this
*/
stopEvent : function( ev )
{
this.preventDefault( ev );
this.stopPropagation( ev );
return this;
},
/*==============================
* DOM
==============================*/
/**
* Check to see whether or not a given element has a class applied
* @return bool
*/
hasClass : function( cssClass )
{
var pattern = new RegExp("(^| )" +cssClass+ "( |$)");
this.each(function(el) {
if (pattern.test(el.className)) { return true; }
});
return false;
},
/**
* Remove a class from the selected objects
* @return this
*/
removeClass : function( cssClass )
{
var pattern = new RegExp("(^| )" +cssClass+ "( |$)");
this.each(function(el) {
el.className = el.className.replace(pattern, "$1");
el.className = el.className.replace(/ $/, "");
});
return this;
},
/**
* Add a given class to selected elements
* @return this
*/
addClass : function( cssClass )
{
var self = this;
this.each(function(el) {
if ( ! self.hasClass(cssClass))
{
if (el.className == "") { el.className = cssClass; }
else { el.className += " " + cssClass; }
}
});
return this;
},
/**
* Replace all elements from the this.elements array with the ones that match the regex pattern
* @return this
*/
getByClass : function( searchClass, parent, searchInTag )
{
// reset main array
this.elements = [];
if ( parent == null ) {
parent = document;
}
if ( searchInTag == null ) {
searchInTag = '*';
}
var els = parent.getElementsByTagName(searchInTag);
var elsLen = els.length;
var pattern = new RegExp('(^|\\\\s)'+searchClass+'(\\\\s|$)');
for (i = 0, j = 0; i < elsLen; i++)
{
if ( pattern.test(els[i].className) )
{
this.elements.push( els[i] );
j++;
}
}
return this;
},
/**
* Replace all elements from the this.elements array with the ones that match the regex pattern
* @return this
*/
getByTags : function( /*[ as Array ]*/searchTags, /*[ as Object ]*/parent )
{
if ( ! this.isArray(searchTags)) {
throw new Error("The getByTags function expects the first argument to be an Array!");
}
if (searchTags.length == 0) { return this; }
// temp array - holds the elements that match the regex
var tempArr = [];
// reset main array
this.elements = [];
if ( parent == null ) { parent = document; }
for (var i= 0; i < searchTags.length; ++i)
{
var tag = searchTags[i];
var els = parent.getElementsByTagName(tag);
}
var elsLen = els.length;
var pattern = new RegExp('(^|\\\\s)'+searchClass+'(\\\\s|$)');
for (i = 0, j = 0; i < elsLen; i++)
{
if ( pattern.test(els[i].className) )
{
this.elements.push( els[i] );
j++;
}
}
return this;
},
/**
* Set the inner text to all of the elements from this.elements array
* @return this
*/
text : function( txt )
{
/*[ SET ]*/
if (txt)
{
this.each(function(e) {
e.innerHTML = txt;
});
return this;
}
/*[ GET ]*/
else { return this.elements[0].innerHTML; }
},
/**
* Set/Get the value to all of the elements from this.elements array
* @return this | mixed
*/
value : function( txt )
{
/*[ SET ]*/
if (txt)
{
this.each(function(e) {
e.value = txt;
});
return this;
}
/*[ GET ]*/
else { return this.elements[0].value; }
},
/**
* Set the css style property to all of the elements from this.elements array
*
* @param object properties A key value pair object literal with the properties and values to apply to the selected object
* @return this
*/
css : function( /*[ as object ]*/properties )
{
this.each(function(el) {
for (var p in properties)
el.style[ p ] = properties[ p ];
});
return this;
},
/**
* Set the css style property to an element
* @return this
*/
setStyle : function( element, property, value )
{
element.style[ property ] = value;
return this;
},
/**
* Retrieve the computed style attribute of the element
* @return string
*/
getStyle : function( element, property )
{
var comp_style = null;
if (window.getComputedStyle) {
comp_style = window.getComputedStyle(element,null).getPropertyValue(property);
}
else {
if (typeof(element) != "undefined") {
comp_style = element.currentStyle;
return comp_style[property];
}
}
return comp_style;
},
/*==============================
* AJAX
==============================*/
/**
* Abort the active request
* @return this
*/
_abort : function( xhr )
{
xhr.abort();
xhr = null;
return this;
},
ajax : function( method, uri, /*[ as object ]*/options, onSuccess, onFailure )
{
method = method.toUpperCase();
var self = this;
/*[ Check and validate method ]*/
var allow_methods = ["GET", "HEAD", "POST"];
if ( ! allow_methods.inArray(method)) {
throw new Error("The provided method: "+ method.toString() +" is not supported!");
}
xhr = _createRequest();
if (xhr == null) { return this; }
if ( ! options ) { options = {}; }
/*[ Set options ]
options = {
async : false | true (default)
timeout : null | 3000 (default)
postData : string | null (default) // when making POST requests
label : string | null (default) // when making HEAD requests
cache : true | false (default) // when making GET requests, whether or not to cache server's response
showLoader : true | false (default)
imgSrc : string | null (default) // the path to the image to be displayed
parentCtl : DOMElement | null (default) // the element that will append the image loader
loadingText : 'Loading...' (default) // the alternate text for the image loader
}
*/
if ( options.async == null ) { options.async = true; }
if ( ! options.timeout ) { options.timeout = 3000; }
if ( ! options.postData ) { options.postData = null; }
if ( ! options.label ) { options.label = null; }
if ( ! options.cache ) { options.cache = false; }
if ( ! options.showLoader ) { options.showLoader = false; }
if ( ! options.imgSrc ) { options.imgSrc = null; }
if ( ! options.parentCtl ) { options.parentCtl = null; }
if ( ! options.loadingText ) { options.loadingText = "Loading..."; }
/*[ Create the ajax loader ]*/
var img_loader = null;
if (options.showLoader)
{
/*[ Clear content first ]*/
options.parentCtl.innerHTML = '';
img_loader = _createImageLoader(options.imgSrc, options.parentCtl, options.loadingText);
}
/*[ Set timeout ]*/
var _timer = setTimeout(function() { self._abort(xhr); }, options.timeout);
/*[ Handle the state of the request ]*/
xhr.onreadystatechange = function()
{
if (xhr.readyState == 4)
{
/*[ Clear timeout ]*/
clearTimeout(_timer);
if (xhr.status == 200 || xhr.status == 304)
{
/*[ Clear the loading image ]*/
if (img_loader != null) { options.parentCtl.removeChild(img_loader); }
/*[ Retrieve response ]*/
if (method == "HEAD")
{
/*[ If a header label was provided ]*/
if (options.label) {
onSuccess( xhr.getResponseHeader(options.label) );
}
else {
onSuccess( xhr.getAllResponseHeaders() );
}
}
/*[ Common GET request ]*/
else { onSuccess( xhr.responseText, xhr.responseXML ); }
}
else {
/*[ Clear the loading image ]*/
if (img_loader != null)
{
try { options.parentCtl.removeChild(img_loader); }
catch(e){}
}
if (onFailure) { onFailure(xhr.statusText); self._abort(xhr); }
else {
/*[ Default error message ]*/
throw new Error("An error has occurred while executing the request.\r\nStatus: "+xhr.statusText);
}
}
}
};
if ( ! options.cache)
{
var rand_no = Math.ceil(1000*Math.random());
if (uri.indexOf('?') >= 0) {
uri += "&xyxz_rand="+rand_no;
}
else { uri += "?xyxz_rand="+rand_no; }
}
xhr.open(method, uri, options.async);
if (method == "POST")
{
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
if (options.postData) {
if (options.postData.indexOf("?") < 0) {
options.postData = "?" + options.postData;
}
}
}
xhr.send(options.postData);
return this;
}
};
/*[ end _$.prototype ]*/
/**
* Map the $ object to the library's main function
* return object
*/
window.Clib = window.$ = function() {
return new _$(arguments);
};
})();
Usage:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Clib - a basic javascript library</title>
<script type="text/javascript" src="bin/c-lib.js"></script>
<script type="text/javascript">
// Clib == $
Clib(window).on('load', function(event)
{
/*[ AJAX - GET ]*/
Clib("call_server_button").on('click', function(ev)
{
// $().stopEvent(ev); /*[ if the default action should be prevented ]*/
Clib().ajax("GET", "app_code/server.php?myname="+$('name_textbox').value(),
/*[ OPTIONS ]*/
{
"cache" : false,
"showLoader" : true,
"imgSrc" : 'bin/ajax-loader.gif',
"parentCtl" : document.getElementById('container')
},
/*[ ON SUCCESS ]*/
function(txt, xml) {
Clib("container").css({"background":"#f00", 'color':'#ff0'}).text(txt);
}
);
});
/*[ end ajax - get ]*/
});
</script>
</head>
<body>
<h2>Ajax library</h2>
<div>
<input type="text" id="name_textbox" />
<input type="button" id="call_server_button" value="Call server" />
</div>
<div id="container" style="margin: 25px; width: 400px;"></div>
</body>
</html>
Categories: JavaScript
ajax, JavaScript
Recent Comments