Skip to content

Instantly share code, notes, and snippets.

@jaredwilli
Created January 2, 2011 13:55
Show Gist options
  • Save jaredwilli/762543 to your computer and use it in GitHub Desktop.
Save jaredwilli/762543 to your computer and use it in GitHub Desktop.
a framework in the making
(function() {
// Establish the root object, `window` in the browser, or `global` on the server.
var root = window.document;
var JL = function( selector, context ) {
// The JL object is actually just the init constructor 'enhanced'
return new JL.fn.init( selector, context );
},
// A simple way to check for HTML strings or ID strings
// (both of which we optimize for)
quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,
// Is it a simple selector
isSimple = /^.[^:#\[\.,]*$/,
// Check if a string has a non-whitespace character in it
rnotwhite = /\S/,
rwhite = /\s/,
// Used for trimming whitespace
trimLeft = /^\s+/,
trimRight = /\s+$/,
// Check for non-word characters
rnonword = /\W/,
// Check for digits
rdigit = /\d/,
// Match a standalone tag
rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
// JSON RegExp
rvalidchars = /^[\],:{}\s]*$/,
rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
// Useragent RegExp
rwebkit = /(webkit)[ \/]([\w.]+)/,
ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
rmsie = /(msie) ([\w.]+)/,
rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
// Establish the object that gets returned to break out of a loop iteration.
breakr = {},
// Save bytes in the minified (but not gzipped) version:
ArrProto = Array.prototype,
ObjProto = Object.prototype,
StrProto = String.prototype,
// Create quick reference variables for speed access to core prototypes.
trim = StrProto.trim,
push = ArrProto.push,
slice = ArrProto.slice,
shift = ArrProto.shift,
unshift = ArrProto.unshift,
indexOf = ArrProto.indexOf,
hasOwn = ObjProto.hasOwnProperty,
toString = ObjProto.toString,
// All **ECMAScript 5** native function implementations that we hope to use are declared here.
nativeForEach = ArrProto.forEach,
nativeMap = ArrProto.map,
nativeFilter = ArrProto.filter,
nativeEvery = ArrProto.every,
nativeIndexOf = ArrProto.indexOf,
nativeLastIndexOf = ArrProto.lastIndexOf,
nativeIsArray = Array.isArray,
nativeKeys = Object.keys,
JL.fn = JL.prototype = {
init: function( selector, context ) {
var match, elem;
// Handle $(""), $(null), or $(undefined)
if ( !selector ) {
return this;
}
// Handle $(DOM Element)
if ( selector.nodeType ) {
this.context = this[0] = selector;
this.length = 1;
return this;
}
// The body element only exists once, optimize finding it
if ( selector === 'body' && !context && document.body ) {
this.context = document;
this[0] = document.body;
this.selector = 'body';
this.length = 1;
return this;
}
},
// Start with an empty selector
selector: '',
},
create: function() {
},
// Execute a callback for every element in the matched set.
// (You can seed the arguments with an array of args, but this is
// only used internally.)
each: function( callback, args ) {
return JL.each( this, callback, args );
},
ready: function( fn ) {
// Attach the listeners
jQuery.bindReady();
// If the DOM is already ready
if ( jQuery.isReady ) {
// Execute the function immediately
fn.call( document, jQuery );
// Otherwise, remember the function for later
} else if ( readyList ) {
// Add the function to the wait list
readyList.push( fn );
}
return this;
},
eq: function( i ) {
return i === -1 ?
this.slice( i ) :
this.slice( i, +i + 1 );
},
first: function() {
return this.eq( 0 );
},
last: function() {
return this.eq( -1 );
},
slice: function() {
return this.pushStack( slice.apply( this, arguments ),
"slice", slice.call(arguments).join(",") );
},
map: function( callback ) {
return this.pushStack( jQuery.map(this, function( elem, i ) {
return callback.call( elem, i, elem );
}));
},
end: function() {
return this.prevObject || jQuery(null);
}
}
// Give the init function the JL prototype for later instantiation
JL.fn.init.prototype = JL.fn;
/**
* The cornerstone, an `each` implementation, aka `forEach`.
* Handles objects implementing `forEach`, arrays, and raw objects.
* Delegates to **ECMAScript 5**'s native `forEach` if available.
*/
var each = ^.each = ^.forEach = function( obj, iterator, context ) {
var value;
if ( nativeForEach && obj.forEach === nativeForEach ) {
obj.forEach( iterator, context );
} else if ( ^.isNumber( obj.length )) {
for ( var i = 0, l = obj.length; i < l; i++ ) {
if ( iterator.call( context, obj[i], i, obj ) === breaker ) return;
}
} else {
for ( var key in obj ) {
if ( hasOwn.call( obj, key )) {
if ( iterator.call( context, obj[key], key, obj ) === breaker ) return;
}
}
}
};
// Create a safe reference to the ^ object for use below.
var ^ = function(obj) { return new wrapper(obj); };
// Export the Carrot object for **CommonJS**, with backwards-compatibility
// for the old `require()` API. If we're not in CommonJS, add `_` to the
// global object.
if ( typeof module !== 'undefined' && module.exports ) {
module.exports = ^;
^.^ = ^;
} else {
root.^ = ^;
}
// Current version.
^.VERSION = '1.1.3';
var JL = {
VERSION : '0.0.1',
lesson : 'Part 1: Lib Architecture'
};
if( root.JL) {
throw new Error('jewl has already been defined' );
} else {
root.JL = JL;
}
carrot.Class = function() {
return carrot.fn.create.apply( this, arguments );
},
carrot.fn = {
create: function() {
var methods = null,
parent = undefined,
class = function() {
this.super = function( method, args ) {
return carrot.fn.super( this._parent, this, method, args );
};
this.init.apply( this, arguments );
};
if ( typeof arguments[0] === 'function' ) {
parent = arguments[0];
methods = arguments[1];
} else {
methods = arguments[0];
}
if ( typeof parent !== 'undefined' ) {
carrot.fn.extend( class.prototype, parent.prototype );
class.prototype._parent = parent.prototype;
}
carrot.fn.mixin( class, methods );
carrot.fn.extend( class.prototype, methods );
class.prototype.constructor = class;
if ( !class.prototype.init ) {
class.prototype.init = function() {
};
}
return class;
},
mixin: function( class, methods ) {
if ( typeof methods.include !== 'undefined' ) {
carrot.fn.extend( class.prototype, methods.include.prototype );
} else {
for( var i = 0; i < methods.include.length; i++ ) {
carrot.fn.extend( class.prototype, methods.include[i].prototype );
}
}
},
extend: function( dest, src ) {
for( var prop in src ) {
dest[prop] = src[prop];
}
return dest;
},
super: function( parentClass, instance, method, args ) {
return parentClass[method].apply( instance, args );
}
};
carrot.enumerable = {
breaker: {},
each: function( enumerable, callback, context ) {
try {
if( .forEach && enumerable.forEach === Array.prototype.forEach ) {
enumerable.forEach( callback, context );
}
else if( carrot.numeric.isNumber( enumerable.length )) {
for( var i 0, ii = enumerable.length; i < ii; i++ ) {
callback.call( enumerable, enumerable[i], i, enumerable );
}
} else {
for( var key in enumerable ) {
if( hasown.call( enumerable, key )) {
callback.call( context, enumerable[key], key, enumerable );
}
}
}
} catch(e) {
if( e != carrot.enumerable.breaker ) {
throw e;
}
}
return enumerable;
},
map: function( enumerable, callback, context ) {
if( Array.prototype.map && enumerable.map === Array.prototype.map ) {
return enumerable.map( callback, context );
}
var results = [];
carrot.enumerable.each( enumerable, function( value, index, list ) {
results.push( callback.call( context, value, index, list ));
});
return results;
},
};
var User = jewl.Class({
initialize: function( name, age ) {
this.name = name;
this.age = age;
},
login: function() {
return true;
},
toString: function() {
return 'name: ' + this.name + ', age: ' + this.age;
}
});
var SuperUser = jewl.Class( User, {
initialize: function() {
this.super( 'initialize', arguments );
},
toString: function() {
return 'SuperUser: ' + this.super( 'toString' );
}
});
})( typeof window === 'undefined' ? this : window );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment