/*
* NinjaScript - 0.9 * written by and copyright 2010-2011 Judson Lester and Logical Reality Design * Licensed under the MIT license * * 06-29-2011 */
/** vim: et:ts=4:sw=4:sts=4
* @license RequireJS 0.24.0 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. * Available via the MIT or new BSD license. * see: http://github.com/jrburke/requirejs for details */
/*jslint strict: false, plusplus: false */ /*global window: false, navigator: false, document: false, importScripts: false,
jQuery: false, clearInterval: false, setInterval: false, self: false, setTimeout: false, opera: false */
var require, define; (function () {
//Change this version number for each release. var version = "0.24.0", commentRegExp = /(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg, cjsRequireRegExp = /require\(["']([^'"\s]+)["']\)/g, currDirRegExp = /^\.\//, jsSuffixRegExp = /\.js$/, ostring = Object.prototype.toString, ap = Array.prototype, aps = ap.slice, apsp = ap.splice, isBrowser = !!(typeof window !== "undefined" && navigator && document), isWebWorker = !isBrowser && typeof importScripts !== "undefined", //PS3 indicates loaded and complete, but need to wait for complete //specifically. Sequence is "loading", "loaded", execution, // then "complete". The UA check is unfortunate, but not sure how //to feature test w/o causing perf issues. readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ? /^complete$/ : /^(complete|loaded)$/, defContextName = "_", //Oh the tragedy, detecting opera. See the usage of isOpera for reason. isOpera = typeof opera !== "undefined" && opera.toString() === "[object Opera]", reqWaitIdPrefix = "_r@@", empty = {}, contexts = {}, globalDefQueue = [], interactiveScript = null, isDone = false, useInteractive = false, req, cfg = {}, currentlyAddingScript, s, head, baseElement, scripts, script, src, subPath, mainScript, dataMain, i, scrollIntervalId, setReadyState, ctx; function isFunction(it) { return ostring.call(it) === "[object Function]"; } function isArray(it) { return ostring.call(it) === "[object Array]"; } /** * Simple function to mix in properties from source into target, * but only if target does not already have a property of the same name. * This is not robust in IE for transferring methods that match * Object.prototype names, but the uses of mixin here seem unlikely to * trigger a problem related to that. */ function mixin(target, source, force) { for (var prop in source) { if (!(prop in empty) && (!(prop in target) || force)) { target[prop] = source[prop]; } } return req; } /** * Used to set up package paths from a packagePaths or packages config object. * @param {Object} pkgs the object to store the new package config * @param {Array} currentPackages an array of packages to configure * @param {String} [dir] a prefix dir to use. */ function configurePackageDir(pkgs, currentPackages, dir) { var i, location, pkgObj; for (i = 0; (pkgObj = currentPackages[i]); i++) { pkgObj = typeof pkgObj === "string" ? { name: pkgObj } : pkgObj; location = pkgObj.location; //Add dir to the path, but avoid paths that start with a slash //or have a colon (indicates a protocol) if (dir && (!location || (location.indexOf("/") !== 0 && location.indexOf(":") === -1))) { location = dir + "/" + (location || pkgObj.name); } //Create a brand new object on pkgs, since currentPackages can //be passed in again, and config.pkgs is the internal transformed //state for all package configs. pkgs[pkgObj.name] = { name: pkgObj.name, location: location || pkgObj.name, lib: pkgObj.lib || "lib", //Remove leading dot in main, so main paths are normalized, //and remove any trailing .js, since different package //envs have different conventions: some use a module name, //some use a file name. main: (pkgObj.main || "lib/main") .replace(currDirRegExp, '') .replace(jsSuffixRegExp, '') }; } } //Check for an existing version of require. If so, then exit out. Only allow //one version of require to be active in a page. However, allow for a require //config object, just exit quickly if require is an actual function. if (typeof require !== "undefined") { if (isFunction(require)) { return; } else { //assume it is a config object. cfg = require; } } /** * Creates a new context for use in require and define calls. * Handle most of the heavy lifting. Do not want to use an object * with prototype here to avoid using "this" in require, in case it * needs to be used in more super secure envs that do not want this. * Also there should not be that many contexts in the page. Usually just * one for the default context, but could be extra for multiversion cases * or if a package needs a special context for a dependency that conflicts * with the standard context. */ function newContext(contextName) { var context, resume, config = { waitSeconds: 7, baseUrl: s.baseUrl || "./", paths: {}, pkgs: {} }, defQueue = [], specified = { "require": true, "exports": true, "module": true }, urlMap = {}, defined = {}, loaded = {}, waiting = {}, waitAry = [], waitIdCounter = 0, managerCallbacks = {}, plugins = {}, pluginsQueue = {}, resumeDepth = 0, normalizedWaiting = {}; /** * Trims the . and .. from an array of path segments. * It will keep a leading path segment if a .. will become * the first path segment, to help with module name lookups, * which act like paths, but can be remapped. But the end result, * all paths that use this function should look normalized. * NOTE: this method MODIFIES the input array. * @param {Array} ary the array of path segments. */ function trimDots(ary) { var i, part; for (i = 0; (part = ary[i]); i++) { if (part === ".") { ary.splice(i, 1); i -= 1; } else if (part === "..") { if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { //End of the line. Keep at least one non-dot //path segment at the front so it can be mapped //correctly to disk. Otherwise, there is likely //no path mapping for a path starting with '..'. //This can still fail, but catches the most reasonable //uses of .. break; } else if (i > 0) { ary.splice(i - 1, 2); i -= 2; } } } } /** * Given a relative module name, like ./something, normalize it to * a real name that can be mapped to a path. * @param {String} name the relative name * @param {String} baseName a real name that the name arg is relative * to. * @returns {String} normalized name */ function normalize(name, baseName) { var pkgName, pkgConfig; //Adjust any relative paths. if (name.charAt(0) === ".") { //If have a base name, try to normalize against it, //otherwise, assume it is a top-level require that will //be relative to baseUrl in the end. if (baseName) { if (config.pkgs[baseName]) { //If the baseName is a package name, then just treat it as one //name to concat the name with. baseName = [baseName]; } else { //Convert baseName to array, and lop off the last part, //so that . matches that "directory" and not name of the baseName's //module. For instance, baseName of "one/two/three", maps to //"one/two/three.js", but we want the directory, "one/two" for //this normalization. baseName = baseName.split("/"); baseName = baseName.slice(0, baseName.length - 1); } name = baseName.concat(name.split("/")); trimDots(name); //Some use of packages may use a . path to reference the //"main" module name, so normalize for that. pkgConfig = config.pkgs[(pkgName = name[0])]; name = name.join("/"); if (pkgConfig && name === pkgName + '/' + pkgConfig.main) { name = pkgName; } } } return name; } /** * Creates a module mapping that includes plugin prefix, module * name, and path. If parentModuleMap is provided it will * also normalize the name via require.normalize() * * @param {String} name the module name * @param {String} [parentModuleMap] parent module map * for the module name, used to resolve relative names. * * @returns {Object} */ function makeModuleMap(name, parentModuleMap) { var index = name ? name.indexOf("!") : -1, prefix = null, parentName = parentModuleMap ? parentModuleMap.name : null, originalName = name, normalizedName, url, pluginModule; if (index !== -1) { prefix = name.substring(0, index); name = name.substring(index + 1, name.length); } if (prefix) { prefix = normalize(prefix, parentName); } //Account for relative paths if there is a base name. if (name) { if (prefix) { pluginModule = defined[prefix]; if (pluginModule) { //Plugin is loaded, use its normalize method, otherwise, //normalize name as usual. if (pluginModule.normalize) { normalizedName = pluginModule.normalize(name, function (name) { return normalize(name, parentName); }); } else { normalizedName = normalize(name, parentName); } } else { //Plugin is not loaded yet, so do not normalize //the name, wait for plugin to load to see if //it has a normalize method. To avoid possible //ambiguity with relative names loaded from another //plugin, use the parent's name as part of this name. normalizedName = '__$p' + parentName + '@' + name; } } else { normalizedName = normalize(name, parentName); } url = urlMap[normalizedName]; if (!url) { //Calculate url for the module, if it has a name. if (req.toModuleUrl) { //Special logic required for a particular engine, //like Node. url = req.toModuleUrl(context, name, parentModuleMap); } else { url = context.nameToUrl(name, null, parentModuleMap); } //Store the URL mapping for later. urlMap[normalizedName] = url; } } return { prefix: prefix, name: normalizedName, parentMap: parentModuleMap, url: url, originalName: originalName, fullName: prefix ? prefix + "!" + normalizedName : normalizedName }; } /** * Determine if priority loading is done. If so clear the priorityWait */ function isPriorityDone() { var priorityDone = true, priorityWait = config.priorityWait, priorityName, i; if (priorityWait) { for (i = 0; (priorityName = priorityWait[i]); i++) { if (!loaded[priorityName]) { priorityDone = false; break; } } if (priorityDone) { delete config.priorityWait; } } return priorityDone; } /** * Helper function that creates a setExports function for a "module" * CommonJS dependency. Do this here to avoid creating a closure that * is part of a loop. */ function makeSetExports(moduleObj) { return function (exports) { moduleObj.exports = exports; }; } function makeContextModuleFunc(func, relModuleMap, enableBuildCallback) { return function () { //A version of a require function that passes a moduleName //value for items that may need to //look up paths relative to the moduleName var args = [].concat(aps.call(arguments, 0)), lastArg; if (enableBuildCallback && isFunction((lastArg = args[args.length - 1]))) { lastArg.__requireJsBuild = true; } args.push(relModuleMap); return func.apply(null, args); }; } /** * Helper function that creates a require function object to give to * modules that ask for it as a dependency. It needs to be specific * per module because of the implication of path mappings that may * need to be relative to the module name. */ function makeRequire(relModuleMap, enableBuildCallback) { var modRequire = makeContextModuleFunc(context.require, relModuleMap, enableBuildCallback); mixin(modRequire, { nameToUrl: makeContextModuleFunc(context.nameToUrl, relModuleMap), toUrl: makeContextModuleFunc(context.toUrl, relModuleMap), isDefined: makeContextModuleFunc(context.isDefined, relModuleMap), ready: req.ready, isBrowser: req.isBrowser }); //Something used by node. if (req.paths) { modRequire.paths = req.paths; } return modRequire; } /** * Used to update the normalized name for plugin-based dependencies * after a plugin loads, since it can have its own normalization structure. * @param {String} pluginName the normalized plugin module name. */ function updateNormalizedNames(pluginName) { var oldFullName, oldModuleMap, moduleMap, fullName, callbacks, i, j, k, depArray, existingCallbacks, maps = normalizedWaiting[pluginName]; if (maps) { for (i = 0; (oldModuleMap = maps[i]); i++) { oldFullName = oldModuleMap.fullName; moduleMap = makeModuleMap(oldModuleMap.originalName, oldModuleMap.parentMap); fullName = moduleMap.fullName; //Callbacks could be undefined if the same plugin!name was //required twice in a row, so use empty array in that case. callbacks = managerCallbacks[oldFullName] || []; existingCallbacks = managerCallbacks[fullName]; if (fullName !== oldFullName) { //Update the specified object, but only if it is already //in there. In sync environments, it may not be yet. if (oldFullName in specified) { delete specified[oldFullName]; specified[fullName] = true; } //Update managerCallbacks to use the correct normalized name. //If there are already callbacks for the normalized name, //just add to them. if (existingCallbacks) { managerCallbacks[fullName] = existingCallbacks.concat(callbacks); } else { managerCallbacks[fullName] = callbacks; } delete managerCallbacks[oldFullName]; //In each manager callback, update the normalized name in the depArray. for (j = 0; j < callbacks.length; j++) { depArray = callbacks[j].depArray; for (k = 0; k < depArray.length; k++) { if (depArray[k] === oldFullName) { depArray[k] = fullName; } } } } } } delete normalizedWaiting[pluginName]; } /* * Queues a dependency for checking after the loader is out of a * "paused" state, for example while a script file is being loaded * in the browser, where it may have many modules defined in it. * * depName will be fully qualified, no relative . or .. path. */ function queueDependency(dep) { //Make sure to load any plugin and associate the dependency //with that plugin. var prefix = dep.prefix, fullName = dep.fullName; //Do not bother if the depName is already in transit if (specified[fullName] || fullName in defined) { return; } if (prefix && !plugins[prefix]) { //Queue up loading of the dependency, track it //via context.plugins. Mark it as a plugin so //that the build system will know to treat it //special. plugins[prefix] = undefined; //Remember this dep that needs to have normaliztion done //after the plugin loads. (normalizedWaiting[prefix] || (normalizedWaiting[prefix] = [])) .push(dep); //Register an action to do once the plugin loads, to update //all managerCallbacks to use a properly normalized module //name. (managerCallbacks[prefix] || (managerCallbacks[prefix] = [])).push({ onDep: function (name, value) { if (name === prefix) { updateNormalizedNames(prefix); } } }); queueDependency(makeModuleMap(prefix)); } context.paused.push(dep); } function execManager(manager) { var i, ret, waitingCallbacks, cb = manager.callback, fullName = manager.fullName, args = [], ary = manager.depArray; //Call the callback to define the module, if necessary. if (cb && isFunction(cb)) { //Pull out the defined dependencies and pass the ordered //values to the callback. if (ary) { for (i = 0; i < ary.length; i++) { args.push(manager.deps[ary[i]]); } } ret = req.execCb(fullName, manager.callback, args); if (fullName) { //If using exports and the function did not return a value, //and the "module" object for this definition function did not //define an exported value, then use the exports object. if (manager.usingExports && ret === undefined && (!manager.cjsModule || !("exports" in manager.cjsModule))) { ret = defined[fullName]; } else { if (manager.cjsModule && "exports" in manager.cjsModule) { ret = defined[fullName] = manager.cjsModule.exports; } else { if (fullName in defined && !manager.usingExports) { return req.onError(new Error(fullName + " has already been defined")); } defined[fullName] = ret; } } } } else if (fullName) { //May just be an object definition for the module. Only //worry about defining if have a module name. ret = defined[fullName] = cb; } if (fullName) { //If anything was waiting for this module to be defined, //notify them now. waitingCallbacks = managerCallbacks[fullName]; if (waitingCallbacks) { for (i = 0; i < waitingCallbacks.length; i++) { waitingCallbacks[i].onDep(fullName, ret); } delete managerCallbacks[fullName]; } } //Clean up waiting. if (waiting[manager.waitId]) { delete waiting[manager.waitId]; manager.isDone = true; context.waitCount -= 1; if (context.waitCount === 0) { //Clear the wait array used for cycles. waitAry = []; } } return undefined; } function main(inName, depArray, callback, relModuleMap) { var moduleMap = makeModuleMap(inName, relModuleMap), name = moduleMap.name, fullName = moduleMap.fullName, uniques = {}, manager = { //Use a wait ID because some entries are anon //async require calls. waitId: name || reqWaitIdPrefix + (waitIdCounter++), depCount: 0, depMax: 0, prefix: moduleMap.prefix, name: name, fullName: fullName, deps: {}, depArray: depArray, callback: callback, onDep: function (depName, value) { if (!(depName in manager.deps)) { manager.deps[depName] = value; manager.depCount += 1; if (manager.depCount === manager.depMax) { //All done, execute! execManager(manager); } } } }, i, depArg, depName, cjsMod; if (fullName) { //If module already defined for context, or already loaded, //then leave. if (fullName in defined || loaded[fullName] === true) { return; } //Set specified/loaded here for modules that are also loaded //as part of a layer, where onScriptLoad is not fired //for those cases. Do this after the inline define and //dependency tracing is done. //Also check if auto-registry of jQuery needs to be skipped. specified[fullName] = true; loaded[fullName] = true; context.jQueryDef = (fullName === "jquery"); } //Add the dependencies to the deps field, and register for callbacks //on the dependencies. for (i = 0; i < depArray.length; i++) { depArg = depArray[i]; //There could be cases like in IE, where a trailing comma will //introduce a null dependency, so only treat a real dependency //value as a dependency. if (depArg) { //Split the dependency name into plugin and name parts depArg = makeModuleMap(depArg, (name ? moduleMap : relModuleMap)); depName = depArg.fullName; //Fix the name in depArray to be just the name, since //that is how it will be called back later. depArray[i] = depName; //Fast path CommonJS standard dependencies. if (depName === "require") { manager.deps[depName] = makeRequire(moduleMap); } else if (depName === "exports") { //CommonJS module spec 1.1 manager.deps[depName] = defined[fullName] = {}; manager.usingExports = true; } else if (depName === "module") { //CommonJS module spec 1.1 manager.cjsModule = cjsMod = manager.deps[depName] = { id: name, uri: name ? context.nameToUrl(name, null, relModuleMap) : undefined }; cjsMod.setExports = makeSetExports(cjsMod); } else if (depName in defined && !(depName in waiting)) { //Module already defined, no need to wait for it. manager.deps[depName] = defined[depName]; } else if (!uniques[depName]) { //A dynamic dependency. manager.depMax += 1; queueDependency(depArg); //Register to get notification when dependency loads. (managerCallbacks[depName] || (managerCallbacks[depName] = [])).push(manager); uniques[depName] = true; } } } //Do not bother tracking the manager if it is all done. if (manager.depCount === manager.depMax) { //All done, execute! execManager(manager); } else { waiting[manager.waitId] = manager; waitAry.push(manager); context.waitCount += 1; } } /** * Convenience method to call main for a require.def call that was put on * hold in the defQueue. */ function callDefMain(args) { main.apply(null, args); //Mark the module loaded. Must do it here in addition //to doing it in require.def in case a script does //not call require.def loaded[args[0]] = true; } /** * As of jQuery 1.4.3, it supports a readyWait property that will hold off * calling jQuery ready callbacks until all scripts are loaded. Be sure * to track it if readyWait is available. Also, since jQuery 1.4.3 does * not register as a module, need to do some global inference checking. * Even if it does register as a module, not guaranteed to be the precise * name of the global. If a jQuery is tracked for this context, then go * ahead and register it as a module too, if not already in process. */ function jQueryCheck(jqCandidate) { if (!context.jQuery) { var $ = jqCandidate || (typeof jQuery !== "undefined" ? jQuery : null); if ($ && "readyWait" in $) { context.jQuery = $; //Manually create a "jquery" module entry if not one already //or in process. callDefMain(["jquery", [], function () { return jQuery; }]); //Increment jQuery readyWait if ncecessary. if (context.scriptCount) { $.readyWait += 1; context.jQueryIncremented = true; } } } } function forceExec(manager, traced) { if (manager.isDone) { return undefined; } var fullName = manager.fullName, depArray = manager.depArray, depName, i; if (fullName) { if (traced[fullName]) { return defined[fullName]; } traced[fullName] = true; } //forceExec all of its dependencies. for (i = 0; i < depArray.length; i++) { //Some array members may be null, like if a trailing comma //IE, so do the explicit [i] access and check if it has a value. depName = depArray[i]; if (depName) { if (!manager.deps[depName] && waiting[depName]) { manager.onDep(depName, forceExec(waiting[depName], traced)); } } } return fullName ? defined[fullName] : undefined; } /** * Checks if all modules for a context are loaded, and if so, evaluates the * new ones in right dependency order. * * @private */ function checkLoaded() { var waitInterval = config.waitSeconds * 1000, //It is possible to disable the wait interval by using waitSeconds of 0. expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(), noLoads = "", hasLoadedProp = false, stillLoading = false, prop, err, manager; //If there are items still in the paused queue processing wait. //This is particularly important in the sync case where each paused //item is processed right away but there may be more waiting. if (context.pausedCount > 0) { return undefined; } //Determine if priority loading is done. If so clear the priority. If //not, then do not check if (config.priorityWait) { if (isPriorityDone()) { //Call resume, since it could have //some waiting dependencies to trace. resume(); } else { return undefined; } } //See if anything is still in flight. for (prop in loaded) { if (!(prop in empty)) { hasLoadedProp = true; if (!loaded[prop]) { if (expired) { noLoads += prop + " "; } else { stillLoading = true; break; } } } } //Check for exit conditions. if (!hasLoadedProp && !context.waitCount) { //If the loaded object had no items, then the rest of //the work below does not need to be done. return undefined; } if (expired && noLoads) { //If wait time expired, throw error of unloaded modules. err = new Error("require.js load timeout for modules: " + noLoads); err.requireType = "timeout"; err.requireModules = noLoads; return req.onError(err); } if (stillLoading || context.scriptCount) { //Something is still waiting to load. Wait for it. if (isBrowser || isWebWorker) { setTimeout(checkLoaded, 50); } return undefined; } //If still have items in the waiting cue, but all modules have //been loaded, then it means there are some circular dependencies //that need to be broken. //However, as a waiting thing is fired, then it can add items to //the waiting cue, and those items should not be fired yet, so //make sure to redo the checkLoaded call after breaking a single //cycle, if nothing else loaded then this logic will pick it up //again. if (context.waitCount) { //Cycle through the waitAry, and call items in sequence. for (i = 0; (manager = waitAry[i]); i++) { forceExec(manager, {}); } checkLoaded(); return undefined; } //Check for DOM ready, and nothing is waiting across contexts. req.checkReadyState(); return undefined; } function callPlugin(pluginName, dep) { var name = dep.name, fullName = dep.fullName, load; //Do not bother if plugin is already defined or being loaded. if (fullName in defined || fullName in loaded) { return; } if (!plugins[pluginName]) { plugins[pluginName] = defined[pluginName]; } //Only set loaded to false for tracking if it has not already been set. if (!loaded[fullName]) { loaded[fullName] = false; } load = function (ret) { //Allow the build process to register plugin-loaded dependencies. if (require.onPluginLoad) { require.onPluginLoad(context, pluginName, name, ret); } execManager({ prefix: dep.prefix, name: dep.name, fullName: dep.fullName, callback: function () { return ret; } }); loaded[fullName] = true; }; //Allow plugins to load other code without having to know the //context or how to "complete" the load. load.fromText = function (moduleName, text) { /*jslint evil: true */ var hasInteractive = useInteractive; //Indicate a the module is in process of loading. context.loaded[moduleName] = false; context.scriptCount += 1; //Turn off interactive script matching for IE for any define //calls in the text, then turn it back on at the end. if (hasInteractive) { useInteractive = false; } eval(text); if (hasInteractive) { useInteractive = true; } //Support anonymous modules. context.completeLoad(moduleName); }; //Use parentName here since the plugin's name is not reliable, //could be some weird string with no path that actually wants to //reference the parentName's path. plugins[pluginName].load(name, makeRequire(dep.parentMap, true), load, config); } function loadPaused(dep) { //Renormalize dependency if its name was waiting on a plugin //to load, which as since loaded. if (dep.prefix && dep.name.indexOf('__$p') === 0 && defined[dep.prefix]) { dep = makeModuleMap(dep.originalName, dep.parentMap); } var pluginName = dep.prefix, fullName = dep.fullName; //Do not bother if the dependency has already been specified. if (specified[fullName] || loaded[fullName]) { return; } else { specified[fullName] = true; } if (pluginName) { //If plugin not loaded, wait for it. //set up callback list. if no list, then register //managerCallback for that plugin. if (defined[pluginName]) { callPlugin(pluginName, dep); } else { if (!pluginsQueue[pluginName]) { pluginsQueue[pluginName] = []; (managerCallbacks[pluginName] || (managerCallbacks[pluginName] = [])).push({ onDep: function (name, value) { if (name === pluginName) { var i, oldModuleMap, ary = pluginsQueue[pluginName]; //Now update all queued plugin actions. for (i = 0; i < ary.length; i++) { oldModuleMap = ary[i]; //Update the moduleMap since the //module name may be normalized //differently now. callPlugin(pluginName, makeModuleMap(oldModuleMap.originalName, oldModuleMap.parentMap)); } delete pluginsQueue[pluginName]; } } }); } pluginsQueue[pluginName].push(dep); } } else { req.load(context, fullName, dep.url); } } /** * Resumes tracing of dependencies and then checks if everything is loaded. */ resume = function () { var args, i, p; resumeDepth += 1; if (context.scriptCount <= 0) { //Synchronous envs will push the number below zero with the //decrement above, be sure to set it back to zero for good measure. //require() calls that also do not end up loading scripts could //push the number negative too. context.scriptCount = 0; } //Make sure any remaining defQueue items get properly processed. while (defQueue.length) { args = defQueue.shift(); if (args[0] === null) { return req.onError(new Error('Mismatched anonymous require.def modules')); } else { callDefMain(args); } } //Skip the resume of paused dependencies //if current context is in priority wait. if (!config.priorityWait || isPriorityDone()) { while (context.paused.length) { p = context.paused; context.pausedCount += p.length; //Reset paused list context.paused = []; for (i = 0; (args = p[i]); i++) { loadPaused(args); } //Move the start time for timeout forward. context.startTime = (new Date()).getTime(); context.pausedCount -= p.length; } } //Only check if loaded when resume depth is 1. It is likely that //it is only greater than 1 in sync environments where a factory //function also then calls the callback-style require. In those //cases, the checkLoaded should not occur until the resume //depth is back at the top level. if (resumeDepth === 1) { checkLoaded(); } resumeDepth -= 1; return undefined; }; //Define the context object. Many of these fields are on here //just to make debugging easier. context = { contextName: contextName, config: config, defQueue: defQueue, waiting: waiting, waitCount: 0, specified: specified, loaded: loaded, urlMap: urlMap, scriptCount: 0, urlFetched: {}, defined: defined, paused: [], pausedCount: 0, plugins: plugins, managerCallbacks: managerCallbacks, makeModuleMap: makeModuleMap, normalize: normalize, /** * Set a configuration for the context. * @param {Object} cfg config object to integrate. */ configure: function (cfg) { var paths, prop, packages, pkgs, packagePaths, requireWait; //Make sure the baseUrl ends in a slash. if (cfg.baseUrl) { if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== "/") { cfg.baseUrl += "/"; } } //Save off the paths and packages since they require special processing, //they are additive. paths = config.paths; packages = config.packages; pkgs = config.pkgs; //Mix in the config values, favoring the new values over //existing ones in context.config. mixin(config, cfg, true); //Adjust paths if necessary. if (cfg.paths) { for (prop in cfg.paths) { if (!(prop in empty)) { paths[prop] = cfg.paths[prop]; } } config.paths = paths; } packagePaths = cfg.packagePaths; if (packagePaths || cfg.packages) { //Convert packagePaths into a packages config. if (packagePaths) { for (prop in packagePaths) { if (!(prop in empty)) { configurePackageDir(pkgs, packagePaths[prop], prop); } } } //Adjust packages if necessary. if (cfg.packages) { configurePackageDir(pkgs, cfg.packages); } //Done with modifications, assing packages back to context config config.pkgs = pkgs; } //If priority loading is in effect, trigger the loads now if (cfg.priority) { //Hold on to requireWait value, and reset it after done requireWait = context.requireWait; //Allow tracing some require calls to allow the fetching //of the priority config. context.requireWait = false; //But first, call resume to register any defined modules that may //be in a data-main built file before the priority config //call. Also grab any waiting define calls for this context. context.takeGlobalQueue(); resume(); context.require(cfg.priority); //Trigger a resume right away, for the case when //the script with the priority load is done as part //of a data-main call. In that case the normal resume //call will not happen because the scriptCount will be //at 1, since the script for data-main is being processed. resume(); //Restore previous state. context.requireWait = requireWait; config.priorityWait = cfg.priority; } //If a deps array or a config callback is specified, then call //require with those args. This is useful when require is defined as a //config object before require.js is loaded. if (cfg.deps || cfg.callback) { context.require(cfg.deps || [], cfg.callback); } //Set up ready callback, if asked. Useful when require is defined as a //config object before require.js is loaded. if (cfg.ready) { req.ready(cfg.ready); } }, isDefined: function (moduleName, relModuleMap) { return makeModuleMap(moduleName, relModuleMap).fullName in defined; }, require: function (deps, callback, relModuleMap) { var moduleName, ret, moduleMap; if (typeof deps === "string") { //Synchronous access to one module. If require.get is //available (as in the Node adapter), prefer that. //In this case deps is the moduleName and callback is //the relModuleMap if (req.get) { return req.get(context, deps, callback); } //Just return the module wanted. In this scenario, the //second arg (if passed) is just the relModuleMap. moduleName = deps; relModuleMap = callback; //Normalize module name, if it contains . or .. moduleMap = makeModuleMap(moduleName, relModuleMap); ret = defined[moduleMap.fullName]; if (ret === undefined) { return req.onError(new Error("require: module name '" + moduleMap.fullName + "' has not been loaded yet for context: " + contextName)); } return ret; } main(null, deps, callback, relModuleMap); //If the require call does not trigger anything new to load, //then resume the dependency processing. if (!context.requireWait) { while (!context.scriptCount && context.paused.length) { resume(); } } return undefined; }, /** * Internal method to transfer globalQueue items to this context's * defQueue. */ takeGlobalQueue: function () { //Push all the globalDefQueue items into the context's defQueue if (globalDefQueue.length) { //Array splice in the values since the context code has a //local var ref to defQueue, so cannot just reassign the one //on context. apsp.apply(context.defQueue, [context.defQueue.length - 1, 0].concat(globalDefQueue)); globalDefQueue = []; } }, /** * Internal method used by environment adapters to complete a load event. * A load event could be a script load or just a load pass from a synchronous * load call. * @param {String} moduleName the name of the module to potentially complete. */ completeLoad: function (moduleName) { var args; context.takeGlobalQueue(); while (defQueue.length) { args = defQueue.shift(); if (args[0] === null) { args[0] = moduleName; break; } else if (args[0] === moduleName) { //Found matching require.def call for this script! break; } else { //Some other named require.def call, most likely the result //of a build layer that included many require.def calls. callDefMain(args); args = null; } } if (args) { callDefMain(args); } else { //A script that does not call define(), so just simulate //the call for it. Special exception for jQuery dynamic load. callDefMain([moduleName, [], moduleName === "jquery" && typeof jQuery !== "undefined" ? function () { return jQuery; } : null]); } //Mark the script as loaded. Note that this can be different from a //moduleName that maps to a require.def call. This line is important //for traditional browser scripts. loaded[moduleName] = true; //If a global jQuery is defined, check for it. Need to do it here //instead of main() since stock jQuery does not register as //a module via define. jQueryCheck(); //Doing this scriptCount decrement branching because sync envs //need to decrement after resume, otherwise it looks like //loading is complete after the first dependency is fetched. //For browsers, it works fine to decrement after, but it means //the checkLoaded setTimeout 50 ms cost is taken. To avoid //that cost, decrement beforehand. if (req.isAsync) { context.scriptCount -= 1; } resume(); if (!req.isAsync) { context.scriptCount -= 1; } }, /** * Converts a module name + .extension into an URL path. * *Requires* the use of a module name. It does not support using * plain URLs like nameToUrl. */ toUrl: function (moduleNamePlusExt, relModuleMap) { var index = moduleNamePlusExt.lastIndexOf("."), ext = null; if (index !== -1) { ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length); moduleNamePlusExt = moduleNamePlusExt.substring(0, index); } return context.nameToUrl(moduleNamePlusExt, ext, relModuleMap); }, /** * Converts a module name to a file path. Supports cases where * moduleName may actually be just an URL. */ nameToUrl: function (moduleName, ext, relModuleMap) { var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url, config = context.config; if (moduleName.indexOf("./") === 0 || moduleName.indexOf("../") === 0) { //A relative ID, just map it relative to relModuleMap's url syms = relModuleMap && relModuleMap.url ? relModuleMap.url.split('/') : []; //Pop off the file name. if (syms.length) { syms.pop(); } syms = syms.concat(moduleName.split('/')); trimDots(syms); url = syms.join('/') + (ext ? ext : (req.jsExtRegExp.test(moduleName) ? "" : ".js")); } else { //Normalize module name if have a base relative module name to work from. moduleName = normalize(moduleName, relModuleMap); //If a colon is in the URL, it indicates a protocol is used and it is just //an URL to a file, or if it starts with a slash or ends with .js, it is just a plain file. //The slash is important for protocol-less URLs as well as full paths. if (req.jsExtRegExp.test(moduleName)) { //Just a plain path, not module name lookup, so just return it. //Add extension if it is included. This is a bit wonky, only non-.js things pass //an extension, this method probably needs to be reworked. url = moduleName + (ext ? ext : ""); } else { //A module that needs to be converted to a path. paths = config.paths; pkgs = config.pkgs; syms = moduleName.split("/"); //For each module name segment, see if there is a path //registered for it. Start with most specific name //and work up from it. for (i = syms.length; i > 0; i--) { parentModule = syms.slice(0, i).join("/"); if (paths[parentModule]) { syms.splice(0, i, paths[parentModule]); break; } else if ((pkg = pkgs[parentModule])) { //If module name is just the package name, then looking //for the main module. if (moduleName === pkg.name) { pkgPath = pkg.location + '/' + pkg.main; } else { pkgPath = pkg.location + '/' + pkg.lib; } syms.splice(0, i, pkgPath); break; } } //Join the path parts together, then figure out if baseUrl is needed. url = syms.join("/") + (ext || ".js"); url = (url.charAt(0) === '/' || url.match(/^\w+:/) ? "" : config.baseUrl) + url; } } return config.urlArgs ? url + ((url.indexOf('?') === -1 ? '?' : '&') + config.urlArgs) : url; } }; //Make these visible on the context so can be called at the very //end of the file to bootstrap context.jQueryCheck = jQueryCheck; context.resume = resume; return context; } /** * Main entry point. * * If the only argument to require is a string, then the module that * is represented by that string is fetched for the appropriate context. * * If the first argument is an array, then it will be treated as an array * of dependency string names to fetch. An optional function callback can * be specified to execute when all of those dependencies are available. * * Make a local req variable to help Caja compliance (it assumes things * on a require that are not standardized), and to give a short * name for minification/local scope use. */ req = require = function (deps, callback) { //Find the right context, use default var contextName = defContextName, context, config; // Determine if have config object in the call. if (!isArray(deps) && typeof deps !== "string") { // deps is a config object config = deps; if (isArray(callback)) { // Adjust args if there are dependencies deps = callback; callback = arguments[2]; } else { deps = []; } } if (config && config.context) { contextName = config.context; } context = contexts[contextName] || (contexts[contextName] = newContext(contextName)); if (config) { context.configure(config); } return context.require(deps, callback); }; req.version = version; req.isArray = isArray; req.isFunction = isFunction; req.mixin = mixin; //Used to filter out dependencies that are already paths. req.jsExtRegExp = /^\/|:|\?|\.js$/; s = req.s = { contexts: contexts, //Stores a list of URLs that should not get async script tag treatment. skipAsync: {}, isPageLoaded: !isBrowser, readyCalls: [] }; req.isAsync = req.isBrowser = isBrowser; if (isBrowser) { head = s.head = document.getElementsByTagName("head")[0]; //If BASE tag is in play, using appendChild is a problem for IE6. //When that browser dies, this can be removed. Details in this jQuery bug: //http://dev.jquery.com/ticket/2709 baseElement = document.getElementsByTagName("base")[0]; if (baseElement) { head = s.head = baseElement.parentNode; } } /** * Any errors that require explicitly generates will be passed to this * function. Intercept/override it if you want custom error handling. * @param {Error} err the error object. */ req.onError = function (err) { throw err; }; /** * Does the request to load a module for the browser case. * Make this a separate function to allow other environments * to override it. * * @param {Object} context the require context to find state. * @param {String} moduleName the name of the module. * @param {Object} url the URL to the module. */ req.load = function (context, moduleName, url) { var contextName = context.contextName, urlFetched = context.urlFetched, loaded = context.loaded; isDone = false; //Only set loaded to false for tracking if it has not already been set. if (!loaded[moduleName]) { loaded[moduleName] = false; } if (!urlFetched[url]) { context.scriptCount += 1; req.attach(url, contextName, moduleName); urlFetched[url] = true; //If tracking a jQuery, then make sure its readyWait //is incremented to prevent its ready callbacks from //triggering too soon. if (context.jQuery && !context.jQueryIncremented) { context.jQuery.readyWait += 1; context.jQueryIncremented = true; } } }; function getInteractiveScript() { var scripts, i, script; if (interactiveScript && interactiveScript.readyState === 'interactive') { return interactiveScript; } scripts = document.getElementsByTagName('script'); for (i = scripts.length - 1; i > -1 && (script = scripts[i]); i--) { if (script.readyState === 'interactive') { return (interactiveScript = script); } } return null; } /** * The function that handles definitions of modules. Differs from * require() in that a string for the module should be the first argument, * and the function to execute after dependencies are loaded should * return a value to define the module corresponding to the first argument's * name. */ define = req.def = function (name, deps, callback) { var node, context; //Allow for anonymous functions if (typeof name !== 'string') { //Adjust args appropriately callback = deps; deps = name; name = null; } //This module may not have dependencies if (!req.isArray(deps)) { callback = deps; deps = []; } //If no name, and callback is a function, then figure out if it a //CommonJS thing with dependencies. if (!name && !deps.length && req.isFunction(callback)) { //Remove comments from the callback string, //look for require calls, and pull them into the dependencies, //but only if there are function args. if (callback.length) { callback .toString() .replace(commentRegExp, "") .replace(cjsRequireRegExp, function (match, dep) { deps.push(dep); }); //May be a CommonJS thing even without require calls, but still //could use exports, and such, so always add those as dependencies. //This is a bit wasteful for RequireJS modules that do not need //an exports or module object, but erring on side of safety. //REQUIRES the function to expect the CommonJS variables in the //order listed below. deps = ["require", "exports", "module"].concat(deps); } } //If in IE 6-8 and hit an anonymous define() call, do the interactive //work. if (useInteractive) { node = currentlyAddingScript || getInteractiveScript(); if (!node) { return req.onError(new Error("ERROR: No matching script interactive for " + callback)); } if (!name) { name = node.getAttribute("data-requiremodule"); } context = contexts[node.getAttribute("data-requirecontext")]; } //Always save off evaluating the def call until the script onload handler. //This allows multiple modules to be in a file without prematurely //tracing dependencies, and allows for anonymous module support, //where the module name is not known until the script onload event //occurs. If no context, use the global queue, and get it processed //in the onscript load callback. (context ? context.defQueue : globalDefQueue).push([name, deps, callback]); return undefined; }; define.amd = { multiversion: true, plugins: true }; /** * Executes a module callack function. Broken out as a separate function * solely to allow the build system to sequence the files in the built * layer in the right sequence. * * @private */ req.execCb = function (name, callback, args) { return callback.apply(null, args); }; /** * callback for script loads, used to check status of loading. * * @param {Event} evt the event from the browser for the script * that was loaded. * * @private */ req.onScriptLoad = function (evt) { //Using currentTarget instead of target for Firefox 2.0's sake. Not //all old browsers will be supported, but this one was easy enough //to support and still makes sense. var node = evt.currentTarget || evt.srcElement, contextName, moduleName, context; if (evt.type === "load" || readyRegExp.test(node.readyState)) { //Reset interactive script so a script node is not held onto for //to long. interactiveScript = null; //Pull out the name of the module and the context. contextName = node.getAttribute("data-requirecontext"); moduleName = node.getAttribute("data-requiremodule"); context = contexts[contextName]; contexts[contextName].completeLoad(moduleName); //Clean up script binding. Favor detachEvent because of IE9 //issue, see attachEvent/addEventListener comment elsewhere //in this file. if (node.detachEvent && !isOpera) { //Probably IE. If not it will throw an error, which will be //useful to know. node.detachEvent("onreadystatechange", req.onScriptLoad); } else { node.removeEventListener("load", req.onScriptLoad, false); } } }; /** * Attaches the script represented by the URL to the current * environment. Right now only supports browser loading, * but can be redefined in other environments to do the right thing. * @param {String} url the url of the script to attach. * @param {String} contextName the name of the context that wants the script. * @param {moduleName} the name of the module that is associated with the script. * @param {Function} [callback] optional callback, defaults to require.onScriptLoad * @param {String} [type] optional type, defaults to text/javascript */ req.attach = function (url, contextName, moduleName, callback, type) { var node, loaded, context; if (isBrowser) { //In the browser so use a script tag callback = callback || req.onScriptLoad; node = document.createElement("script"); node.type = type || "text/javascript"; node.charset = "utf-8"; //Use async so Gecko does not block on executing the script if something //like a long-polling comet tag is being run first. Gecko likes //to evaluate scripts in DOM order, even for dynamic scripts. //It will fetch them async, but only evaluate the contents in DOM //order, so a long-polling script tag can delay execution of scripts //after it. But telling Gecko we expect async gets us the behavior //we want -- execute it whenever it is finished downloading. Only //Helps Firefox 3.6+ //Allow some URLs to not be fetched async. Mostly helps the order! //plugin node.async = !s.skipAsync[url]; node.setAttribute("data-requirecontext", contextName); node.setAttribute("data-requiremodule", moduleName); //Set up load listener. Test attachEvent first because IE9 has //a subtle issue in its addEventListener and script onload firings //that do not match the behavior of all other browsers with //addEventListener support, which fire the onload event for a //script right after the script execution. See: //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution //UNFORTUNATELY Opera implements attachEvent but does not follow the script //script execution mode. if (node.attachEvent && !isOpera) { //Probably IE. IE (at least 6-8) do not fire //script onload right after executing the script, so //we cannot tie the anonymous require.def call to a name. //However, IE reports the script as being in "interactive" //readyState at the time of the require.def call. useInteractive = true; node.attachEvent("onreadystatechange", callback); } else { node.addEventListener("load", callback, false); } node.src = url; //For some cache cases in IE 6-8, the script executes before the end //of the appendChild execution, so to tie an anonymous require.def //call to the module name (which is stored on the node), hold on //to a reference to this node, but clear after the DOM insertion. currentlyAddingScript = node; if (baseElement) { head.insertBefore(node, baseElement); } else { head.appendChild(node); } currentlyAddingScript = null; return node; } else if (isWebWorker) { //In a web worker, use importScripts. This is not a very //efficient use of importScripts, importScripts will block until //its script is downloaded and evaluated. However, if web workers //are in play, the expectation that a build has been done so that //only one script needs to be loaded anyway. This may need to be //reevaluated if other use cases become common. context = contexts[contextName]; loaded = context.loaded; loaded[moduleName] = false; importScripts(url); //Account for anonymous modules context.completeLoad(moduleName); } return null; }; //Look for a data-main script attribute, which could also adjust the baseUrl. if (isBrowser) { //Figure out baseUrl. Get it from the script tag with require.js in it. scripts = document.getElementsByTagName("script"); for (i = scripts.length - 1; i > -1 && (script = scripts[i]); i--) { //Set the "head" where we can append children by //using the script's parent. if (!head) { head = script.parentNode; } //Look for a data-main attribute to set main script for the page //to load. If it is there, the path to data main becomes the //baseUrl, if it is not already set. if ((dataMain = script.getAttribute('data-main'))) { if (!cfg.baseUrl) { //Pull off the directory of data-main for use as the //baseUrl. src = dataMain.split('/'); mainScript = src.pop(); subPath = src.length ? src.join('/') + '/' : './'; //Set final config. cfg.baseUrl = subPath; //Strip off any trailing .js since dataMain is now //like a module name. dataMain = mainScript.replace(jsSuffixRegExp, ''); } //Put the data-main script in the files to load. cfg.deps = cfg.deps ? cfg.deps.concat(dataMain) : [dataMain]; break; } } } //Set baseUrl based on config. s.baseUrl = cfg.baseUrl; //****** START page load functionality **************** /** * Sets the page as loaded and triggers check for all modules loaded. */ req.pageLoaded = function () { if (!s.isPageLoaded) { s.isPageLoaded = true; if (scrollIntervalId) { clearInterval(scrollIntervalId); } //Part of a fix for FF < 3.6 where readyState was not set to //complete so libraries like jQuery that check for readyState //after page load where not getting initialized correctly. //Original approach suggested by Andrea Giammarchi: //http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html //see other setReadyState reference for the rest of the fix. if (setReadyState) { document.readyState = "complete"; } req.callReady(); } }; //See if there is nothing waiting across contexts, and if not, trigger //callReady. req.checkReadyState = function () { var contexts = s.contexts, prop; for (prop in contexts) { if (!(prop in empty)) { if (contexts[prop].waitCount) { return; } } } s.isDone = true; req.callReady(); }; /** * Internal function that calls back any ready functions. If you are * integrating RequireJS with another library without require.ready support, * you can define this method to call your page ready code instead. */ req.callReady = function () { var callbacks = s.readyCalls, i, callback, contexts, context, prop; if (s.isPageLoaded && s.isDone) { if (callbacks.length) { s.readyCalls = []; for (i = 0; (callback = callbacks[i]); i++) { callback(); } } //If jQuery with readyWait is being tracked, updated its //readyWait count. contexts = s.contexts; for (prop in contexts) { if (!(prop in empty)) { context = contexts[prop]; if (context.jQueryIncremented) { context.jQuery.ready(true); context.jQueryIncremented = false; } } } } }; /** * Registers functions to call when the page is loaded */ req.ready = function (callback) { if (s.isPageLoaded && s.isDone) { callback(); } else { s.readyCalls.push(callback); } return req; }; if (isBrowser) { if (document.addEventListener) { //Standards. Hooray! Assumption here that if standards based, //it knows about DOMContentLoaded. document.addEventListener("DOMContentLoaded", req.pageLoaded, false); window.addEventListener("load", req.pageLoaded, false); //Part of FF < 3.6 readystate fix (see setReadyState refs for more info) if (!document.readyState) { setReadyState = true; document.readyState = "loading"; } } else if (window.attachEvent) { window.attachEvent("onload", req.pageLoaded); //DOMContentLoaded approximation, as found by Diego Perini: //http://javascript.nwbox.com/IEContentLoaded/ if (self === self.top) { scrollIntervalId = setInterval(function () { try { //From this ticket: //http://bugs.dojotoolkit.org/ticket/11106, //In IE HTML Application (HTA), such as in a selenium test, //javascript in the iframe can't see anything outside //of it, so self===self.top is true, but the iframe is //not the top window and doScroll will be available //before document.body is set. Test document.body //before trying the doScroll trick. if (document.body) { document.documentElement.doScroll("left"); req.pageLoaded(); } } catch (e) {} }, 30); } } //Check if document already complete, and if so, just trigger page load //listeners. NOTE: does not work with Firefox before 3.6. To support //those browsers, manually call require.pageLoaded(). if (document.readyState === "complete") { req.pageLoaded(); } } //****** END page load functionality **************** //Set up default context. If require was a configuration object, use that as base config. req(cfg); //If modules are built into require.js, then need to make sure dependencies are //traced. Use a setTimeout in the browser world, to allow all the modules to register //themselves. In a non-browser env, assume that modules are not built into require.js, //which seems odd to do on the server. if (req.isAsync && typeof setTimeout !== "undefined") { ctx = s.contexts[(cfg.context || defContextName)]; //Indicate that the script that includes require() is still loading, //so that require()'d dependencies are not traced until the end of the //file is parsed (approximated via the setTimeout call). ctx.requireWait = true; setTimeout(function () { ctx.requireWait = false; //Any modules included with the require.js file will be in the //global queue, assign them to this context. ctx.takeGlobalQueue(); //Allow for jQuery to be loaded/already in the page, and if jQuery 1.4.3, //make sure to hold onto it for readyWait triggering. ctx.jQueryCheck(); if (!ctx.scriptCount) { ctx.resume(); } req.checkReadyState(); }, 0); }
}());
define(‘utils’,,function(){
return { log: function(message) { if(false) { //LOGGING TURNED OFF IS 100% faster! try { console.log(message) } catch(e) {} //we're in IE or FF w/o Firebug or something } }, isArray: function(candidate) { return (candidate.constructor == Array) }, forEach: function(list, callback, thisArg) { if(typeof list.forEach == "function") { return list.forEach(callback, thisArg) } else if(typeof Array.prototype.forEach == "function") { return Array.prototype.forEach.call(list, callback, thisArg) } else { var len = Number(list.length) for(var k = 0; k < len; k+=1) { if(typeof list[k] != "undefined") { callback.call(thisArg, list[k], k, list) } } return } } } })
define(‘ninja/exceptions’,,function () {
return { CouldntChoose: function(){}, TransformFailed: function(){} } })
define(‘ninja/behaviors’,, function(Exceptions) {
var CouldntChooseException = Exceptions.CouldntChoose var behaviors = { } behaviors.meta = function(setup, callback) { setup(this) this.chooser = callback } behaviors.meta.prototype = { choose: function(element) { var chosen = this.chooser(element) if(chosen !== undefined) { return chosen.choose(element) } else { throw new CouldntChooseException } } } //For these to be acceptable, I need to fit them into the pattern that //Ninja.behavior accepts... behaviors.select = function(menu) { this.menu = menu } behaviors.select.prototype = { choose: function(element) { for(var selector in this.menu) { if(jQuery(element).is(selector)) { return this.menu[selector].choose(element) } } return null //XXX Should raise exception } } behaviors.base = function(handlers) { this.helpers = {} this.eventHandlers = [] this.lexicalOrder = 0 this.priority = 0 if (typeof handlers.transform == "function") { this.transform = handlers.transform delete handlers.transform } if (typeof handlers.helpers != "undefined"){ this.helpers = handlers.helpers delete handlers.helpers } if (typeof handlers.priority != "undefined"){ this.priority = handlers.priority } delete handlers.priority if (typeof handlers.events != "undefined") { this.eventHandlers = handlers.events } else { this.eventHandlers = handlers } return this } behaviors.base.prototype = { //XXX applyTo? apply: function(elem) { var context = this.inContext({}) elem = this.applyTransform(context, elem) jQuery(elem).data("ninja-visited", context) this.applyEventHandlers(context, elem) return elem }, priority: function(value) { this.priority = value return this }, choose: function(element) { return this }, inContext: function(basedOn) { function Context() {} Context.prototype = basedOn return Ninja.tools.enrich(new Context, this.helpers) }, applyTransform: function(context, elem) { var previousElem = elem var newElem = this.transform.call(context, elem) if(newElem === undefined) { return previousElem } else { return newElem } }, applyEventHandlers: function(context, elem) { for(var eventName in this.eventHandlers) { var handler = this.eventHandlers[eventName] jQuery(elem).bind(eventName, this.makeHandler.call(context, handler)) } return elem }, recordEventHandlers: function(scribe, context) { for(var eventName in this.eventHandlers) { scribe.recordHandler(this, eventName, function(oldHandler){ return this.makeHandler.call(context, this.eventHandlers[eventName], oldHandler) } ) } }, buildHandler: function(context, eventName, previousHandler) { var handle var fallThrough = true var stopDefault = true var stopPropagate = true var stopImmediate = false var fireMutation = false var config = this.eventHandlers[eventName] if (typeof config == "function") { handle = config } else { handle = config[0] config = config.slice(1,config.length) var len = config.length for(var i = 0; i < len; i++) { var found = true if (config[i] == "dontContinue" || config[i] == "overridesOthers") { fallThrough = false } if (config[i] == "andDoDefault" || config[i] == "continues" || config[i] == "allowDefault") { stopDefault = false } if (config[i] == "allowPropagate" || config[i] == "dontStopPropagation") { stopPropagate = false } //stopImmediatePropagation is a jQuery thing if (config[i] == "andDoOthers") { stopImmediate = false } if (config[i] == "changesDOM") { fireMutation = true } if (!found) { console.log("Event handler modifier unrecognized: " + config[i]) } } } var handler = function(eventRecord) { handle.call(context, eventRecord, this) if(!eventRecord.isFallthroughPrevented()) { previousHandler.call(context, eventRecord) } if(stopDefault){ return false } else { return !eventRecord.isDefaultPrevented() } } if(!fallThrough) { handler = this.prependAction(handler, function(eventRecord) { eventRecord.preventFallthrough() }) } if(stopDefault) { handler = this.prependAction(handler, function(eventRecord) { eventRecord.preventDefault() }) } if(stopPropagate) { handler = this.prependAction(handler, function(eventRecord) { eventRecord.stopPropagation() }) } if (stopImmediate) { handler = this.prependAction(handler, function(eventRecord) { eventRecord.stopImmediatePropagation() }) } if (fireMutation) { handler = this.appendAction(handler, function(eventRecord) { Ninja.tools.fireMutationEvent() }) } handler = this.prependAction(handler, function(eventRecord) { eventRecord.isFallthroughPrevented = function(){ return false }; eventRecord.preventFallthrough = function(){ eventRecord.isFallthroughPrevented =function(){ return true }; } }) return handler }, prependAction: function(handler, doWhat) { return function(eventRecord) { doWhat.call(this, eventRecord) return handler.call(this, eventRecord) } }, appendAction: function(handler, doWhat) { return function(eventRecord) { var result = handler.call(this, eventRecord) doWhat.call(this, eventRecord) return result } }, transform: function(elem){ return elem } } return behaviors })
define(‘sizzle-1.0’,,function() {
/* * Sizzle CSS engine * Copyright 2009 The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * * This version of the Sizzle engine taken from jQuery 1.4.2 * Doesn't conflict with Mutation events. */ var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, done = 0, toString = Object.prototype.toString, hasDuplicate = false, baseHasDuplicate = true; // Here we check if the JavaScript engine is using some sort of // optimization where it does not always call our comparision // function. If that is the case, discard the hasDuplicate value. // Thus far that includes Google Chrome. [0, 0].sort(function(){ baseHasDuplicate = false; return 0; }); var Sizzle = function(selector, context, results, seed) { results = results || []; var origContext = context = context || document; if ( context.nodeType !== 1 && context.nodeType !== 9 ) { return []; } if ( !selector || typeof selector !== "string" ) { return results; } var parts = [], m, set, checkSet, extra, prune = true, contextXML = isXML(context), soFar = selector; // Reset the position of the chunker regexp (start from head) while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) { soFar = m[3]; parts.push( m[1] ); if ( m[2] ) { extra = m[3]; break; } } if ( parts.length > 1 && origPOS.exec( selector ) ) { if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { set = posProcess( parts[0] + parts[1], context ); } else { set = Expr.relative[ parts[0] ] ? [ context ] : Sizzle( parts.shift(), context ); while ( parts.length ) { selector = parts.shift(); if ( Expr.relative[ selector ] ) { selector += parts.shift(); } set = posProcess( selector, set ); } } } else { // Take a shortcut and set the context if the root selector is an ID // (but not if it'll be faster if the inner selector is an ID) if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { var ret = Sizzle.find( parts.shift(), context, contextXML ); context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; } if ( context ) { var ret = seed ? { expr: parts.pop(), set: makeArray(seed) } : Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; if ( parts.length > 0 ) { checkSet = makeArray(set); } else { prune = false; } while ( parts.length ) { var cur = parts.pop(), pop = cur; if ( !Expr.relative[ cur ] ) { cur = ""; } else { pop = parts.pop(); } if ( pop == null ) { pop = context; } Expr.relative[ cur ]( checkSet, pop, contextXML ); } } else { checkSet = parts = []; } } if ( !checkSet ) { checkSet = set; } if ( !checkSet ) { Sizzle.error( cur || selector ); } if ( toString.call(checkSet) === "[object Array]" ) { if ( !prune ) { results.push.apply( results, checkSet ); } else if ( context && context.nodeType === 1 ) { for ( var i = 0; checkSet[i] != null; i++ ) { if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) { results.push( set[i] ); } } } else { for ( var i = 0; checkSet[i] != null; i++ ) { if ( checkSet[i] && checkSet[i].nodeType === 1 ) { results.push( set[i] ); } } } } else { makeArray( checkSet, results ); } if ( extra ) { Sizzle( extra, origContext, results, seed ); Sizzle.uniqueSort( results ); } return results; }; Sizzle.uniqueSort = function(results){ if ( sortOrder ) { hasDuplicate = baseHasDuplicate; results.sort(sortOrder); if ( hasDuplicate ) { for ( var i = 1; i < results.length; i++ ) { if ( results[i] === results[i-1] ) { results.splice(i--, 1); } } } } return results; }; Sizzle.matches = function(expr, set){ return Sizzle(expr, null, null, set); }; Sizzle.find = function(expr, context, isXML){ var set, match; if ( !expr ) { return []; } for ( var i = 0, l = Expr.order.length; i < l; i++ ) { var type = Expr.order[i], match; if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { var left = match[1]; match.splice(1,1); if ( left.substr( left.length - 1 ) !== "\\" ) { match[1] = (match[1] || "").replace(/\\/g, ""); set = Expr.find[ type ]( match, context, isXML ); if ( set != null ) { expr = expr.replace( Expr.match[ type ], "" ); break; } } } } if ( !set ) { set = context.getElementsByTagName("*"); } return {set: set, expr: expr}; }; Sizzle.filter = function(expr, set, inplace, not){ var old = expr, result = [], curLoop = set, match, anyFound, isXMLFilter = set && set[0] && isXML(set[0]); while ( expr && set.length ) { for ( var type in Expr.filter ) { if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { var filter = Expr.filter[ type ], found, item, left = match[1]; anyFound = false; match.splice(1,1); if ( left.substr( left.length - 1 ) === "\\" ) { continue; } if ( curLoop === result ) { result = []; } if ( Expr.preFilter[ type ] ) { match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); if ( !match ) { anyFound = found = true; } else if ( match === true ) { continue; } } if ( match ) { for ( var i = 0; (item = curLoop[i]) != null; i++ ) { if ( item ) { found = filter( item, match, i, curLoop ); var pass = not ^ !!found; if ( inplace && found != null ) { if ( pass ) { anyFound = true; } else { curLoop[i] = false; } } else if ( pass ) { result.push( item ); anyFound = true; } } } } if ( found !== undefined ) { if ( !inplace ) { curLoop = result; } expr = expr.replace( Expr.match[ type ], "" ); if ( !anyFound ) { return []; } break; } } } // Improper expression if ( expr === old ) { if ( anyFound == null ) { Sizzle.error( expr ); } else { break; } } old = expr; } return curLoop; }; Sizzle.error = function( msg ) { throw "Syntax error, unrecognized expression: " + msg; }; var Expr = Sizzle.selectors = { order: [ "ID", "NAME", "TAG" ], match: { ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/, CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/, NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/, ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/, CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ }, leftMatch: {}, attrMap: { "class": "className", "for": "htmlFor" }, attrHandle: { href: function(elem){ return elem.getAttribute("href"); } }, relative: { "+": function(checkSet, part){ var isPartStr = typeof part === "string", isTag = isPartStr && !/\W/.test(part), isPartStrNotTag = isPartStr && !isTag; if ( isTag ) { part = part.toLowerCase(); } for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { if ( (elem = checkSet[i]) ) { while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? elem || false : elem === part; } } if ( isPartStrNotTag ) { Sizzle.filter( part, checkSet, true ); } }, ">": function(checkSet, part){ var isPartStr = typeof part === "string"; if ( isPartStr && !/\W/.test(part) ) { part = part.toLowerCase(); for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { var parent = elem.parentNode; checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; } } } else { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { checkSet[i] = isPartStr ? elem.parentNode : elem.parentNode === part; } } if ( isPartStr ) { Sizzle.filter( part, checkSet, true ); } } }, "": function(checkSet, part, isXML){ var doneName = done++, checkFn = dirCheck; if ( typeof part === "string" && !/\W/.test(part) ) { var nodeCheck = part = part.toLowerCase(); checkFn = dirNodeCheck; } checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); }, "~": function(checkSet, part, isXML){ var doneName = done++, checkFn = dirCheck; if ( typeof part === "string" && !/\W/.test(part) ) { var nodeCheck = part = part.toLowerCase(); checkFn = dirNodeCheck; } checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); } }, find: { ID: function(match, context, isXML){ if ( typeof context.getElementById !== "undefined" && !isXML ) { var m = context.getElementById(match[1]); return m ? [m] : []; } }, NAME: function(match, context){ if ( typeof context.getElementsByName !== "undefined" ) { var ret = [], results = context.getElementsByName(match[1]); for ( var i = 0, l = results.length; i < l; i++ ) { if ( results[i].getAttribute("name") === match[1] ) { ret.push( results[i] ); } } return ret.length === 0 ? null : ret; } }, TAG: function(match, context){ return context.getElementsByTagName(match[1]); } }, preFilter: { CLASS: function(match, curLoop, inplace, result, not, isXML){ match = " " + match[1].replace(/\\/g, "") + " "; if ( isXML ) { return match; } for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { if ( elem ) { if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) { if ( !inplace ) { result.push( elem ); } } else if ( inplace ) { curLoop[i] = false; } } } return false; }, ID: function(match){ return match[1].replace(/\\/g, ""); }, TAG: function(match, curLoop){ return match[1].toLowerCase(); }, CHILD: function(match){ if ( match[1] === "nth" ) { // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); // calculate the numbers (first)n+(last) including if they are negative match[2] = (test[1] + (test[2] || 1)) - 0; match[3] = test[3] - 0; } // TODO: Move to normal caching system match[0] = done++; return match; }, ATTR: function(match, curLoop, inplace, result, not, isXML){ var name = match[1].replace(/\\/g, ""); if ( !isXML && Expr.attrMap[name] ) { match[1] = Expr.attrMap[name]; } if ( match[2] === "~=" ) { match[4] = " " + match[4] + " "; } return match; }, PSEUDO: function(match, curLoop, inplace, result, not){ if ( match[1] === "not" ) { // If we're dealing with a complex expression, or a simple one if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { match[3] = Sizzle(match[3], null, null, curLoop); } else { var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); if ( !inplace ) { result.push.apply( result, ret ); } return false; } } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { return true; } return match; }, POS: function(match){ match.unshift( true ); return match; } }, filters: { enabled: function(elem){ return elem.disabled === false && elem.type !== "hidden"; }, disabled: function(elem){ return elem.disabled === true; }, checked: function(elem){ return elem.checked === true; }, selected: function(elem){ // Accessing this property makes selected-by-default // options in Safari work properly elem.parentNode.selectedIndex; return elem.selected === true; }, parent: function(elem){ return !!elem.firstChild; }, empty: function(elem){ return !elem.firstChild; }, has: function(elem, i, match){ return !!Sizzle( match[3], elem ).length; }, header: function(elem){ return /h\d/i.test( elem.nodeName ); }, text: function(elem){ return "text" === elem.type; }, radio: function(elem){ return "radio" === elem.type; }, checkbox: function(elem){ return "checkbox" === elem.type; }, file: function(elem){ return "file" === elem.type; }, password: function(elem){ return "password" === elem.type; }, submit: function(elem){ return "submit" === elem.type; }, image: function(elem){ return "image" === elem.type; }, reset: function(elem){ return "reset" === elem.type; }, button: function(elem){ return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; }, input: function(elem){ return /input|select|textarea|button/i.test(elem.nodeName); } }, setFilters: { first: function(elem, i){ return i === 0; }, last: function(elem, i, match, array){ return i === array.length - 1; }, even: function(elem, i){ return i % 2 === 0; }, odd: function(elem, i){ return i % 2 === 1; }, lt: function(elem, i, match){ return i < match[3] - 0; }, gt: function(elem, i, match){ return i > match[3] - 0; }, nth: function(elem, i, match){ return match[3] - 0 === i; }, eq: function(elem, i, match){ return match[3] - 0 === i; } }, filter: { PSEUDO: function(elem, match, i, array){ var name = match[1], filter = Expr.filters[ name ]; if ( filter ) { return filter( elem, i, match, array ); } else if ( name === "contains" ) { return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; } else if ( name === "not" ) { var not = match[3]; for ( var i = 0, l = not.length; i < l; i++ ) { if ( not[i] === elem ) { return false; } } return true; } else { Sizzle.error( "Syntax error, unrecognized expression: " + name ); } }, CHILD: function(elem, match){ var type = match[1], node = elem; switch (type) { case 'only': case 'first': while ( (node = node.previousSibling) ) { if ( node.nodeType === 1 ) { return false; } } if ( type === "first" ) { return true; } node = elem; case 'last': while ( (node = node.nextSibling) ) { if ( node.nodeType === 1 ) { return false; } } return true; case 'nth': var first = match[2], last = match[3]; if ( first === 1 && last === 0 ) { return true; } var doneName = match[0], parent = elem.parentNode; if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { var count = 0; for ( node = parent.firstChild; node; node = node.nextSibling ) { if ( node.nodeType === 1 ) { node.nodeIndex = ++count; } } parent.sizcache = doneName; } var diff = elem.nodeIndex - last; if ( first === 0 ) { return diff === 0; } else { return ( diff % first === 0 && diff / first >= 0 ); } } }, ID: function(elem, match){ return elem.nodeType === 1 && elem.getAttribute("id") === match; }, TAG: function(elem, match){ return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; }, CLASS: function(elem, match){ return (" " + (elem.className || elem.getAttribute("class")) + " ") .indexOf( match ) > -1; }, ATTR: function(elem, match){ var name = match[1], result = Expr.attrHandle[ name ] ? Expr.attrHandle[ name ]( elem ) : elem[ name ] != null ? elem[ name ] : elem.getAttribute( name ), value = result + "", type = match[2], check = match[4]; return result == null ? type === "!=" : type === "=" ? value === check : type === "*=" ? value.indexOf(check) >= 0 : type === "~=" ? (" " + value + " ").indexOf(check) >= 0 : !check ? value && result !== false : type === "!=" ? value !== check : type === "^=" ? value.indexOf(check) === 0 : type === "$=" ? value.substr(value.length - check.length) === check : type === "|=" ? value === check || value.substr(0, check.length + 1) === check + "-" : false; }, POS: function(elem, match, i, array){ var name = match[2], filter = Expr.setFilters[ name ]; if ( filter ) { return filter( elem, i, match, array ); } } } }; var origPOS = Expr.match.POS; for ( var type in Expr.match ) { Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source ); Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, function(all, num){ return "\\" + (num - 0 + 1); })); } var makeArray = function(array, results) { array = Array.prototype.slice.call( array, 0 ); if ( results ) { results.push.apply( results, array ); return results; } return array; }; // Perform a simple check to determine if the browser is capable of // converting a NodeList to an array using builtin methods. // Also verifies that the returned array holds DOM nodes // (which is not the case in the Blackberry browser) try { Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; // Provide a fallback method if it does not work } catch(e){ makeArray = function(array, results) { var ret = results || []; if ( toString.call(array) === "[object Array]" ) { Array.prototype.push.apply( ret, array ); } else { if ( typeof array.length === "number" ) { for ( var i = 0, l = array.length; i < l; i++ ) { ret.push( array[i] ); } } else { for ( var i = 0; array[i]; i++ ) { ret.push( array[i] ); } } } return ret; }; } var sortOrder; if ( document.documentElement.compareDocumentPosition ) { sortOrder = function( a, b ) { if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { if ( a == b ) { hasDuplicate = true; } return a.compareDocumentPosition ? -1 : 1; } var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; if ( ret === 0 ) { hasDuplicate = true; } return ret; }; } else if ( "sourceIndex" in document.documentElement ) { sortOrder = function( a, b ) { if ( !a.sourceIndex || !b.sourceIndex ) { if ( a == b ) { hasDuplicate = true; } return a.sourceIndex ? -1 : 1; } var ret = a.sourceIndex - b.sourceIndex; if ( ret === 0 ) { hasDuplicate = true; } return ret; }; } else if ( document.createRange ) { sortOrder = function( a, b ) { if ( !a.ownerDocument || !b.ownerDocument ) { if ( a == b ) { hasDuplicate = true; } return a.ownerDocument ? -1 : 1; } var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); aRange.setStart(a, 0); aRange.setEnd(a, 0); bRange.setStart(b, 0); bRange.setEnd(b, 0); var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange); if ( ret === 0 ) { hasDuplicate = true; } return ret; }; } // Utility function for retreiving the text value of an array of DOM nodes function getText( elems ) { var ret = "", elem; for ( var i = 0; elems[i]; i++ ) { elem = elems[i]; // Get the text from text nodes and CDATA nodes if ( elem.nodeType === 3 || elem.nodeType === 4 ) { ret += elem.nodeValue; // Traverse everything else, except comment nodes } else if ( elem.nodeType !== 8 ) { ret += getText( elem.childNodes ); } } return ret; } // Check to see if the browser returns elements by name when // querying by getElementById (and provide a workaround) (function(){ // We're going to inject a fake input element with a specified name var form = document.createElement("div"), id = "script" + (new Date).getTime(); form.innerHTML = "<a name='" + id + "'/>"; // Inject it into the root element, check its status, and remove it quickly var root = document.documentElement; root.insertBefore( form, root.firstChild ); // The workaround has to do additional checks after a getElementById // Which slows things down for other browsers (hence the branching) if ( document.getElementById( id ) ) { Expr.find.ID = function(match, context, isXML){ if ( typeof context.getElementById !== "undefined" && !isXML ) { var m = context.getElementById(match[1]); return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; } }; Expr.filter.ID = function(elem, match){ var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); return elem.nodeType === 1 && node && node.nodeValue === match; }; } root.removeChild( form ); root = form = null; // release memory in IE })(); (function(){ // Check to see if the browser returns only elements // when doing getElementsByTagName("*") // Create a fake element var div = document.createElement("div"); div.appendChild( document.createComment("") ); // Make sure no comments are found if ( div.getElementsByTagName("*").length > 0 ) { Expr.find.TAG = function(match, context){ var results = context.getElementsByTagName(match[1]); // Filter out possible comments if ( match[1] === "*" ) { var tmp = []; for ( var i = 0; results[i]; i++ ) { if ( results[i].nodeType === 1 ) { tmp.push( results[i] ); } } results = tmp; } return results; }; } // Check to see if an attribute returns normalized href attributes div.innerHTML = "<a href='#'></a>"; if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && div.firstChild.getAttribute("href") !== "#" ) { Expr.attrHandle.href = function(elem){ return elem.getAttribute("href", 2); }; } div = null; // release memory in IE })(); if ( document.querySelectorAll ) { (function(){ var oldSizzle = Sizzle, div = document.createElement("div"); div.innerHTML = "<p class='TEST'></p>"; // Safari can't handle uppercase or unicode characters when // in quirks mode. if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { return; } Sizzle = function(query, context, extra, seed){ context = context || document; // Only use querySelectorAll on non-XML documents // (ID selectors don't work in non-HTML documents) if ( !seed && context.nodeType === 9 && !isXML(context) ) { try { return makeArray( context.querySelectorAll(query), extra ); } catch(e){} } return oldSizzle(query, context, extra, seed); }; for ( var prop in oldSizzle ) { Sizzle[ prop ] = oldSizzle[ prop ]; } div = null; // release memory in IE })(); } (function(){ var div = document.createElement("div"); div.innerHTML = "<div class='test e'></div><div class='test'></div>"; // Opera can't find a second classname (in 9.6) // Also, make sure that getElementsByClassName actually exists if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { return; } // Safari caches class attributes, doesn't catch changes (in 3.2) div.lastChild.className = "e"; if ( div.getElementsByClassName("e").length === 1 ) { return; } Expr.order.splice(1, 0, "CLASS"); Expr.find.CLASS = function(match, context, isXML) { if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { return context.getElementsByClassName(match[1]); } }; div = null; // release memory in IE })(); function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { elem = elem[dir]; var match = false; while ( elem ) { if ( elem.sizcache === doneName ) { match = checkSet[elem.sizset]; break; } if ( elem.nodeType === 1 && !isXML ){ elem.sizcache = doneName; elem.sizset = i; } if ( elem.nodeName.toLowerCase() === cur ) { match = elem; break; } elem = elem[dir]; } checkSet[i] = match; } } } function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { elem = elem[dir]; var match = false; while ( elem ) { if ( elem.sizcache === doneName ) { match = checkSet[elem.sizset]; break; } if ( elem.nodeType === 1 ) { if ( !isXML ) { elem.sizcache = doneName; elem.sizset = i; } if ( typeof cur !== "string" ) { if ( elem === cur ) { match = true; break; } } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { match = elem; break; } } elem = elem[dir]; } checkSet[i] = match; } } } var contains = document.compareDocumentPosition ? function(a, b){ return !!(a.compareDocumentPosition(b) & 16); } : function(a, b){ return a !== b && (a.contains ? a.contains(b) : true); }; var isXML = function(elem){ // documentElement is verified for cases where it doesn't yet exist // (such as loading iframes in IE - #4833) var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; }; var posProcess = function(selector, context){ var tmpSet = [], later = "", match, root = context.nodeType ? [context] : context; // Position selectors must be done after the filter // And so must :not(positional) so we move all PSEUDOs to the end while ( (match = Expr.match.PSEUDO.exec( selector )) ) { later += match[0]; selector = selector.replace( Expr.match.PSEUDO, "" ); } selector = Expr.relative[selector] ? selector + "*" : selector; for ( var i = 0, l = root.length; i < l; i++ ) { Sizzle( selector, root[i], tmpSet ); } return Sizzle.filter( later, tmpSet ); }; return Sizzle; })
define(‘ninja/event-scribe’,,function() {
function EventScribe() { this.handlers = {} this.currentElement = null } EventScribe.prototype = { //I'll be frank: I don't remember what this method is for, //so I'm not comfortable keeping it in play.
// makeHandlersRemove: function(element) { // for(var eventName in this.handlers) { // var handler = this.handlers // this.handlers = function(eventRecord) { // var res = handler.call(eventRecord) // //jQuery(element).remove() // return res // } // } // },
recordEventHandlers: function (context, behavior) { if(this.currentElement !== context.element) { if(this.currentElement !== null) { //this.makeHandlersRemove(this.currentElement) this.applyEventHandlers(this.currentElement) this.handlers = {} } this.currentElement = context.element } for(var eventName in behavior.eventHandlers) { var oldHandler = this.handlers[eventName] if(typeof oldHandler == "undefined") { oldHandler = function(){return true} } this.handlers[eventName] = behavior.buildHandler(context, eventName, oldHandler) } }, applyEventHandlers: function(element) { for(var eventName in this.handlers) { jQuery(element).bind(eventName, this.handlers[eventName]) } } } return EventScribe })
define(‘ninja/behavior-collection’,[“sizzle-1.0”, “ninja/behaviors”, “utils”, “ninja/event-scribe”, “ninja/exceptions”],
function(Sizzle, Behaviors, Utils, EventScribe, Exceptions) { var forEach = Utils.forEach var log = Utils.log var TransformFailedException = Exceptions.TransformFailed var CouldntChooseException = Exceptions.CouldntChoose function BehaviorCollection(tools) { this.lexicalCount = 0 this.eventQueue = [] this.behaviors = {} this.selectors = [] this.mutationTargets = [] this.tools = tools return this } BehaviorCollection.prototype = { addBehavior: function(selector, behavior) { if(Utils.isArray(behavior)) { forEach(behavior, function(behaves){ this.addBehavior(selector, behaves) }, this) } else if(behavior instanceof Behaviors.base) { this.insertBehavior(selector, behavior) } else if(behavior instanceof Behaviors.select) { this.insertBehavior(selector, behavior) } else if(behavior instanceof Behaviors.meta) { this.insertBehavior(selector, behavior) } else if(typeof behavior == "function"){ this.addBehavior(selector, behavior()) } else { var behavior = new Behaviors.base(behavior) this.addBehavior(selector, behavior) } }, insertBehavior: function(selector, behavior) { behavior.lexicalOrder = this.lexicalCount this.lexicalCount += 1 if(this.behaviors[selector] === undefined) { this.selectors.push(selector) this.behaviors[selector] = [behavior] } else { this.behaviors[selector].push(behavior) } }, addMutationTargets: function(targets) { this.mutationTargets = this.mutationTargets.concat(targets) }, //Move to Tools fireMutationEvent: function() { var targets = this.mutationTargets if (targets.length > 0 ) { for(var target = targets[0]; targets.length > 0; target = targets.shift()) { jQuery(target).trigger("thisChangedDOM") } } else { this.tools.getRootOfDocument().trigger("thisChangedDOM") } }, mutationEventTriggered: function(evnt){ if(this.eventQueue.length == 0){ log("mutation event - first") this.enqueueEvent(evnt) this.handleQueue() } else { log("mutation event - queueing") this.enqueueEvent(evnt) } }, enqueueEvent: function(evnt) { var eventCovered = false var uncovered = [] forEach(this.eventQueue, function(val) { eventCovered = eventCovered || jQuery.contains(val.target, evnt.target) if (!(jQuery.contains(evnt.target, val.target))) { uncovered.push(val) } }) if(!eventCovered) { uncovered.unshift(evnt) this.eventQueue = uncovered } }, handleQueue: function(){ while (this.eventQueue.length != 0){ this.applyAll(this.eventQueue[0].target) this.eventQueue.shift() } }, applyBehaviorsTo: function(element, behaviors) { return this.applyBehaviorsInContext(new this.tools.behaviorContext, element, behaviors) }, applyBehaviorsInContext: function(context, element, behaviors) { var curContext, applyList = [], scribe = new EventScribe //Move enrich to Utils this.tools.enrich(scribe.handlers, context.eventHandlerSet) behaviors = behaviors.sort(function(left, right) { if(left.priority != right.priority) { if(left.priority === undefined) { return -1 } else if(right.priority === undefined) { return 1 } else { return left.priority - right.priority } } else { return left.lexicalOrder - right.lexicalOrder } } ) forEach(behaviors, function(behavior){ //XXX This needs to have exception handling back try { curContext = behavior.inContext(context) element = behavior.applyTransform(curContext, element) context = curContext context.element = element scribe.recordEventHandlers(context, behavior) } catch(ex) { if(ex instanceof TransformFailedException) { log("!!! Transform failed") } else { log(ex) throw ex } } } ) jQuery(element).data("ninja-visited", context) scribe.applyEventHandlers(element) //Move enrich to utils this.tools.enrich(context.eventHandlerSet, scribe.handlers) this.fireMutationEvent() return element }, collectBehaviors: function(element, collection, behaviors) { forEach(behaviors, function(val) { try { collection.push(val.choose(element)) } catch(ex) { if(ex instanceof CouldntChooseException) { log("!!! couldn't choose") } else { log(ex) throw(ex) } } }) }, //XXX Still doesn't quite handle the sub-behavior case - order of application apply: function(element, startBehaviors, selectorIndex) { var applicableBehaviors = [], len = this.selectors.length this.collectBehaviors(element, applicableBehaviors, startBehaviors) var context = jQuery(element).data('ninja-visited') if (!context) { if(typeof selectorIndex == "undefined") { selectorIndex = 0 } for(var j = selectorIndex; j < len; j++) { if(jQuery(element).is(this.selectors[j])) { this.collectBehaviors(element, applicableBehaviors, this.behaviors[this.selectors[j]]) } } this.applyBehaviorsTo(element, applicableBehaviors) } else { context.unbindHandlers() this.applyBehaviorsInContext(context, element, applicableBehaviors) } }, applyAll: function(root){ var len = this.selectors.length for(var i = 0; i < len; i++) { var collection = this //Sizzle? forEach(Sizzle( this.selectors[i], root), //an array, not a jQuery function(elem){ if (!jQuery(elem).data("ninja-visited")) { //Pure optimization collection.apply(elem, [], i) } }) // jQuery(root).find(this.selectors[i]).each( // function(index, elem){ // if (!jQuery(elem).data("ninja-visited")) { //Pure optimization // collection.apply(elem, [], i) // } // } // ) } } } return BehaviorCollection })
define(‘ninja/root-context’,, function(Utils) {
var forEach = Utils.forEach return function(tools) { function RootContext() { this.stashedElements = [] this.eventHandlerSet = {} } RootContext.prototype = tools.enrich( tools, { stash: function(element) { this.stashedElements.unshift(element) }, unstash: function() { return this.stashedElements.shift() }, clearStash: function() { this.stashedElements = [] }, //XXX Of concern: how do cascading events work out? //Should there be a first catch? Or a "doesn't cascade" or something? cascadeEvent: function(event) { var formDiv = Ninja.tools.hiddenDiv() forEach(this.stashedElements, function(element) { var elem = jQuery(element) elem.data("ninja-visited", this) jQuery(formDiv).append(elem) elem.trigger(event) }) }, unbindHandlers: function() { var el = jQuery(this.element) for(eventName in this.eventHandlerSet) { el.unbind(eventName, this.eventHandlerSet[eventName]) } } }) return RootContext } })
define(‘ninja/tools’,[ “ninja/behaviors”, “ninja/behavior-collection”, “ninja/exceptions”,
"utils", "ninja/root-context" ], function( Behaviors, BehaviorCollection, Exceptions, Utils, rootContext ) { var CantTransformException = Exceptions.CantTransform var log = Utils.log function Tools(ninja) { this.ninja = ninja this.behaviorContext = rootContext(this) } Tools.prototype = { //Handy JS things forEach: Utils.forEach, enrich: function(left, right) { return jQuery.extend(left, right) }, ensureDefaults: function(config, defaults) { if(!(config instanceof Object)) { config = {} } for(var key in defaults) { if(typeof config[key] == "undefined") { if(typeof this.ninja.config[key] != "undefined") { config[key] = this.ninja.config[key] } else if(typeof defaults[key] != "undefined") { config[key] = defaults[key] } } } return config }, //DOM and Events getRootOfDocument: function() { return jQuery("html") //document.firstChild) }, clearRootCollection: function() { this.ninja.behavior = this.ninja.goodBehavior this.getRootOfDocument().data("ninja-behavior", null) }, getRootCollection: function() { var rootOfDocument = this.getRootOfDocument() if(rootOfDocument.data("ninja-behavior") instanceof BehaviorCollection) { return rootOfDocument.data("ninja-behavior") } var collection = new BehaviorCollection(this) rootOfDocument.data("ninja-behavior", collection); return collection }, addMutationTargets: function(targets) { this.getRootCollection().addMutationTargets(targets) }, fireMutationEvent: function() { this.getRootCollection().fireMutationEvent() }, detachSyntheticMutationEvents: function() { this.getRootCollection().fireMutationEvent = function(){} this.getRootCollection().addMutationTargets = function(t){} }, //HTML Utils copyAttributes: function(from, to, which) { var attributeList = [] var attrs = [] var match = new RegExp("^" + which.join("$|^") + "$") to = jQuery(to) this.forEach(from.attributes, function(att) { if(match.test(att.nodeName)) { to.attr(att.nodeName, att.nodeValue) } }) }, deriveElementsFrom: function(element, means){ switch(typeof means){ case 'undefined': return element case 'string': return jQuery(means) case 'function': return means(element) } }, extractMethod: function(element, formData) { if(element.dataset !== undefined && element.dataset["method"] !== undefined && element.dataset["method"].length > 0) { log("Override via dataset: " + element.dataset["method"]) return element.dataset["method"] } if(element.dataset === undefined && jQuery(element).attr("data-method") !== undefined) { log("Override via data-method: " + jQuery(element).attr("data-method")) return jQuery(element).attr("data-method") } if(typeof formData !== "undefined") { for(var i=0, len = formData.length; i<len; i++) { if(formData[i].name == "Method") { log("Override via Method: " + formData[i].value) return formData[i].value } } } if(typeof element.method !== "undefined") { return element.method } return "GET" }, //Ninjascript utils cantTransform: function() { throw new TransformFailedException }, applyBehaviors: function(element, behaviors) { this.getRootCollection().apply(element, behaviors) }, message: function(text, classes) { var addingMessage = this.ninja.config.messageWrapping(text, classes) jQuery(this.ninja.config.messageList).append(addingMessage) }, hiddenDiv: function() { var existing = jQuery("div#ninja-hide") if(existing.length > 0) { return existing[0] } var hide = jQuery("<div id='ninja-hide'></div>").css("display", "none") jQuery("body").append(hide) this.getRootCollection().applyBehaviorsTo(hide, [this.ninja.suppressChangeEvents()]) return hide } } return Tools; })
define(‘ninja/configuration’,,function() {
return { //This is the half-assed: it should be template of some sort messageWrapping: function(text, classes) { return "<div class='flash " + classes +"'><p>" + text + "</p></div>" }, messageList: "#messages", busyLaziness: 200 } })
define(‘ninja/tools/json-dispatcher’,, function(Utils) {
function JSONDispatcher() { this.handlers = [] } JSONDispatcher.prototype = { addHandler: function(handler) { this.handlers.push({ handler: new JSONHandler(handler) }) }, dispatch: function(json) { var len = this.handlers.length for(var i = 0; i < len; i++) { try { this.handlers[i].handler.receive(json) } catch(problem) { Utils.log("Caught: " + problem + " while handling JSON response.") } } } } function JSONHandler(desc) { this.desc = desc } /** * Intention is to use JSONHandler like this: * * this.ajaxToJson({ * item: function(html) { * $('#items').append($(html)) * }, * item_count: function(html) { * $('#item_count').replace($(html)) * } * }) * * And the server sends back something like: * * { "item": "<li>A list item<\li>", "item_count": 17 } **/ JSONHandler.prototype = { receive: function (data) { this.compose([], data, this.desc) return null }, compose: function(path, data, desc) { if(typeof desc == "function") { try { desc.call(this, data) //Individual functions can share data through handler } catch(problem) { Utils.log("Caught: " + problem + " while handling JSON at " + path.join("/")) } } else { for(var key in data) { if(data.hasOwnProperty(key)) { if( key in desc) { this.compose(path.concat([key]), data[key], desc[key]) } } } } return null } } return JSONDispatcher })
define(‘ninja’,[“utils”, “ninja/tools”, “ninja/behaviors”, “ninja/configuration”, ‘ninja/tools/json-dispatcher’],
function(Utils, Tools, Behaviors, Configs, JSONDispatcher) { var log = Utils.log function NinjaScript() { //NinjaScript-wide configurations. Currently, not very many this.config = Configs this.behavior = this.goodBehavior this.jsonDispatcher = new JSONDispatcher() this.tools = new Tools(this) } NinjaScript.prototype = { packageBehaviors: function(callback) { var types = { does: Behaviors.base, chooses: Behaviors.meta, selects: Behaviors.select } result = callback(types) this.tools.enrich(this, result) }, packageTools: function(object) { this.tools.enrich(Tools.prototype, object) }, configure: function(opts) { this.tools.enrich(this.config, opts) }, goodBehavior: function(dispatching) { var collection = this.tools.getRootCollection() for(var selector in dispatching) { if(typeof dispatching[selector] == "undefined") { log("Selector " + selector + " not properly defined - ignoring") } else { collection.addBehavior(selector, dispatching[selector]) } } jQuery(window).load( function(){ Ninja.go() } ) }, badBehavior: function(nonsense) { throw new Error("Called Ninja.behavior() after Ninja.go() - don't do that. 'Go' means 'I'm done, please proceed'") }, respondToJson: function(handlerConfig) { this.jsonDispatcher.addHandler(handlerConfig) }, go: function() { var Ninja = this function handleMutation(evnt) { Ninja.tools.getRootCollection().mutationEventTriggered(evnt); } if(this.behavior != this.misbehavior) { var rootOfDocument = this.tools.getRootOfDocument() rootOfDocument.bind("DOMSubtreeModified DOMNodeInserted thisChangedDOM", handleMutation); //If we ever receive either of the W3C DOMMutation events, we don't need our IE based //hack, so nerf it rootOfDocument.one("DOMSubtreeModified DOMNodeInserted", function(){ Ninja.tools.detachSyntheticMutationEvents() }) this.behavior = this.badBehavior this.tools.fireMutationEvent() } } } return new NinjaScript() })
define(‘ninja/behaviors/utility’,, function(Ninja) {
Ninja.packageBehaviors(function(ninja) { return { suppressChangeEvents: function() { return new ninja.does({ events: { DOMSubtreeModified: function(e){}, DOMNodeInserted: function(e){} } }) } } }) })
define(‘ninja/behaviors/standard’,[“ninja”, “utils”],
function(Ninja, Utils) { var log = Utils.log Ninja.packageBehaviors( function(ninja){ return { /** * Ninja.submitsAsAjax(configs) -> null * - configs(Object): configuration for the behavior, passed directly * to either submitsAsAjaxLink or submitsAsAjaxForm * * Converts either a link or a form to send its requests via AJAX - we * eval the Javascript we get back. We get an busy overlay if * configured to do so. * * This farms out the actual behavior to submitsAsAjaxLink and * submitsAsAjaxForm, c.f. **/ submitsAsAjax: function(configs) { return new ninja.chooses(function(meta) { meta.asLink = Ninja.submitsAsAjaxLink(configs), meta.asForm = Ninja.submitsAsAjaxForm(configs) }, function(elem) { switch(elem.tagName.toLowerCase()) { case "a": return this.asLink case "form": return this.asForm } }) }, /** * Ninja.submitAsAjaxLink( configs ) -> null * * Converts a link to send its GET request via Ajax - we assume that we * get Javascript back, which is eval'd. While we're waiting, we'll * throw up a busy overlay if configured to do so. By default, we don't * use a busy overlay. * **/ submitsAsAjaxLink: function(configs) { configs = Ninja.tools.ensureDefaults(configs, { busyElement: function(elem) { return $(elem).parents('address,blockquote,body,dd,div,p,dl,dt,table,form,ol,ul,tr')[0] }}) return new ninja.does({ priority: 10, helpers: { findOverlay: function(elem) { return this.deriveElementsFrom(elem, configs.busyElement) } }, events: { click: function(evnt) { this.overlayAndSubmit(evnt.target, evnt.target.href, configs.actions) } } }) }, /** * Ninja.submitAsAjaxForm(configs) -> null * * Converts a form to send its request via Ajax - we assume that we get * Javascript back, which is eval'd. We pull the method from the form: * either from the method attribute itself, a data-method attribute or a * Method input. While we're waiting, we'll throw up a busy overlay if * configured to do so. By default, we use the form itself as the busy * element. * **/ submitsAsAjaxForm: function(configs) { configs = Ninja.tools.ensureDefaults(configs, { busyElement: undefined }) return new ninja.does({ priority: 10, helpers: { findOverlay: function(elem) { return this.deriveElementsFrom(elem, configs.busyElement) } }, events: { submit: function(evnt) { this.overlayAndSubmit(evnt.target, evnt.target.action, configs.actions) } } }) }, /** * Ninja.becomesAjaxLink( configs ) -> null * * Converts a whole form into a link that submits via AJAX. The * intention is that you create a <form> elements with hidden inputs and * a single submit button - then when we transform it, you don't lose * anything in terms of user interface. Like submitsAsAjaxForm, it will * put up a busy overlay - by default we overlay the element itself **/ becomesAjaxLink: function(configs) { configs = Ninja.tools.ensureDefaults(configs, { busyElement: undefined, retainedFormAttributes: ["id", "class", "lang", "dir", "title", "data-.*"] }) return [ Ninja.submitsAsAjax(configs), Ninja.becomesLink(configs) ] }, /** * Ninja.becomesLink( configs ) -> null * * Replaces a form with a link - the text of the link is based on the * Submit input of the form. The form itself is pulled out of the * document until the link is clicked, at which point, it gets stuffed * back into the document and submitted, so the link behaves exactly * link submitting the form with its default inputs. The motivation is * to use hidden-input-only forms for POST interactions, which * Javascript can convert into links if you want. * **/ becomesLink: function(configs) { configs = Ninja.tools.ensureDefaults(configs, { retainedFormAttributes: ["id", "class", "lang", "dir", "title", "rel", "data-.*"] }) return new ninja.does({ priority: 30, transform: function(form){ var linkText if ((images = jQuery('input[type=image]', form)).size() > 0){ image = images[0] linkText = "<img src='" + image.src + "' alt='" + image.alt +"'"; } else if((submits = jQuery('input[type=submit]', form)).size() > 0) { submit = submits[0] if(submits.size() > 1) { log("Multiple submits. Using: " + submit) } linkText = submit.value } else { log("Couldn't find a submit input in form"); this.cantTransform() } var link = jQuery("<a rel='nofollow' href='#'>" + linkText + "</a>") this.copyAttributes(form, link, configs.retainedFormAttributes) this.stash(jQuery(form).replaceWith(link)) return link }, events: { click: function(evnt, elem){ this.cascadeEvent("submit") } } }) }, /** * Ninja.decay( configs ) -> null * * Use for elements that should be transient. For instance, the * default behavior of failed AJAX calls is to insert a message into a * div#messages with a "flash" class. You can use this behavior to * have those disappear after a few seconds. * * Configs: { lifetime: 10000, diesFor: 600 } **/ decays: function(configs) { configs = Ninja.tools.ensureDefaults(configs, { lifetime: 10000, diesFor: 600 }) return new ninja.does({ priority: 100, transform: function(elem) { jQuery(elem).delay(configs.lifetime).slideUp(configs.diesFor, function(){ jQuery(elem).remove() Ninja.tools.fireMutationEvent() }) }, events: { click: [function(event) { jQuery(this.element).remove(); }, "changesDOM"] } }) } }; }) })
define(‘ninja/behaviors/placeholder’,,
function(Ninja) { Ninja.packageBehaviors( function(ninja){ function placeholderSubmitter(inputBehavior) { return new ninja.does({ priority: 1000, submit: [function(event, el, oldHandler) { inputBehavior.prepareForSubmit() oldHandler(event) }, "andDoDefault"] }) } function grabsPlaceholderText(configs) { configs = Ninja.tools.ensureDefaults(configs, { textElementSelector: function(elem) { return "*[data-for=" + elem.id + "]" }, findTextElement: function(elem) { var textHolder = $(configs.textElementSelector(elem)) if(textHolder.length == 0) { return null } return textHolder[0] } }) return new ninja.does({ priority: -10, transform: function(element) { var label = $(configs.findTextElement(element)) if( label === null ) { this.cantTransform() } this.placeholderText = label.text() $(element).attr("placeholder", label.text()) this.stash(label.detach()) } }) } //Gratefully borrowed from Modernizr var input_placeholder = !!('placeholder' in document.createElement('input')) var textarea_placeholder = !!('placeholder' in document.createElement('textarea')) if(! input_placeholder) { function alternateInput(passwordField, parentForm) { return new ninja.does({ helpers: { prepareForSubmit: function() { $(this.element).val('') } }, transform: function() { this.applyBehaviors(parentForm, [placeholderSubmitter(this)]) }, events: { focus: function(event) { var el = $(this.element) var id = el.attr("id") el.attr("id", '') el.replaceWith(passwordField) passwordField.attr("id", id) passwordField.focus() } } }) } function hasPlaceholderPassword(configs) { configs = Ninja.tools.ensureDefaults(configs, { findParentForm: function(elem) { return elem.parents('form')[0] }, retainedInputAttributes: [ "name", "class", "style", "title", "lang", "dir", "size", "maxlength", "alt", "tabindex", "accesskey", "data-.*" ] }) return new ninja.does({ priority: 1000, helpers: { swapInAlternate: function() { var el = $(this.element) var id = el.attr("id") if(el.val() == '') { el.attr("id", '') el.replaceWith(this.placeholderTextInput) this.placeholderTextInput.attr('id', id) } } }, transform: function(element) { var replacement var el = $(element) replacement = $('<input type="text">') this.copyAttributes(element, replacement, configs.retainedInputAttributes) replacement.addClass("ninja_placeholder") replacement.val(this.placeholderText) var alternate = alternateInput(el, configs.findParentForm(el)) this.applyBehaviors(replacement, [alternate]) this.placeholderTextInput = replacement this.swapInAlternate() return element }, events: { blur: function(event) { this.swapInAlternate() } } }) } } if((!input_placeholder) || (!textarea_placeholder)) { function hasPlaceholderText(configs) { configs = Ninja.tools.ensureDefaults(configs, { findParentForm: function(elem) { return elem.parents('form')[0] } }) return new ninja.does({ priority: 1000, helpers: { prepareForSubmit: function() { if($(this.element).hasClass('ninja_placeholder')) { $(this.element).val('') } } }, transform: function(element) { var el = $(element) el.addClass('ninja_placeholder') el.val(this.placeholderText) this.applyBehaviors(configs.findParentForm(el), [placeholderSubmitter(this)]) return element }, events: { focus: function(event) { if($(this.element).hasClass('ninja_placeholder')) { $(this.element).removeClass('ninja_placeholder').val('') } }, blur: function(event) { if($(this.element).val() == '') { $(this.element).addClass('ninja_placeholder').val(this.placeholderText) } } } }) } } return { hasPlaceholder: function(configs) { var behaviors = [grabsPlaceholderText(configs)] if(!input_placeholder || !textarea_placeholder) { behaviors.push( new ninja.chooses(function(meta) { if(input_placeholder) { meta.asTextInput = null meta.asPassword = null } else { meta.asTextInput = hasPlaceholderText(configs) meta.asPassword = hasPlaceholderPassword(configs) } if( textarea_placeholder) { meta.asTextArea = null } else { meta.asTextArea = hasPlaceholderText(configs) } }, function(elem) { elem = $(elem) if(elem.is("input[type=text]")) { return this.asTextInput } else if(elem.is("textarea")) { return this.asTextArea } else if(elem.is("input[type=password]")) { return this.asPassword } })) } return behaviors } } })
}) define(‘ninja/behaviors/trigger-on’,,
function(Ninja) { Ninja.packageBehaviors( function(ninja) { return { triggersOnSelect: function(configs) { configs = Ninja.tools.ensureDefaults(configs, { busyElement: undefined, placeholderText: "Select to go", placeholderValue: "instructions" }) var jsonActions = configs if (typeof(configs.actions) === "object") { jsonActions = configs.actions } return new ninja.does({ priority: 20, helpers: { findOverlay: function(elem) { return this.deriveElementsFrom(elem, configs.busyElement) } }, transform: function(form) { var select = $(form).find("select").first() if( typeof select == "undefined" ) { this.cantTransform() } select.prepend("<option value='"+ configs.placeholderValue +"'> " + configs.placeholderText + "</option>") select.val(configs.placeholderValue) $(form).find("input[type='submit']").remove() return form }, events: { change: [ function(evnt, elem) { this.overlayAndSubmit(elem, elem.action, jsonActions) }, "andDoDefault" ] } }) } }; }) })
define(‘ninja/behaviors/confirm’,,
function(Ninja){ Ninja.packageBehaviors( function(ninja) { return { confirms: function(configs) { configs = Ninja.tools.ensureDefaults(configs, { confirmMessage: function(elem){ return $(elem).attr('data-confirm') }}) if(typeof configs.confirmMessage == "string"){ message = configs.confirmMessage configs.confirmMessage = function(elem){ return message } } function confirmDefault(event,elem) { if(!confirm(configs.confirmMessage(elem))) { event.preventDefault() event.preventFallthrough() } } return new ninja.selects({ "form": new ninja.does({ priority: 20, events: { submit: [confirmDefault, "andDoDefault"] } }), "a,input": new ninja.does({ priority: 20, events: { click: [confirmDefault, "andDoDefault"] } }) }) } } }) })
define(‘ninja/behaviors/all’,[
"./utility", "./standard", "./placeholder", "./trigger-on", "./confirm" ], function(){})
define(‘ninja/tools/overlay’,[“utils”, “ninja”],
function(Utils, Ninja) { var forEach = Utils.forEach function Overlay(list) { var elements = this.convertToElementArray(list) this.laziness = 0 var ov = this this.set = jQuery(jQuery.map(elements, function(element, idx) { return ov.buildOverlayFor(element) })) } Overlay.prototype = { convertToElementArray: function(list) { var h = this switch(typeof list) { case 'undefined': return [] case 'boolean': return [] case 'string': return h.convertToElementArray(jQuery(list)) case 'function': return h.convertToElementArray(list()) case 'object': { //IE8 barfs on 'list instanceof Element' if("focus" in list && "blur" in list && !("jquery" in list)) { return [list] } else if("length" in list && "0" in list) { var result = [] forEach(list, function(element) { result = result.concat(h.convertToElementArray(element)) }) return result } else { return [] } } } }, buildOverlayFor: function(elem) { var overlay = jQuery(document.createElement("div")) var hideMe = jQuery(elem) var offset = hideMe.offset() overlay.css("position", "absolute") overlay.css("top", offset.top) overlay.css("left", offset.left) overlay.width(hideMe.outerWidth()) overlay.height(hideMe.outerHeight()) overlay.css("zIndex", "2") overlay.css("display", "none") return overlay[0] }, affix: function() { this.set.appendTo(jQuery("body")) overlaySet = this.set window.setTimeout(function() { overlaySet.css("display", "block") }, this.laziness) }, remove: function() { this.set.remove() } } Ninja.packageTools({ overlay: function() { // I really liked using //return new Overlay([].map.apply(arguments,[function(i) {return i}])) //but IE8 doesn't implement ECMA 2.6.2 5th ed. return new Overlay(jQuery.makeArray(arguments)) }, busyOverlay: function(elem) { var overlay = this.overlay(elem) overlay.set.addClass("ninja_busy") overlay.laziness = this.ninja.config.busyLaziness return overlay }, //Currently, this doesn't respect changes to the original block... //There should be an "Overlay behavior" that gets applied buildOverlayFor: function(elem) { var overlay = jQuery(document.createElement("div")) var hideMe = jQuery(elem) var offset = hideMe.offset() overlay.css("position", "absolute") overlay.css("top", offset.top) overlay.css("left", offset.left) overlay.width(hideMe.outerWidth()) overlay.height(hideMe.outerHeight()) overlay.css("zIndex", "2") return overlay } }) return Overlay })
define(‘ninja/tools/ajax-submitter’,[“ninja”, “utils”, “./json-dispatcher”, “./overlay”], function(Ninja, Utils, jH, O) {
var log = Utils.log function AjaxSubmitter() { this.formData = [] this.action = "/" this.method = "GET" this.dataType = 'script' return this } AjaxSubmitter.prototype = { submit: function() { log("Computed method: " + this.method) jQuery.ajax(this.ajaxData()) }, sourceForm: function(form) { this.formData = jQuery(form).serializeArray() }, ajaxData: function() { return { data: this.formData, dataType: this.dataType, url: this.action, type: this.method, complete: this.responseHandler(), success: this.successHandler(), error: this.onError } }, successHandler: function() { var submitter = this return function(data, statusTxt, xhr) { submitter.onSuccess(xhr, statusTxt, data) } }, responseHandler: function() { var submitter = this return function(xhr, statusTxt) { submitter.onResponse(xhr, statusTxt) Ninja.tools.fireMutationEvent() } }, onResponse: function(xhr, statusTxt) { }, onSuccess: function(xhr, statusTxt, data) { }, onError: function(xhr, statusTxt, errorThrown) { log(xhr.responseText) Ninja.tools.message("Server error: " + xhr.statusText, "error") } } Ninja.packageTools({ ajaxSubmitter: function() { return new AjaxSubmitter() }, ajaxToJson: function(desc) { var submitter = this.ajaxSubmitter() submitter.dataType = 'json' submitter.onSuccess = function(xhr, statusText, data) { Ninja.jsonDispatcher.dispatch(data) } return submitter }, overlayAndSubmit: function(target, action, jsonHandling) { var overlay = this.busyOverlay(this.findOverlay(target)) var submitter if( typeof jsonHandling == "undefined" ) { submitter = this.ajaxSubmitter() } else { submitter = this.ajaxToJson(jsonHandling) } submitter.sourceForm(target) submitter.action = action submitter.method = this.extractMethod(target, submitter.formData) submitter.onResponse = function(xhr, statusTxt) { overlay.remove() } overlay.affix() submitter.submit() } }) return AjaxSubmitter })
define(‘ninja/tools/all’,[
"./overlay", "./ajax-submitter", "./json-dispatcher" ], function() { })
define(‘ninja/jquery’,, function(Ninja) {
jQuery.extend( { ninja: Ninja, behavior: Ninja.behavior } );
}) window = {
orderList: [], orders: function(order_func){ this.orderList.push(order_func) }
} require([
"ninja", "ninja/behaviors/all", "ninja/tools/all", "ninja/jquery" ], function(Ninja, stdBehaviors, placeholder, triggerOn, allTools, jquery) { var ninjaOrders = window["Ninja"].orderList var ordersLength = ninjaOrders.length window["Ninja"] = Ninja Ninja['behavior'] = Ninja.behavior for(var i = 0; i < ordersLength; i++) { ninjaOrders[i](Ninja) } Ninja.orders = function(funk) { funk(this) //because it amuses JDL, that's why. } })
define(“main”, function(){});