UNPKG

todomvc

Version:

> Helping you select an MV\* framework

399 lines (364 loc) 9.8 kB
/*! * CanJS - 2.0.3 * http://canjs.us/ * Copyright (c) 2013 Bitovi * Tue, 26 Nov 2013 18:21:22 GMT * Licensed MIT * Includes: CanJS default build * Download from: http://canjs.us/ */ define(["can/util/can", "mootools", "can/util/event", "can/util/fragment", "can/util/deferred", "can/util/array/each", "can/util/object/isplain", "can/util/inserted"], function(can) { // mootools.js // --------- // _MooTools node list._ // // Map string helpers. can.trim = function(s){ return s && s.trim() } // This extend() function is ruthlessly and shamelessly stolen from // jQuery 1.8.2:, lines 291-353. var extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; // skip the boolean and the target i = 2; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !can.isFunction(target) ) { target = {}; } // extend jQuery itself if only one argument is passed if ( length === i ) { target = this; --i; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( (options = arguments[ i ]) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { continue; } // Recurse if we're merging plain objects or arrays if ( deep && copy && ( can.isPlainObject(copy) || (copyIsArray = can.isArray(copy)) ) ) { if ( copyIsArray ) { copyIsArray = false; clone = src && can.isArray(src) ? src : []; } else { clone = src && can.isPlainObject(src) ? src : {}; } // Never move original objects, clone them target[ name ] = can.extend( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; }; can.extend = extend; // Map array helpers. can.makeArray = function(item) { // All other libraries return a copy if item is an array. // The original Mootools Array.from returned the same item so we need to slightly modify it if (item == null) return []; try { return (Type.isEnumerable(item) && typeof item != 'string') ? Array.prototype.slice.call(item) : [item]; } catch(ex) { // some things like DOMNodeChildCollections don't slice so good. // This pains me, but it has to be done. var arr = [], i; for( i = 0; i < item.length; ++i) { arr.push(item[i]); } return arr; } } can.isArray = function(arr) { return typeOf(arr) === 'array' }; can.inArray = function(item,arr,fromIndex) { if(!arr) { return -1; } return Array.prototype.indexOf.call(arr, item, fromIndex); } can.map = function(arr, fn){ return Array.from(arr||[]).map(fn); } // Map object helpers. can.param = function(object){ return Object.toQueryString(object) } can.isEmptyObject = function(object){ return Object.keys(object).length === 0; } // Map function helpers. can.proxy = function(func){ var args = can.makeArray(arguments), func = args.shift(); return func.bind.apply(func, args) } can.isFunction = function(f){ return typeOf(f) == 'function' } // Make this object so you can bind on it. can.bind = function( ev, cb){ // If we can bind to it... if(this.bind && this.bind !== can.bind){ this.bind(ev, cb) } else if(this.addEvent) { this.addEvent(ev, cb); } else if(this.nodeName && this.nodeType == 1) { $(this).addEvent(ev, cb) } else { // Make it bind-able... can.addEvent.call(this, ev, cb) } return this; } can.unbind = function(ev, cb){ // If we can bind to it... if(this.unbind && this.unbind !== can.unbind){ this.unbind(ev, cb) } else if(this.removeEvent) { this.removeEvent(ev, cb) } if(this.nodeName && this.nodeType == 1) { $(this).removeEvent(ev, cb) } else { // Make it bind-able... can.removeEvent.call(this, ev, cb) } return this; } // Alias on/off to bind/unbind respectively can.on = can.bind; can.off = can.unbind; can.trigger = function(item, event, args, bubble){ // Defaults to `true`. bubble = (bubble === undefined ? true : bubble); args = args || []; var propagating = true; if(item.fireEvent){ item = item[0] || item; // walk up parents to simulate bubbling . while(item && propagating) { // Handle walking yourself. if(!event.type){ event = { type : event, target : item, stopPropagation: function(){ propagating = false; } } } var events = (item !== window ? can.$(item).retrieve('events')[0] : item.retrieve('events') ); if (events && events[event.type]) { events[event.type].keys.each(function(fn){ fn.apply(item, [event].concat(args)); }, this); } // If we are bubbling, get parent node. if(bubble && item.parentNode && item.parentNode.nodeType != 11){ item = item.parentNode } else { item = null; } } } else { if(typeof event === 'string'){ event = {type: event} } event.target = event.target || item; can.dispatch.call(item, event, args) } } can.delegate = function(selector, ev , cb){ if(this.delegate) { this.delegate(selector, ev , cb) } else if(this.addEvent) { this.addEvent(ev+":relay("+selector+")", cb) } else { // make it bind-able ... } return this; } can.undelegate = function(selector, ev , cb){ if(this.undelegate) { this.undelegate(selector, ev , cb) } else if(this.removeEvent) { this.removeEvent(ev+":relay("+selector+")", cb) } else { // make it bind-able ... } return this; } var optionsMap = { type:"method", success : undefined, error: undefined } var updateDeferred = function(xhr, d){ for(var prop in xhr){ if(typeof d[prop] == 'function'){ d[prop] = function(){ xhr[prop].apply(xhr, arguments) } } else { d[prop] = prop[xhr] } } } can.ajax = function(options){ var d = can.Deferred(), requestOptions = can.extend({}, options), request; // Map jQuery options to MooTools options. for(var option in optionsMap){ if(requestOptions[option] !== undefined){ requestOptions[optionsMap[option]] = requestOptions[option]; delete requestOptions[option] } } // Mootools defaults to 'post', but Can expects a default of 'get' requestOptions.method = requestOptions.method || 'get'; requestOptions.url = requestOptions.url.toString(); var success = options.onSuccess || options.success, error = options.onFailure || options.error; requestOptions.onSuccess = function(response, xml){ var data = response; updateDeferred(request.xhr, d); d.resolve(data,"success",request.xhr); success && success(data,"success",request.xhr); } requestOptions.onFailure = function(){ updateDeferred(request.xhr, d); d.reject(request.xhr,"error"); error && error(request.xhr,"error"); } if(options.dataType ==='json'){ request = new Request.JSON(requestOptions); } else { request = new Request(requestOptions); } request.send(); updateDeferred(request.xhr, d); return d; } // Element -- get the wrapped helper. can.$ = function(selector){ if(selector === window){ return window; } return $$(selector) } // Add `document` fragment support. var old = document.id; document.id = function(el){ if(el && el.nodeType === 11){ return el } else{ return old.apply(document, arguments); } }; can.append = function(wrapped, html){ if(typeof html === 'string'){ html = can.buildFragment(html) } return wrapped.grab(html) } can.filter = function(wrapped, filter){ return wrapped.filter(filter); } can.data = function(wrapped, key, value){ if(value === undefined){ return wrapped[0].retrieve(key) } else { return wrapped.store(key, value) } } can.addClass = function(wrapped, className){ return wrapped.addClass(className); } can.remove = function(wrapped){ // We need to remove text nodes ourselves. var filtered = wrapped.filter(function(node){ if(node.nodeType !== 1){ node.parentNode.removeChild(node); } else { return true; } }) filtered.destroy(); return filtered; } can.has = function(wrapped, element){ // this way work in mootools if( Slick.contains(wrapped[0], element) ){ return wrapped } else { return [] } } // Destroyed method. var destroy = Element.prototype.destroy, grab = Element.prototype.grab; Element.implement({ destroy : function(){ can.trigger(this,"removed",[],false) var elems = this.getElementsByTagName("*"); for ( var i = 0, elem; (elem = elems[i]) !== undefined; i++ ) { can.trigger(elem,"removed",[],false); } destroy.apply(this, arguments) }, grab: function(el){ var elems; if(el && el.nodeType === 11){ elems = can.makeArray(el.childNodes); } else { elems = [el] } var ret = grab.apply(this,arguments); can.inserted( elems ); return ret; } }); can.get = function(wrapped, index){ return wrapped[index]; } // Overwrite to handle IE not having an id. // IE barfs if text node. var idOf = Slick.uidOf; Slick.uidOf = function(node){ // for some reason, in IE8, node will be the window but not equal it. if(node.nodeType === 1 || node === window || node.document === document ) { return idOf(node); } else { return Math.random(); } } Element.NativeEvents["hashchange"] = 2; return can; });