├── .gitignore ├── data ├── noise.png ├── glyphicons-halflings.png ├── core.js ├── index.html ├── theme.js ├── support │ ├── command-manager.js │ ├── mode-manager.js │ └── fs.js ├── theme.css ├── text.js └── require.js ├── raw.github.com └── Gozala │ ├── events │ └── v0.5.0 │ │ └── events.js │ ├── extendables │ └── v0.2.0 │ │ └── extendables.js │ └── jetpack-protocol │ └── v0.3.0 │ └── index.js ├── package.json ├── .gitmodules ├── Readme.md ├── permissions.js ├── History.md └── main.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | http!* 3 | https!* 4 | -------------------------------------------------------------------------------- /data/noise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gozala/sky-edit/HEAD/data/noise.png -------------------------------------------------------------------------------- /data/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gozala/sky-edit/HEAD/data/glyphicons-halflings.png -------------------------------------------------------------------------------- /raw.github.com/Gozala/events/v0.5.0/events.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../../../../@modules/raw.github.com/Gozala/events/v0.5.0/events'); 2 | -------------------------------------------------------------------------------- /raw.github.com/Gozala/extendables/v0.2.0/extendables.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../../../../@modules/raw.github.com/Gozala/extendables/v0.2.0/extendables'); 2 | -------------------------------------------------------------------------------- /raw.github.com/Gozala/jetpack-protocol/v0.3.0/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../../../../@modules/raw.github.com/Gozala/jetpack-protocol/v0.3.0/index'); 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sky-edit", 3 | "id": "sky-edit", 4 | "version": "0.6.1", 5 | "description": "Editor embedded in browser.", 6 | "homepage": "http://github.com/Gozala/sky-edit/", 7 | "keywords": [ "editor", "ace", "firefox", "vim", "vice" ], 8 | "author": "Irakli Gozalishvili (http://jeditoolkit.com)", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/Gozala/sky-edit.git", 12 | "web": "https://github.com/Gozala/sky-edit" 13 | }, 14 | "bugs": { 15 | "web": "http://github.com/Gozala/sky-edit/issues/" 16 | }, 17 | "main": "./main.js", 18 | "licenses": [{ 19 | "type" : "MIT", 20 | "url" : "http://jeditoolkit.com/LICENSE" 21 | }] 22 | } 23 | -------------------------------------------------------------------------------- /data/core.js: -------------------------------------------------------------------------------- 1 | /* vim:set ts=2 sw=2 sts=2 expandtab */ 2 | /*jshint asi: true es5: true node: true browser: true devel: true */ 3 | define(function(require, exports, module) { 4 | 'use strict'; 5 | 6 | var hub = require('plugin-hub/core') 7 | var gcli = require('gcli-plug/core') 8 | var ace = require('ace-plug/core') 9 | var vice = require('vice/core') 10 | var modes = require('support/mode-manager') 11 | var commands = require('support/command-manager') 12 | var fs = require('support/fs') 13 | 14 | var env = window.env = {} 15 | 16 | hub.plug(env, hub) 17 | hub.plug(env, gcli) 18 | hub.plug(env, ace) 19 | hub.plug(env, commands) 20 | hub.plug(env, vice) 21 | hub.plug(env, modes) 22 | hub.plug(env, fs) 23 | }); 24 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "data/support/ace"] 2 | path = data/support/ace 3 | url = https://github.com/Gozala/ace.git 4 | [submodule "data/support/vice"] 5 | path = data/support/vice 6 | url = https://github.com/Gozala/vice.git 7 | [submodule "data/support/gcli"] 8 | path = data/support/gcli 9 | url = https://github.com/Gozala/gcli.git 10 | [submodule "data/support/gcli-plug"] 11 | path = data/support/gcli-plug 12 | url = https://github.com/Gozala/gcli-plug.git 13 | [submodule "data/support/ace-plug"] 14 | path = data/support/ace-plug 15 | url = https://github.com/Gozala/ace-plug.git 16 | [submodule "data/support/plugin-hub"] 17 | path = data/support/plugin-hub 18 | url = https://github.com/Gozala/plugin-hub.git 19 | [submodule "data/support/micro-promise"] 20 | path = data/support/micro-promise 21 | url = git://github.com/Gozala/micro-promise.git 22 | [submodule "@modules/raw.github.com/Gozala/extendables/v0.2.0"] 23 | path = @modules/raw.github.com/Gozala/extendables/v0.2.0 24 | url = https://github.com/Gozala/extendables.git 25 | [submodule "@modules/raw.github.com/Gozala/events/v0.5.0"] 26 | path = @modules/raw.github.com/Gozala/events/v0.5.0 27 | url = https://github.com/Gozala/events.git 28 | [submodule "@modules/raw.github.com/Gozala/jetpack-io/v0.4.2"] 29 | path = @modules/raw.github.com/Gozala/jetpack-io/v0.4.2 30 | url = https://github.com/Gozala/jetpack-io.git 31 | [submodule "@modules/raw.github.com/Gozala/jetpack-protocol/v0.3.0"] 32 | path = @modules/raw.github.com/Gozala/jetpack-protocol/v0.3.0 33 | url = https://github.com/Gozala/jetpack-protocol.git 34 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # sky-edit 2 | 3 | **This is still very alpha experiment** 4 | 5 | Skyedit is an editor embedded in browser. Some browsers support `view-source:*` 6 | type URIs for viewing page source (Try clicking 7 | [view-source:http://google.com](view-source:http://google.com) in Firefox or 8 | Chrome). In a same way you could view source for a files in the local hard drive 9 | [view-source:file:///etc/hosts](view-source:file:///etc/hosts). Would not be it 10 | nice to have similar way to edit those files ? Would not be it awesome to have 11 | an edit link 12 | [edit:https://gist.github.com/raw/648918/2520e8264bd20d9b1d58848e369ab15c9f665bd6/read-lines.js](edit:https://gist.github.com/raw/648918/2520e8264bd20d9b1d58848e369ab15c9f665bd6/read-lines.js) 13 | [on a gist page](https://gist.github.com/648918) along with embed to start 14 | editing it an editor, or just being able to navigate to 15 | [edit:file:///etc/hosts](edit:file:///etc/hosts) to edit it ? This is an 16 | experiment using [jetpack] and [ace] with an attempt to do exactly that and 17 | probably more in a future. 18 | 19 | ![Screenshot](http://f.cl.ly/items/0P312g0o0U3I210H0C0i/Screen%20Shot%202012-04-11%20at%2017.40.36%20.png "Screenshot") 20 | 21 | ## Hack 22 | 23 | git clone git://github.com/Gozala/sky-edit.git --recursive 24 | cd sky-edit 25 | 26 | ## Install 27 | 28 | Download latest .xpi file from [downloads] and drag it to firefox. 29 | 30 | [downloads]:https://github.com/Gozala/sky-edit/downloads 31 | [ace]:http://ajaxorg.github.com/ace/ 32 | [jetpack]:https://jetpack.mozillalabs.com/ 33 | [graphquire]:https://github.com/Gozala/graphquire/ 34 | -------------------------------------------------------------------------------- /data/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 19 | 20 | 21 |
22 |
23 | 24 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /permissions.js: -------------------------------------------------------------------------------- 1 | /*global define: true port: true */ 2 | /*jshint asi:true globalstrict: true */ 3 | 4 | 'use strict'; 5 | 6 | const { Cc, Ci } = require('chrome') 7 | const nsIPermissionManager = Ci.nsIPermissionManager 8 | const manager = Cc['@mozilla.org/permissionmanager;1']. 9 | getService(nsIPermissionManager) 10 | const ioService = Cc["@mozilla.org/network/io-service;1"]. 11 | getService(Ci.nsIIOService) 12 | const { UNKNOWN_ACTION, ALLOW_ACTION, DENY_ACTION } = nsIPermissionManager 13 | 14 | exports.add = function add(permission) { 15 | let { host, type, capability, expireType, expireTime } = permission 16 | let uri = ioService.newURI('http://' + host, null, null) 17 | uri.host = host 18 | 19 | capability = capability === true ? ALLOW_ACTION : 20 | capability === false ? DENY_ACTION : 21 | capability === null ? UNKNOWN_ACTION : capability 22 | 23 | manager.add(uri, String(type), capability, expireType, expireTime) 24 | } 25 | 26 | exports.remove = function remove({ host, type }) { 27 | manager.remove(host, type) 28 | } 29 | 30 | exports.permissions = function() { 31 | function tail(enumerator) { 32 | return !enumerator.hasMoreElements() ? null : Object.defineProperties({}, { 33 | head: { 34 | enumerable: true, 35 | value: enumerator.getNext().QueryInterface(Ci.nsIPermission) 36 | }, 37 | tail: { 38 | enumerable: true, 39 | get: new function(value) { 40 | return function() { 41 | return value || (value = tail(enumerator)) 42 | } 43 | } 44 | } 45 | }) 46 | } 47 | return tail(manager.enumerator) 48 | } 49 | -------------------------------------------------------------------------------- /data/theme.js: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | * 4 | * The contents of this file are subject to the Mozilla Public License Version 5 | * 1.1 (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * http://www.mozilla.org/MPL/ 8 | * 9 | * Software distributed under the License is distributed on an "AS IS" basis, 10 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | * for the specific language governing rights and limitations under the 12 | * License. 13 | * 14 | * The Original Code is Ajax.org Code Editor (ACE). 15 | * 16 | * The Initial Developer of the Original Code is 17 | * Ajax.org B.V. 18 | * Portions created by the Initial Developer are Copyright (C) 2010 19 | * the Initial Developer. All Rights Reserved. 20 | * 21 | * Contributor(s): 22 | * Fabian Jakobs 23 | * 24 | * Alternatively, the contents of this file may be used under the terms of 25 | * either the GNU General Public License Version 2 or later (the "GPL"), or 26 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 27 | * in which case the provisions of the GPL or the LGPL are applicable instead 28 | * of those above. If you wish to allow use of your version of this file only 29 | * under the terms of either the GPL or the LGPL, and not to allow others to 30 | * use your version of this file under the terms of the MPL, indicate your 31 | * decision by deleting the provisions above and replace them with the notice 32 | * and other provisions required by the GPL or the LGPL. If you do not delete 33 | * the provisions above, a recipient may use your version of this file under 34 | * the terms of any one of the MPL, the GPL or the LGPL. 35 | * 36 | * ***** END LICENSE BLOCK ***** */ 37 | 38 | define(function(require, exports, module) { 39 | 40 | exports.cssClass = "ace-ambiance"; 41 | exports.cssText = require("text!./theme.css"); 42 | 43 | }); 44 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | # History # 2 | 3 | ## 0.6.1 / 2012-04-11 4 | 5 | - Fix issues with workers to allow background jobs like jshint. 6 | - Fix open command by allowing pop-ups form `edit:` URLs. 7 | - Got rid off annoying ace hotkeys that conflict with browser ones. 8 | - Normalize URLs to avoid `/./`-s in them. 9 | 10 | ## 0.6.0 / 2012-04-10 11 | 12 | - Remove dependency on npm and graphqurie. 13 | - Introduce new independent plugin system. 14 | - Implement all features ace plugins. 15 | 16 | ## 0.5.3 / 2012-02-11 17 | 18 | - Decouple mode manager from the `fs` plugin. 19 | - Add setting `mode` for manual mode settings on buffer. 20 | - Add support for new language modes added in latest ace. 21 | 22 | ## 0.5.2 / 2012-02-10 23 | 24 | - Fix issue [#3](issues/3) with coffeescript files. 25 | - Fix issue [#2](issues/2) that breaks navigation when holding navigation 26 | keys. 27 | - Update no newer ace with code-folding. 28 | 29 | ## 0.5.0 / 2011-09-08 30 | 31 | - Improved UI 32 | - Parens highlighting. 33 | - Selection highlighting. 34 | - Updating to the latest ACE version. 35 | - `command-s` saves buffer. 36 | - More VIM bindings (`f/t/F/T/0/20G`). 37 | 38 | ## 0.4.2 / 2011-07-14 39 | 40 | - Fixing bug breaking an addon. 41 | 42 | ## 0.4.1 / 2011-07-14 43 | 44 | - Some visual improvements. 45 | - Add-on cleans up correctly after uninstall / reinstall. 46 | 47 | ## 0.4.0 / 2011-07-07 48 | 49 | - history.pushState support now changes location bar depending on loaded 50 | buffer. 51 | 52 | ## 0.3.0 / 2011-07-03 53 | 54 | - Fix undo manager. 55 | - Modify default settings. 56 | - Code refactoring & cleanup. 57 | - Fix `^` and `$` keybindings. 58 | - Improve write / edit commands feedback. 59 | - Style improvements. 60 | - Switch to URL based require. 61 | 62 | ## 0.2.2 / 2011-06-30 63 | 64 | - Updating to the latest ace version. 65 | 66 | ## 0.2.1 / 2011-06-30 67 | 68 | - Improve feedback for writing files. 69 | - Adding keyboard shortcut for jumping in and out of CLI. 70 | - Bugfixes. 71 | 72 | ## 0.2.0 / 2011-06-29 73 | 74 | - Switching to packageless module dependencies. 75 | - Simplified package structure. 76 | - Performance improvement. 77 | - Replacing hacks with actual fixes. 78 | 79 | ## 0.1.1 / 2011-06-24 80 | 81 | - Syntax highlighting for `.js` and `.json` files. 82 | - Support for file saving. 83 | 84 | ## 0.1.0 / 2011-04-06 85 | 86 | - Start managing dependencies via git-submodules. 87 | - Bugfix. 88 | 89 | ## 0.0.4 / 2011-02-07 90 | 91 | - Improved ace embedding. 92 | 93 | ## 0.0.3 / 2011-01-27 94 | 95 | - Bug fix. 96 | 97 | ## 0.0.2 / 2011-01-26 98 | 99 | - Ace update. 100 | - Vim key bindings. 101 | 102 | ## 0.0.1 / 2011-01-10 103 | 104 | - Initial implementation. 105 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | /* vim:set ts=2 sw=2 sts=2 expandtab */ 2 | /*jshint asi: true undef: true es5: true node: true devel: true 3 | forin: true latedef: false browser: true */ 4 | /*global define: true port: true */ 5 | !define(function(require, exports) { 6 | 7 | "use strict"; 8 | 9 | var data = require("self").data 10 | var PageMod = require("addon-kit/page-mod").PageMod 11 | var protocol = require("raw.github.com/Gozala/jetpack-protocol/v0.3.0/index") 12 | var fs = require("raw.github.com/Gozala/jetpack-io/v0.4.2/fs") 13 | var permissions = require('./permissions') 14 | 15 | const PROTOCOL = 'edit' 16 | const editorURI = data.url('index.html') 17 | const rootURI = editorURI.substr(0, editorURI.lastIndexOf('/') + 1) 18 | 19 | console.log(editorURI) 20 | 21 | function errorToJSON(error) { 22 | return error ? { message: error.message, stack: error.stack } : error 23 | } 24 | 25 | // Allow popups for editor. 26 | permissions.add({ 27 | host: 'edit:', 28 | type: 'popup', 29 | capability: true 30 | }) 31 | 32 | var mod = PageMod({ 33 | include: PROTOCOL + ':*', 34 | contentScript: 'unsafeWindow.port = self.port', 35 | contentScriptWhen: 'start', 36 | onAttach: function onAttach(worker) { 37 | worker.port.on('<=', function onMessage(message) { 38 | fs[message.method].apply(fs, message.params.concat([function(error) { 39 | worker.port.emit('=>', { 40 | '@': message['@'], 41 | params: [errorToJSON(error)].concat(Array.slice(arguments, 1)) 42 | }) 43 | }])) 44 | }) 45 | } 46 | }) 47 | 48 | function isAbsolute(uri) { 49 | return ~uri.indexOf('edit:') || ~uri.indexOf('://') 50 | } 51 | function resolve(id, base) { 52 | var path, paths, last 53 | if (isAbsolute(id)) return id 54 | paths = id.split('/') 55 | base = base ? base.split('/') : [ '.' ] 56 | if (base.length > 1) base.pop() 57 | while ((path = paths.shift())) { 58 | if (path === '..') { 59 | if (base.length && base[base.length - 1] !== '..') { 60 | if (base.pop() === '.') base.push(path) 61 | } else base.push(path) 62 | } else if (path !== '.') { 63 | base.push(path) 64 | } 65 | } 66 | if (base[base.length - 1].substr(-1) === '.') base.push('') 67 | return base.join('/') 68 | } 69 | 70 | function normalize(uri) { 71 | return uri.replace(/\/\.\//, '/') 72 | } 73 | 74 | // Registers protocol handler for `edit:*` protocol. 75 | var editProtocolHandler = protocol.protocol(PROTOCOL, { 76 | onResolve: function(uri, base) { 77 | if (base && !~base.indexOf('edit:///')) 78 | base = 'edit:///index.html' 79 | 80 | var href = normalize(resolve(uri, base)). 81 | replace('edit::', '') // strip out host from the URLs. 82 | 83 | return { 84 | scheme: 'edit', 85 | host: 'edit:', 86 | href: href, 87 | path: ~href.indexOf('edit:///') ? href.replace('edit:///', '') : '/' 88 | } 89 | }, 90 | // When browser is navigated to `edit:*` URI this function is called with an 91 | // absolute URI and returned content or content under returned URI will be 92 | // displayed to a user. 93 | onRequest: function(request, response) { 94 | try { 95 | // All the editor content is located under 'edit:///' so to get a path 96 | // we just strip that out. 97 | var path = request.uri.replace('edit:///', '') 98 | // If requested path was diff from 'edit:///...', then we load editor. 99 | path = ~path.indexOf('edit:') ? 'index.html' : path 100 | response.uri = data.url(path) 101 | } catch(error) { 102 | console.exception(error) 103 | } 104 | } 105 | }).register() 106 | 107 | // Make suer that protocol handler is removed, once add-on is uninstalled. 108 | require("unload").when(function() { 109 | editProtocolHandler.unregister() 110 | }) 111 | 112 | }); 113 | -------------------------------------------------------------------------------- /data/support/command-manager.js: -------------------------------------------------------------------------------- 1 | /*jshint asi:true */ 2 | 3 | define(function(require, exports, module) { 4 | 'use strict'; 5 | 6 | exports.name = 'command-manager' 7 | exports.version = '0.0.1' 8 | exports.description = 'Installs modes exposed by plugins.' 9 | exports.author = 'Irakli Gozalishvili ' 10 | exports.stability = 'unstable' 11 | exports.dependencies = [ 'hub@0.0.2' ] 12 | 13 | var unbind = Function.call.bind(Function.bind, Function.call) 14 | var owns = unbind(Object.prototype.hasOwnProperty) 15 | var meta = require('plugin-hub/core').meta 16 | 17 | var commands = Object.create(null); 18 | 19 | var command = meta('Group of utilities for working with commands', {}) 20 | command.params = meta({ 21 | description: 'Generates paramater signature' 22 | }, function params(signature) { 23 | var result = [] 24 | 25 | if (Array.isArray(signature)) { 26 | result = signature.map(function(_, index) { 27 | var param = typeof(_) === 'string' ? { type: _ } : _ 28 | param.name = String(index) 29 | return param 30 | }) 31 | } 32 | 33 | if (typeof(signature) === 'number') { 34 | while (signature) result.unshift({ name: signature -- }) 35 | } 36 | 37 | return result 38 | }) 39 | command.make = meta({ 40 | description: 'Makes a commonad from function' 41 | }, function make(f) { 42 | return { 43 | name: f.meta.name || f.name, 44 | description: f.meta.description || '', 45 | params: command.params(f.meta.takes || f.length), 46 | exec: function execute(editor, params, context) { 47 | var args = [] 48 | for (var index in params) args[index] = params[index] 49 | // TODO: Find a proper solution instead. 50 | if (~f.meta.takes.indexOf('editor')) 51 | args[f.meta.takes.indexOf('editor')] = editor 52 | if (~f.meta.takes.indexOf('env')) 53 | args[f.meta.takes.indexOf('editor')] = editor 54 | 55 | return f.apply(f, args) 56 | } 57 | } 58 | }) 59 | 60 | command.plug = meta({ 61 | description: 'Plugs in the command' 62 | }, function plug(env, name, descriptor) { 63 | if (typeof(descriptor) === 'function') { 64 | env.commands[name] = descriptor 65 | env.broadcast('command:plug', name, descriptor) 66 | } 67 | 68 | if (typeof(descriptor) === 'object') { 69 | env.commands[name] = descriptor 70 | Object.keys(descriptor).forEach(function(key) { 71 | command.plug(env, name + ' ' + key, descriptor[key]) 72 | }) 73 | env.broadcast('command:group:plug', name, descriptor) 74 | } 75 | }) 76 | command.plug.all = meta({ 77 | description: 'Plugs in all commands' 78 | }, function plug(env, commands) { 79 | return Object.keys(commands).map(function(name) { 80 | return commands[name] && command.plug(env, name, commands[name]) 81 | }) 82 | }) 83 | 84 | command.unplug = meta({ 85 | description: 'Unplugs given command' 86 | }, function unplug(env, name, descriptor) { 87 | descriptor = env.commands[name] 88 | if (typeof(descriptor) === 'function') { 89 | delete env.commands[name] 90 | env.broadcast('command:unplug', name, descriptor) 91 | } 92 | 93 | if (typeof(descriptor) === 'object') { 94 | delete env.commands[name] 95 | Object.keys(descriptor).forEach(function(key) { 96 | command.unplug(env, name + ' ' + key, descriptor[key]) 97 | }) 98 | env.broadcast('command:group:unplug', name, descriptor) 99 | } 100 | return env.editor.commands.removeCommand(command.plug) 101 | }) 102 | command.unplug.all = meta({ 103 | description: 'Unplugs all commands' 104 | }, function unplug(env, commands) { 105 | return Object.keys(commands).map(function(name) { 106 | return command.unplug(env, name, commands[name]) 107 | }) 108 | }) 109 | 110 | exports.onstartup = function onstartup(env, plugins) { 111 | env.commands = commands 112 | plugins.forEach(exports.onplug.bind(exports.onplug, env)) 113 | } 114 | exports.onshutdown = function onshutdown(env) { 115 | delete env.commands 116 | } 117 | exports.onplug = function onplug(env, plugin) { 118 | if (plugin.commands) command.plug.all(env, plugin.commands) 119 | } 120 | exports.onunplug = function onunplug(env, plugin) { 121 | if (plugin.command) command.unplug.all(env, plugin.commands) 122 | } 123 | 124 | }); 125 | -------------------------------------------------------------------------------- /data/support/mode-manager.js: -------------------------------------------------------------------------------- 1 | /*jshint asi:true */ 2 | 3 | define(function(require, exports, module) { 4 | 'use strict'; 5 | 6 | exports.name = 'mode-manager' 7 | exports.version = '0.0.1' 8 | exports.description = 'Installs modes exposed by plugins.' 9 | exports.author = 'Irakli Gozalishvili ' 10 | exports.stability = 'unstable' 11 | 12 | var unbind = Function.call.bind(Function.bind, Function.call) 13 | var owns = unbind(Object.prototype.hasOwnProperty) 14 | var meta = require('plugin-hub/core').meta 15 | 16 | var modes = Object.create(null) 17 | ;[ 18 | ["C/C++", require("ace/mode/c_cpp").Mode, ["c", "cpp", "cxx", "h", "hpp"]], 19 | ["Clojure", require("ace/mode/clojure").Mode, ["clj"]], 20 | ["CoffeeScript", require("ace/mode/coffee").Mode, ["coffee"]], 21 | ["ColdFusion", require("ace/mode/coldfusion").Mode, ["cfm"]], 22 | ["C#", require("ace/mode/csharp").Mode, ["cs"]], 23 | ["CSS", require("ace/mode/css").Mode, ["css"]], 24 | ["Groovy", require("ace/mode/groovy").Mode, ["groovy"]], 25 | ["haXe", require("ace/mode/haxe").Mode, ["hx"]], 26 | ["HTML", require("ace/mode/html").Mode, ["html", "htm"]], 27 | ["Java", require("ace/mode/java").Mode, ["java"]], 28 | ["JavaScript", require("ace/mode/javascript").Mode, ["js"]], 29 | ["JSON", require("ace/mode/json").Mode, ["json"]], 30 | ["LaTeX", require("ace/mode/latex").Mode, ["tex"]], 31 | ["Lua", require("ace/mode/lua").Mode, ["lua"]], 32 | ["Markdown", require("ace/mode/markdown").Mode, ["md", "markdown"]], 33 | ["OCaml", require("ace/mode/ocaml").Mode, ["ml", "mli"]], 34 | ["Perl", require("ace/mode/perl").Mode, ["pl", "pm"]], 35 | ["pgSQL",require("ace/mode/pgsql").Mode, ["pgsql", "sql"]], 36 | ["PHP",require("ace/mode/php").Mode, ["php"]], 37 | ["Powershell", require("ace/mode/powershell").Mode, ["ps1"]], 38 | ["Python", require("ace/mode/python").Mode, ["py"]], 39 | ["Scala", require("ace/mode/scala").Mode, ["scala"]], 40 | ["SCSS", require("ace/mode/scss").Mode, ["scss"]], 41 | ["Ruby", require("ace/mode/ruby").Mode, ["rb"]], 42 | ["SQL", require("ace/mode/sql").Mode, ["sql"]], 43 | ["SVG", require("ace/mode/svg").Mode, ["svg"]], 44 | ["Text", require("ace/mode/text").Mode, ["txt"]], 45 | ["Textile", require("ace/mode/textile").Mode, ["textile"]], 46 | ["XML", require("ace/mode/xml").Mode, ["xml"]] 47 | ].forEach(function($) { 48 | modes[$[0]] = { name: $[0], mode: new $[1], types: $[2] } 49 | }) 50 | 51 | // hack to workaround the fact that types are not passed an environment. 52 | var ENV, mode 53 | 54 | // pre-installed modes. 55 | exports.modes = modes 56 | 57 | exports.types = { 58 | mode: meta({ type: 'selection' }, function data() { 59 | return Object.keys(modes) 60 | }) 61 | } 62 | 63 | exports.settings = { 64 | mode: meta({ 65 | description: 'Sets buffer file mode', 66 | type: 'mode' 67 | }, function mode(value) { 68 | ENV.editor.getSession().setMode(modes[value].mode) 69 | }) 70 | } 71 | 72 | exports.commands = { 73 | 'set-mode': meta({ 74 | takes: [ 'mode' ], 75 | description: 'Sets editor mode on the active buffer' 76 | }, function setMode(name) { 77 | mode.set(ENV, mode.get(ENV, name).mode) 78 | }), 79 | echo: meta({ 80 | takes: [ 'string' ], 81 | description: 'Echos back a message' 82 | }, function(input) { 83 | return input 84 | }) 85 | } 86 | 87 | exports.mode = mode = {} 88 | mode.install = function plug(env, mode) { 89 | return env.modes[mode.name] = mode 90 | } 91 | mode.install.all = function installall(env, modes) { 92 | return Object.keys(modes).map(function(name) { 93 | var item = modes[name] 94 | if (!owns(item, 'name')) item.name = name 95 | mode.install(env, item) 96 | }) 97 | } 98 | mode.uninstall = function uninstall(env, mode) { 99 | return delete env.modes[mode.name] 100 | } 101 | mode.uninstall.all = function uninstallall(env, modes) { 102 | return Object.keys(modes).map(function(name) { 103 | mode.uninstall(env, modes[name]) 104 | }) 105 | } 106 | mode.set = function set(env, mode) { 107 | env.editor.getSession().setMode(mode) 108 | } 109 | mode.get = function get(env, name) { 110 | return env.modes[name] 111 | } 112 | mode.of = function of(env, uri) { 113 | var type = uri.split('.').pop() 114 | var names = Object.keys(env.modes) 115 | while (names.length) { 116 | var mode = modes[names.shift()] 117 | if (~mode.types.indexOf(type)) return mode.mode 118 | } 119 | } 120 | 121 | exports.onstartup = function onstartup(env, plugins) { 122 | ENV = env 123 | env.modes = Object.create(null) 124 | } 125 | 126 | exports.onplug = function onplug(env, plugin) { 127 | return plugin.modes && mode.install.all(env, plugin.modes) 128 | } 129 | 130 | exports.onunplug = function onunplug(env, plugin) { 131 | return plugin.modes && mode.uninstall.all(env, plugin.modes) 132 | } 133 | 134 | }); 135 | -------------------------------------------------------------------------------- /data/support/fs.js: -------------------------------------------------------------------------------- 1 | /* vim:set ts=2 sw=2 sts=2 expandtab */ 2 | /*jshint asi: true undef: true es5: true node: true devel: true 3 | forin: true latedef: false supernew: true browser: true */ 4 | /*global define: true port: true */ 5 | define(function(require, exports) { 6 | 7 | "use strict"; 8 | 9 | var hub = require('plugin-hub/core'), meta = hub.meta, values = meta.values 10 | var defer = require('support/micro-promise/core').defer 11 | var mode = require('support/mode-manager').mode 12 | 13 | exports.name = 'fs' 14 | exports.version = '0.0.2' 15 | exports.author = 'Irakli Gozalishvili ' 16 | exports.description = 'Filesystem bindings for an editor' 17 | exports.stability = 'unstable' 18 | exports.dependencies = [ 'mode-manager@0.0.1' ] 19 | 20 | var env, GUID = 0 21 | var callbacks = {} 22 | 23 | 24 | function call(method) { 25 | var address = ++GUID 26 | callbacks[address] = arguments[arguments.length - 1] 27 | if (typeof(port) !== 'undefined') port.emit('<=', { 28 | '@': address, 29 | method: method, 30 | params: Array.prototype.slice.call(arguments, 1, arguments.length - 1) 31 | }) 32 | } 33 | 34 | if (typeof(port) !== 'undefined') port.on('=>', function(message) { 35 | var address = message['@'], params = message.params 36 | var callback = callbacks[address] 37 | delete callbacks[address] 38 | if (callback) callback.apply(null, params) 39 | }, false) 40 | 41 | exports.readdir = call.bind(null, 'readdir') 42 | exports.mkdir = call.bind(null, 'mkdir') 43 | exports.rmdir = call.bind(null, 'unlink') 44 | exports.readFile = call.bind(null, 'readFile') 45 | exports.writeFile = call.bind(null, 'writeFile') 46 | exports.readURI = call.bind(null, 'readURI') 47 | exports.rename = call.bind(null, 'rename') 48 | exports.readdir = call.bind(null, 'readdir') 49 | 50 | function isFileURI(uri) { 51 | doc: "Returns true if given string is 'file:///' uri." 52 | 53 | return uri.indexOf('file://') === 0 54 | } 55 | function getFilePath(uri) { 56 | doc: "Takes 'file:///' uri & returs given file path." 57 | 58 | return uri.substr('file://'.length) 59 | } 60 | function isPath(uri) { 61 | doc: "Returns true if uri is path or relative file uri." 62 | 63 | return !~uri.indexOf('://') 64 | } 65 | function getDirectory(uri) { 66 | doc: "Returns uri to the parent directory." 67 | 68 | return uri.substr(0, uri.lastIndexOf('/') + 1) 69 | } 70 | function normalizeDirectoryURI(uri) { 71 | doc: "Normalized diroctory URI so that last character is '/'" 72 | 73 | return uri.substr(-1) === '/' ? uri : uri + '/' 74 | } 75 | function isAbsolute(uri) { 76 | doc: "Returns true if uri is 'file:///' uri or absolute path." 77 | 78 | return isFileURI(uri) || uri.charAt(0) === '/' || uri.indexOf('~/') === 0 79 | } 80 | 81 | function setBuffer(env, uri, content, skip, replace) { 82 | var session = env.editor.getSession() 83 | session.setValue(content) 84 | session.setMode(mode.of(env, uri)) 85 | editURI(env, uri) 86 | 87 | try { 88 | if (skip) return 89 | if (replace) history.replaceState({ uri: uri }, uri, 'edit:' + uri) 90 | else history.pushState({ uri: uri }, uri, 'edit:' + uri) 91 | } catch (e) { 92 | console.error(e.message) 93 | } 94 | } 95 | 96 | function editURI(env, value) { 97 | doc: "Gets / sets (if value is passed) edit uri for the active buffer." 98 | 99 | return value ? env.editor.getSession().uri = value 100 | : env.editor.getSession().uri 101 | } 102 | function pwd(env) { 103 | doc: "Returns current working directory" 104 | 105 | return env.pwd || getDirectory(editURI(env) || '') || '~/' 106 | } 107 | 108 | function cwd(env, path) { 109 | doc: "Sets current working directiory" 110 | 111 | return env.pwd = path 112 | } 113 | 114 | exports.types = { 115 | uri: meta({ 116 | description: 'File URI type', 117 | type: 'string' 118 | }, function(uri) { 119 | return isAbsolute(uri) ? uri : pwd(window.env) + uri 120 | }) 121 | } 122 | 123 | var commands = { 124 | open: meta({ 125 | description: 'opens a file / uri in a new tab', 126 | takes: [ 'uri', 'env' ] 127 | }, function open(uri, env) { 128 | var deferred = defer() 129 | uri = isAbsolute(uri) ? uri : pwd(env) + uri 130 | try { 131 | window.open('edit:' + uri) 132 | deferred.resolve('opened: ' + uri) 133 | env.editor.focus() 134 | } catch (error) { 135 | deferred.reject(error.message) 136 | } 137 | return deferred.promise 138 | }), 139 | edit: meta({ 140 | description: 'edit a file / uri', 141 | takes: [ 'uri', 'env' ] 142 | }, function edit(uri, env, skip, replace) { 143 | var deferred = defer() 144 | uri = isAbsolute(uri) ? uri : pwd(env) + uri 145 | var path = isFileURI(uri) ? getFilePath(uri) : uri 146 | if (isPath(path)) { 147 | exports.readFile(path, function(error, content) { 148 | if (error) deferred.reject(error.message) 149 | else setBuffer(env, path, content, skip, replace) 150 | deferred.resolve('Edit: ' + path) 151 | env.editor.focus() 152 | }) 153 | } else { 154 | deferred.resolve('Unsupported file location: ' + uri) 155 | } 156 | return deferred.promise 157 | }), 158 | write: meta({ 159 | description: 'save changes to the file', 160 | takes: [ 'uri', 'env' ], 161 | }, function write(uri, env) { 162 | uri = uri || editURI(env) 163 | uri = isAbsolute(uri) ? uri : pwd(env) + uri 164 | var deferred = defer() 165 | var content = env.editor.getSession().getValue() 166 | var path = isFileURI(uri) ? getFilePath(uri) : uri 167 | if (isPath(path)) { 168 | exports.writeFile(path, content, function(error) { 169 | if (error) deferred.reject(error.message) 170 | deferred.resolve('Wrote to: ' + path) 171 | env.editor.focus() 172 | }) 173 | } else { 174 | deferred.reject('Unsupported file location: ' + uri) 175 | } 176 | return deferred.promise 177 | }), 178 | pwd: meta({ 179 | description: 'Prints current working directory', 180 | takes: [ 'env' ] 181 | }, function (env) { 182 | return pwd(env) 183 | }), 184 | ls: meta({ 185 | description: 'list files in the working dir', 186 | takes: [ 'uri', 'env' ] 187 | }, function ls(uri, env) { 188 | uri = isAbsolute(uri) ? uri : pwd(env) + uri 189 | var path = isFileURI(uri) ? getFilePath(uri) : uri 190 | var deferred = defer() 191 | if (isPath(path)) { 192 | exports.readdir(path, function(error, entries) { 193 | if (error) deferred.reject(error.message) 194 | deferred.resolve(entries.join('\n
')) 195 | }) 196 | } else { 197 | deferred.reject('Unsupported location: ' + uri) 198 | } 199 | return deferred.promise 200 | }), 201 | cd: meta({ 202 | description: 'change working directory', 203 | takes: [ 'uri', 'env' ] 204 | }, function exec(uri, env) { 205 | uri = isAbsolute(uri) ? uri : pwd(env) + uri 206 | uri = normalizeDirectoryURI(uri) 207 | var deferred = defer() 208 | exports.readdir(uri, function(error, entries) { 209 | if (error) deferred.reject(error.message) 210 | cwd(env, uri) 211 | deferred.resolve(uri) 212 | }) 213 | return deferred.promise 214 | }) 215 | } 216 | exports.commands = commands 217 | 218 | exports.onstartup = function startup(env) { 219 | env.fs = exports 220 | 221 | function load(skip, replace) { 222 | var uri = String(location).substr('edit:'.length) 223 | if (uri) commands.edit(uri, env, skip, replace) 224 | } 225 | 226 | window.addEventListener('popstate', load, false) 227 | load(false, true) 228 | } 229 | 230 | }); 231 | -------------------------------------------------------------------------------- /data/theme.css: -------------------------------------------------------------------------------- 1 | .ace-ambiance { 2 | background-color: #202020; 3 | } 4 | 5 | .ace-ambiance .ace_editor { 6 | border: 2px solid rgb(159, 159, 159); 7 | } 8 | 9 | .ace-ambiance .ace_editor.ace_focus { 10 | border: 2px solid #327fbd; 11 | } 12 | 13 | .ace-ambiance .ace_gutter { 14 | background-image: -moz-linear-gradient(left, #3D3D3D, #333); 15 | background-image: -ms-linear-gradient(left, #3D3D3D, #333); 16 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#3D3D3D), to(#333)); 17 | background-image: -webkit-linear-gradient(left, #3D3D3D, #333); 18 | background-image: -o-linear-gradient(left, #3D3D3D, #333); 19 | background-image: linear-gradient(left, #3D3D3D, #333); 20 | background-repeat: repeat-x; 21 | 22 | text-shadow: 0px 1px 1px #4d4d4d; 23 | color: #222; 24 | border-right: 1px solid #4d4d4d; 25 | overflow : hidden; 26 | } 27 | 28 | .ace-ambiance .ace_gutter-layer { 29 | background: url("noise.png") repeat left top; 30 | width: 100%; 31 | text-align: right; 32 | } 33 | 34 | .ace-ambiance .ace_gutter-layer .ace_gutter-cell { 35 | min-width: 23px; 36 | } 37 | 38 | .ace-ambiance .ace_gutter-layer .ace_gutter-cell .ace_fold-widget { 39 | position: absolute; 40 | right: 2px; 41 | margin: 0; 42 | vertical-align: middle; 43 | height: inherit; 44 | width: auto; 45 | background: none; 46 | border: none; 47 | box-shadow: none; 48 | outline: none; 49 | } 50 | 51 | .ace-ambiance .ace_gutter-layer .ace_gutter-cell .ace_fold-widget:hover { 52 | color: #777; 53 | } 54 | 55 | .ace-ambiance .ace_gutter-layer .ace_gutter-cell .ace_fold-widget.open:after { 56 | content: '‣' 57 | } 58 | 59 | .ace-ambiance .ace_gutter-layer .ace_gutter-cell .ace_fold-widget.closed:after { 60 | content: '▾' 61 | } 62 | 63 | .ace-ambiance .ace_gutter-cell.ace_warning, 64 | .ace-ambiance .ace_gutter-cell.ace_error { 65 | background: none; 66 | } 67 | 68 | .ace-ambiance .ace_gutter-cell.ace_warning:before, 69 | .ace-ambiance .ace_gutter-cell.ace_error:before { 70 | display: inline-block; 71 | content: ""; 72 | width: 14px; 73 | height: 14px; 74 | vertical-align: text-bottom; 75 | background-image: url("./glyphicons-halflings.png"); 76 | background-position: 14px 14px; 77 | background-repeat: no-repeat; 78 | position: absolute; 79 | left: 3px; 80 | } 81 | 82 | .ace-ambiance .ace_gutter-cell.ace_warning:before { 83 | background-position: 0px -120px; 84 | } 85 | .ace-ambiance .ace_gutter-cell.ace_error:before { 86 | background-position: -216px -96px; 87 | } 88 | 89 | .ace-ambiance .ace_print_margin { 90 | border-left: 1px dotted #2D2D2D; 91 | width: 100%; 92 | background: #262626; 93 | } 94 | 95 | .ace-ambiance .ace_scroller { 96 | background-color: #202020; 97 | -webkit-box-shadow: inset 0 0 10px black; 98 | -moz-box-shadow: inset 0 0 10px black; 99 | -o-box-shadow: inset 0 0 10px black; 100 | box-shadow: inset 0 0 10px black; 101 | } 102 | 103 | .ace-ambiance .ace_text-layer { 104 | cursor: text; 105 | color: #E6E1DC; 106 | background: url("noise.png") repeat left top; 107 | } 108 | 109 | .ace-ambiance .ace_cursor { 110 | border-left: 2px solid #A7A7A7; 111 | } 112 | 113 | .ace-ambiance .ace_cursor.ace_overwrite { 114 | border-left: 0px; 115 | border-bottom: 1px solid #A7A7A7; 116 | } 117 | .ace-ambiance.normal-mode .ace_cursor.ace_overwrite { 118 | border: 1px solid #FFE300; 119 | background: #766B13; 120 | } 121 | .ace-ambiance.normal-mode .ace_cursor-layer { 122 | z-index: 0; 123 | } 124 | 125 | .ace-ambiance .ace_marker-layer .ace_selection { 126 | background: rgba(221, 240, 255, 0.20); 127 | } 128 | 129 | .ace-ambiance .ace_marker-layer .ace_selected_word { 130 | border-radius: 4px; 131 | border: 8px solid #3f475d; 132 | box-shadow: 0 0 4px black; 133 | } 134 | 135 | .ace-ambiance .ace_marker-layer .ace_step { 136 | background: rgb(198, 219, 174); 137 | } 138 | 139 | .ace-ambiance .ace_marker-layer .ace_bracket { 140 | margin: -1px 0 0 -1px; 141 | border: 1px solid rgba(255, 255, 255, 0.25); 142 | } 143 | 144 | .ace-ambiance .ace_marker-layer .ace_active_line { 145 | background: rgba(255, 255, 255, 0.031); 146 | } 147 | 148 | 149 | 150 | .ace-ambiance .ace_invisible { 151 | color: #333; 152 | } 153 | 154 | .ace-ambiance .ace_paren { 155 | color: #24C2C7; 156 | } 157 | 158 | .ace-ambiance .ace_keyword { 159 | color: #cda869; 160 | } 161 | 162 | .ace-ambiance .ace_keyword.ace_operator { 163 | color: #fa8d6a; 164 | } 165 | 166 | .ace-ambiance .ace_punctuation.ace_operator { 167 | color: #fa8d6a; 168 | } 169 | 170 | .ace-ambiance .ace_identifier { 171 | } 172 | 173 | .ace-ambiance .ace-statement { 174 | color: #cda869; 175 | } 176 | 177 | .ace-ambiance .ace_constant { 178 | color: #CF7EA9; 179 | } 180 | 181 | .ace-ambiance .ace_constant.ace_language { 182 | color: #CF7EA9; 183 | } 184 | 185 | .ace-ambiance .ace_constant.ace_library { 186 | 187 | } 188 | 189 | .ace-ambiance .ace_constant.ace_numeric { 190 | color: #78CF8A; 191 | } 192 | 193 | .ace-ambiance .ace_invalid { 194 | text-decoration: underline; 195 | } 196 | 197 | .ace-ambiance .ace_invalid.ace_illegal { 198 | color:#F8F8F8; 199 | background-color: rgba(86, 45, 86, 0.75); 200 | } 201 | 202 | .ace-ambiance .ace_invalid, 203 | .ace-ambiance .ace_deprecated { 204 | text-decoration: underline; 205 | font-style: italic; 206 | color: #D2A8A1; 207 | } 208 | 209 | .ace-ambiance .ace_support { 210 | color: #9B859D; 211 | } 212 | 213 | .ace-ambiance .ace_support.ace_function { 214 | color: #DAD085; 215 | } 216 | 217 | .ace-ambiance .ace_function.ace_buildin { 218 | color: #9b859d; 219 | } 220 | 221 | .ace-ambiance .ace_string { 222 | color: #8f9d6a; 223 | } 224 | 225 | .ace-ambiance .ace_string.ace_regexp { 226 | color: #DAD085; 227 | } 228 | 229 | .ace-ambiance .ace_comment { 230 | font-style: italic; 231 | color: #555; 232 | } 233 | 234 | .ace-ambiance .ace_comment.ace_doc { 235 | } 236 | 237 | .ace-ambiance .ace_comment.ace_doc.ace_tag { 238 | color: #666; 239 | font-style: normal; 240 | } 241 | 242 | .ace-ambiance .ace_definition, 243 | .ace-ambiance .ace_type { 244 | color: #aac6e3; 245 | } 246 | 247 | .ace-ambiance .ace_variable { 248 | color: #9999cc; 249 | } 250 | 251 | .ace-ambiance .ace_variable.ace_language { 252 | color: #9b859d; 253 | } 254 | 255 | .ace-ambiance .ace_xml_pe { 256 | color: #494949; 257 | } 258 | 259 | .gcli-display-hint, 260 | .gcli-display-output { 261 | position: fixed; 262 | bottom: 0px; 263 | } 264 | 265 | #gcli-display { 266 | height: 0; 267 | } 268 | 269 | #gcli-input, 270 | #gcli-display .gcli-display-hint, 271 | #gcli-display .gcli-display-output, 272 | #gcli-display .gcli-row-in, 273 | #gcli-display .gcli-row-out, 274 | #gcli-display .gcli-row-in-typed, 275 | #gcli-display .gcli-display-hint { 276 | background: #3D3D3D; 277 | color: #E6E1DC; 278 | text-shadow: #333 0px 1px; 279 | border-color: #4D4D4D !important; 280 | } 281 | 282 | #gcli-display .gcli-row-in, 283 | #gcli-display .gcli-row-out { 284 | border: none; 285 | border-radius: 4px; 286 | padding: 1px; 287 | margin: 2px 4px; 288 | background: rgba(0, 0, 0, 0.1) !important; 289 | } 290 | 291 | .gcli-row-out p { 292 | margin: 2px; 293 | } 294 | 295 | .gcli-menu { 296 | border: none !important; 297 | } 298 | 299 | .gcli-menu-option, 300 | .gcli-menu-name, 301 | .gcli-menu-desc { 302 | font-family: monaco consolas, courier, monospace; 303 | font-size: 12px !important; 304 | } 305 | 306 | .gcli-menu-option:hover { 307 | background: rgba(255, 255, 255, 0.1) !important; 308 | } 309 | 310 | .gcli-field { 311 | background: rgba(255, 255, 255, 0.1) !important; 312 | font-size: 14px; 313 | border-radius: 5px; 314 | padding: 0 5px; 315 | border: 1px solid #3D3D3D; 316 | outline: none; 317 | color: #E6E1DC; 318 | } 319 | 320 | .gcli-prompt { 321 | color: #fff !important; 322 | } 323 | 324 | #gcli-input { 325 | color: #E6E1DC !important; 326 | background: #3D3D3D !important; 327 | z-index: 3; 328 | position: fixed; 329 | width: 100%; 330 | height: 18px; 331 | bottom: 0; 332 | border: none; 333 | border-top: 1px solid; 334 | outline: none; 335 | margin: 0; 336 | font-family: monaco consolas, courier, monospace; 337 | font-size: 14px; 338 | 339 | opacity: 0.9; 340 | box-shadow: 0 0 10px black; 341 | } 342 | 343 | .gcli-display-output { 344 | opacity: 0.9; 345 | z-index: 1; 346 | border: 1px solid #4D4D4D !important; 347 | border-top-left-radius: 4px; 348 | border-top-right-radius: 4px; 349 | border-bottom: none; 350 | font-size: 13px; 351 | 352 | box-shadow: 0 0 10px black; 353 | max-height: 50% !important; 354 | width: 90%; 355 | margin-left: 20px !important; 356 | } 357 | 358 | #gcli-input { 359 | opacity: 0.3; 360 | -webkit-transition: opacity 0.2s ease; 361 | -moz-transition: opacity 0.2s; 362 | -o-transition: opacity 0.2s ease; 363 | transition: opacity 0.2s ease; 364 | } 365 | 366 | #gcli-input:focus { 367 | opacity: 0.9; 368 | } 369 | 370 | .gcli-display-hint { 371 | opacity: 0.9; 372 | width: auto; 373 | max-height: 200px; 374 | border: 1px solid #4D4D4D !important; 375 | border-top-left-radius: 4px; 376 | border-top-right-radius: 4px; 377 | box-shadow: 0 0 10px black; 378 | z-index: 2 !important; 379 | padding-bottom: 32px !important; 380 | margin-left: 40px; 381 | } 382 | 383 | -------------------------------------------------------------------------------- /data/text.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license RequireJS text 0.26.0 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. 3 | * Available via the MIT or new BSD license. 4 | * see: http://github.com/jrburke/requirejs for details 5 | */ 6 | /*jslint regexp: false, nomen: false, plusplus: false, strict: false */ 7 | /*global require: false, XMLHttpRequest: false, ActiveXObject: false, 8 | define: false, window: false, process: false, Packages: false, 9 | java: false, location: false */ 10 | 11 | (function () { 12 | var progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'], 13 | xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, 14 | bodyRegExp = /]*>\s*([\s\S]+)\s*<\/body>/im, 15 | hasLocation = typeof location !== 'undefined' && location.href, 16 | buildMap = []; 17 | 18 | define(function () { 19 | var text, get, fs; 20 | 21 | if (typeof window !== "undefined" && window.navigator && window.document) { 22 | get = function (url, callback) { 23 | var xhr = text.createXhr(); 24 | xhr.open('GET', url, true); 25 | xhr.onreadystatechange = function (evt) { 26 | //Do not explicitly handle errors, those should be 27 | //visible via console output in the browser. 28 | if (xhr.readyState === 4) { 29 | callback(xhr.responseText); 30 | } 31 | }; 32 | xhr.send(null); 33 | }; 34 | } else if (typeof process !== "undefined" && 35 | process.versions && 36 | !!process.versions.node) { 37 | //Using special require.nodeRequire, something added by r.js. 38 | fs = require.nodeRequire('fs'); 39 | 40 | get = function (url, callback) { 41 | callback(fs.readFileSync(url, 'utf8')); 42 | }; 43 | } else if (typeof Packages !== 'undefined') { 44 | //Why Java, why is this so awkward? 45 | get = function (url, callback) { 46 | var encoding = "utf-8", 47 | file = new java.io.File(url), 48 | lineSeparator = java.lang.System.getProperty("line.separator"), 49 | input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)), 50 | stringBuffer, line, 51 | content = ''; 52 | try { 53 | stringBuffer = new java.lang.StringBuffer(); 54 | line = input.readLine(); 55 | 56 | // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324 57 | // http://www.unicode.org/faq/utf_bom.html 58 | 59 | // Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK: 60 | // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058 61 | if (line && line.length() && line.charAt(0) === 0xfeff) { 62 | // Eat the BOM, since we've already found the encoding on this file, 63 | // and we plan to concatenating this buffer with others; the BOM should 64 | // only appear at the top of a file. 65 | line = line.substring(1); 66 | } 67 | 68 | stringBuffer.append(line); 69 | 70 | while ((line = input.readLine()) !== null) { 71 | stringBuffer.append(lineSeparator); 72 | stringBuffer.append(line); 73 | } 74 | //Make sure we return a JavaScript string and not a Java string. 75 | content = String(stringBuffer.toString()); //String 76 | } finally { 77 | input.close(); 78 | } 79 | callback(content); 80 | }; 81 | } 82 | 83 | text = { 84 | version: '0.26.0', 85 | 86 | strip: function (content) { 87 | //Strips declarations so that external SVG and XML 88 | //documents can be added to a document without worry. Also, if the string 89 | //is an HTML document, only the part inside the body tag is returned. 90 | if (content) { 91 | content = content.replace(xmlRegExp, ""); 92 | var matches = content.match(bodyRegExp); 93 | if (matches) { 94 | content = matches[1]; 95 | } 96 | } else { 97 | content = ""; 98 | } 99 | return content; 100 | }, 101 | 102 | jsEscape: function (content) { 103 | return content.replace(/(['\\])/g, '\\$1') 104 | .replace(/[\f]/g, "\\f") 105 | .replace(/[\b]/g, "\\b") 106 | .replace(/[\n]/g, "\\n") 107 | .replace(/[\t]/g, "\\t") 108 | .replace(/[\r]/g, "\\r"); 109 | }, 110 | 111 | createXhr: function () { 112 | //Would love to dump the ActiveX crap in here. Need IE 6 to die first. 113 | var xhr, i, progId; 114 | if (typeof XMLHttpRequest !== "undefined") { 115 | return new XMLHttpRequest(); 116 | } else { 117 | for (i = 0; i < 3; i++) { 118 | progId = progIds[i]; 119 | try { 120 | xhr = new ActiveXObject(progId); 121 | } catch (e) {} 122 | 123 | if (xhr) { 124 | progIds = [progId]; // so faster next time 125 | break; 126 | } 127 | } 128 | } 129 | 130 | if (!xhr) { 131 | throw new Error("createXhr(): XMLHttpRequest not available"); 132 | } 133 | 134 | return xhr; 135 | }, 136 | 137 | get: get, 138 | 139 | /** 140 | * Parses a resource name into its component parts. Resource names 141 | * look like: module/name.ext!strip, where the !strip part is 142 | * optional. 143 | * @param {String} name the resource name 144 | * @returns {Object} with properties "moduleName", "ext" and "strip" 145 | * where strip is a boolean. 146 | */ 147 | parseName: function (name) { 148 | var strip = false, index = name.indexOf("."), 149 | modName = name.substring(0, index), 150 | ext = name.substring(index + 1, name.length); 151 | 152 | index = ext.indexOf("!"); 153 | if (index !== -1) { 154 | //Pull off the strip arg. 155 | strip = ext.substring(index + 1, ext.length); 156 | strip = strip === "strip"; 157 | ext = ext.substring(0, index); 158 | } 159 | 160 | return { 161 | moduleName: modName, 162 | ext: ext, 163 | strip: strip 164 | }; 165 | }, 166 | 167 | xdRegExp: /^((\w+)\:)?\/\/([^\/\\]+)/, 168 | 169 | /** 170 | * Is an URL on another domain. Only works for browser use, returns 171 | * false in non-browser environments. Only used to know if an 172 | * optimized .js version of a text resource should be loaded 173 | * instead. 174 | * @param {String} url 175 | * @returns Boolean 176 | */ 177 | canUseXhr: function (url, protocol, hostname, port) { 178 | var match = text.xdRegExp.exec(url), 179 | uProtocol, uHostName, uPort; 180 | if (!match) { 181 | return true; 182 | } 183 | uProtocol = match[2]; 184 | uHostName = match[3]; 185 | 186 | uHostName = uHostName.split(':'); 187 | uPort = uHostName[1]; 188 | uHostName = uHostName[0]; 189 | 190 | return (!uProtocol || uProtocol === protocol) && 191 | (!uHostName || uHostName === hostname) && 192 | ((!uPort && !uHostName) || uPort === port); 193 | }, 194 | 195 | finishLoad: function (name, strip, content, onLoad, config) { 196 | content = strip ? text.strip(content) : content; 197 | if (config.isBuild && config.inlineText) { 198 | buildMap[name] = content; 199 | } 200 | onLoad(content); 201 | }, 202 | 203 | load: function (name, req, onLoad, config) { 204 | //Name has format: some.module.filext!strip 205 | //The strip part is optional. 206 | //if strip is present, then that means only get the string contents 207 | //inside a body tag in an HTML string. For XML/SVG content it means 208 | //removing the declarations so the content can be inserted 209 | //into the current doc without problems. 210 | 211 | var parsed = text.parseName(name), 212 | nonStripName = parsed.moduleName + '.' + parsed.ext, 213 | url = req.toUrl(nonStripName); 214 | 215 | //Load the text. Use XHR if possible and in a browser. 216 | if (!hasLocation || text.canUseXhr(url)) { 217 | text.get(url, function (content) { 218 | text.finishLoad(name, parsed.strip, content, onLoad, config); 219 | }); 220 | } else { 221 | //Need to fetch the resource across domains. Assume 222 | //the resource has been optimized into a JS module. Fetch 223 | //by the module name + extension, but do not include the 224 | //!strip part to avoid file system issues. 225 | req([nonStripName], function (content) { 226 | text.finishLoad(parsed.moduleName + '.' + parsed.ext, 227 | parsed.strip, content, onLoad, config); 228 | }); 229 | } 230 | }, 231 | 232 | write: function (pluginName, moduleName, write, config) { 233 | if (moduleName in buildMap) { 234 | var content = text.jsEscape(buildMap[moduleName]); 235 | write("define('" + pluginName + "!" + moduleName + 236 | "', function () { return '" + content + "';});\n"); 237 | } 238 | }, 239 | 240 | writeFile: function (pluginName, moduleName, req, write, config) { 241 | var parsed = text.parseName(moduleName), 242 | nonStripName = parsed.moduleName + '.' + parsed.ext, 243 | //Use a '.js' file name so that it indicates it is a 244 | //script that can be loaded across domains. 245 | fileName = req.toUrl(parsed.moduleName + '.' + 246 | parsed.ext) + '.js'; 247 | 248 | //Leverage own load() method to load plugin value, but only 249 | //write out values that do not have the strip argument, 250 | //to avoid any potential issues with ! in file names. 251 | text.load(nonStripName, req, function (value) { 252 | //Use own write() method to construct full module value. 253 | text.write(pluginName, nonStripName, function (contents) { 254 | write(fileName, contents); 255 | }, config); 256 | }, config); 257 | } 258 | }; 259 | 260 | return text; 261 | }); 262 | }()); 263 | -------------------------------------------------------------------------------- /data/require.js: -------------------------------------------------------------------------------- 1 | /** vim: et:ts=4:sw=4:sts=4 2 | * @license RequireJS 1.0.3 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. 3 | * Available via the MIT or new BSD license. 4 | * see: http://github.com/jrburke/requirejs for details 5 | */ 6 | /*jslint strict: false, plusplus: false, sub: true */ 7 | /*global window: false, navigator: false, document: false, importScripts: false, 8 | jQuery: false, clearInterval: false, setInterval: false, self: false, 9 | setTimeout: false, opera: false */ 10 | 11 | var requirejs, require, define; 12 | (function () { 13 | //Change this version number for each release. 14 | var version = "1.0.3", 15 | commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg, 16 | cjsRequireRegExp = /require\(\s*["']([^'"\s]+)["']\s*\)/g, 17 | currDirRegExp = /^\.\//, 18 | jsSuffixRegExp = /\.js$/, 19 | ostring = Object.prototype.toString, 20 | ap = Array.prototype, 21 | aps = ap.slice, 22 | apsp = ap.splice, 23 | isBrowser = !!(typeof window !== "undefined" && navigator && document), 24 | isWebWorker = !isBrowser && typeof importScripts !== "undefined", 25 | //PS3 indicates loaded and complete, but need to wait for complete 26 | //specifically. Sequence is "loading", "loaded", execution, 27 | // then "complete". The UA check is unfortunate, but not sure how 28 | //to feature test w/o causing perf issues. 29 | readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ? 30 | /^complete$/ : /^(complete|loaded)$/, 31 | defContextName = "_", 32 | //Oh the tragedy, detecting opera. See the usage of isOpera for reason. 33 | isOpera = typeof opera !== "undefined" && opera.toString() === "[object Opera]", 34 | empty = {}, 35 | contexts = {}, 36 | globalDefQueue = [], 37 | interactiveScript = null, 38 | checkLoadedDepth = 0, 39 | useInteractive = false, 40 | req, cfg = {}, currentlyAddingScript, s, head, baseElement, scripts, script, 41 | src, subPath, mainScript, dataMain, i, ctx, jQueryCheck, checkLoadedTimeoutId; 42 | 43 | function isFunction(it) { 44 | return ostring.call(it) === "[object Function]"; 45 | } 46 | 47 | function isArray(it) { 48 | return ostring.call(it) === "[object Array]"; 49 | } 50 | 51 | /** 52 | * Simple function to mix in properties from source into target, 53 | * but only if target does not already have a property of the same name. 54 | * This is not robust in IE for transferring methods that match 55 | * Object.prototype names, but the uses of mixin here seem unlikely to 56 | * trigger a problem related to that. 57 | */ 58 | function mixin(target, source, force) { 59 | for (var prop in source) { 60 | if (!(prop in empty) && (!(prop in target) || force)) { 61 | target[prop] = source[prop]; 62 | } 63 | } 64 | return req; 65 | } 66 | 67 | /** 68 | * Constructs an error with a pointer to an URL with more information. 69 | * @param {String} id the error ID that maps to an ID on a web page. 70 | * @param {String} message human readable error. 71 | * @param {Error} [err] the original error, if there is one. 72 | * 73 | * @returns {Error} 74 | */ 75 | function makeError(id, msg, err) { 76 | var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id); 77 | if (err) { 78 | e.originalError = err; 79 | } 80 | return e; 81 | } 82 | 83 | /** 84 | * Used to set up package paths from a packagePaths or packages config object. 85 | * @param {Object} pkgs the object to store the new package config 86 | * @param {Array} currentPackages an array of packages to configure 87 | * @param {String} [dir] a prefix dir to use. 88 | */ 89 | function configurePackageDir(pkgs, currentPackages, dir) { 90 | var i, location, pkgObj; 91 | 92 | for (i = 0; (pkgObj = currentPackages[i]); i++) { 93 | pkgObj = typeof pkgObj === "string" ? { name: pkgObj } : pkgObj; 94 | location = pkgObj.location; 95 | 96 | //Add dir to the path, but avoid paths that start with a slash 97 | //or have a colon (indicates a protocol) 98 | if (dir && (!location || (location.indexOf("/") !== 0 && location.indexOf(":") === -1))) { 99 | location = dir + "/" + (location || pkgObj.name); 100 | } 101 | 102 | //Create a brand new object on pkgs, since currentPackages can 103 | //be passed in again, and config.pkgs is the internal transformed 104 | //state for all package configs. 105 | pkgs[pkgObj.name] = { 106 | name: pkgObj.name, 107 | location: location || pkgObj.name, 108 | //Remove leading dot in main, so main paths are normalized, 109 | //and remove any trailing .js, since different package 110 | //envs have different conventions: some use a module name, 111 | //some use a file name. 112 | main: (pkgObj.main || "main") 113 | .replace(currDirRegExp, '') 114 | .replace(jsSuffixRegExp, '') 115 | }; 116 | } 117 | } 118 | 119 | /** 120 | * jQuery 1.4.3-1.5.x use a readyWait/ready() pairing to hold DOM 121 | * ready callbacks, but jQuery 1.6 supports a holdReady() API instead. 122 | * At some point remove the readyWait/ready() support and just stick 123 | * with using holdReady. 124 | */ 125 | function jQueryHoldReady($, shouldHold) { 126 | if ($.holdReady) { 127 | $.holdReady(shouldHold); 128 | } else if (shouldHold) { 129 | $.readyWait += 1; 130 | } else { 131 | $.ready(true); 132 | } 133 | } 134 | 135 | if (typeof define !== "undefined") { 136 | //If a define is already in play via another AMD loader, 137 | //do not overwrite. 138 | return; 139 | } 140 | 141 | if (typeof requirejs !== "undefined") { 142 | if (isFunction(requirejs)) { 143 | //Do not overwrite and existing requirejs instance. 144 | return; 145 | } else { 146 | cfg = requirejs; 147 | requirejs = undefined; 148 | } 149 | } 150 | 151 | //Allow for a require config object 152 | if (typeof require !== "undefined" && !isFunction(require)) { 153 | //assume it is a config object. 154 | cfg = require; 155 | require = undefined; 156 | } 157 | 158 | /** 159 | * Creates a new context for use in require and define calls. 160 | * Handle most of the heavy lifting. Do not want to use an object 161 | * with prototype here to avoid using "this" in require, in case it 162 | * needs to be used in more super secure envs that do not want this. 163 | * Also there should not be that many contexts in the page. Usually just 164 | * one for the default context, but could be extra for multiversion cases 165 | * or if a package needs a special context for a dependency that conflicts 166 | * with the standard context. 167 | */ 168 | function newContext(contextName) { 169 | var context, resume, 170 | config = { 171 | waitSeconds: 7, 172 | baseUrl: "./", 173 | paths: {}, 174 | pkgs: {}, 175 | catchError: {} 176 | }, 177 | defQueue = [], 178 | specified = { 179 | "require": true, 180 | "exports": true, 181 | "module": true 182 | }, 183 | urlMap = {}, 184 | defined = {}, 185 | loaded = {}, 186 | waiting = {}, 187 | waitAry = [], 188 | urlFetched = {}, 189 | managerCounter = 0, 190 | managerCallbacks = {}, 191 | plugins = {}, 192 | //Used to indicate which modules in a build scenario 193 | //need to be full executed. 194 | needFullExec = {}, 195 | fullExec = {}, 196 | resumeDepth = 0; 197 | 198 | /** 199 | * Trims the . and .. from an array of path segments. 200 | * It will keep a leading path segment if a .. will become 201 | * the first path segment, to help with module name lookups, 202 | * which act like paths, but can be remapped. But the end result, 203 | * all paths that use this function should look normalized. 204 | * NOTE: this method MODIFIES the input array. 205 | * @param {Array} ary the array of path segments. 206 | */ 207 | function trimDots(ary) { 208 | var i, part; 209 | for (i = 0; (part = ary[i]); i++) { 210 | if (part === ".") { 211 | ary.splice(i, 1); 212 | i -= 1; 213 | } else if (part === "..") { 214 | if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { 215 | //End of the line. Keep at least one non-dot 216 | //path segment at the front so it can be mapped 217 | //correctly to disk. Otherwise, there is likely 218 | //no path mapping for a path starting with '..'. 219 | //This can still fail, but catches the most reasonable 220 | //uses of .. 221 | break; 222 | } else if (i > 0) { 223 | ary.splice(i - 1, 2); 224 | i -= 2; 225 | } 226 | } 227 | } 228 | } 229 | 230 | /** 231 | * Given a relative module name, like ./something, normalize it to 232 | * a real name that can be mapped to a path. 233 | * @param {String} name the relative name 234 | * @param {String} baseName a real name that the name arg is relative 235 | * to. 236 | * @returns {String} normalized name 237 | */ 238 | function normalize(name, baseName) { 239 | var pkgName, pkgConfig; 240 | 241 | //Adjust any relative paths. 242 | if (name && name.charAt(0) === ".") { 243 | //If have a base name, try to normalize against it, 244 | //otherwise, assume it is a top-level require that will 245 | //be relative to baseUrl in the end. 246 | if (baseName) { 247 | if (config.pkgs[baseName]) { 248 | //If the baseName is a package name, then just treat it as one 249 | //name to concat the name with. 250 | baseName = [baseName]; 251 | } else { 252 | //Convert baseName to array, and lop off the last part, 253 | //so that . matches that "directory" and not name of the baseName's 254 | //module. For instance, baseName of "one/two/three", maps to 255 | //"one/two/three.js", but we want the directory, "one/two" for 256 | //this normalization. 257 | baseName = baseName.split("/"); 258 | baseName = baseName.slice(0, baseName.length - 1); 259 | } 260 | 261 | name = baseName.concat(name.split("/")); 262 | trimDots(name); 263 | 264 | //Some use of packages may use a . path to reference the 265 | //"main" module name, so normalize for that. 266 | pkgConfig = config.pkgs[(pkgName = name[0])]; 267 | name = name.join("/"); 268 | if (pkgConfig && name === pkgName + '/' + pkgConfig.main) { 269 | name = pkgName; 270 | } 271 | } else if (name.indexOf("./") === 0) { 272 | // No baseName, so this is ID is resolved relative 273 | // to baseUrl, pull off the leading dot. 274 | name = name.substring(2); 275 | } 276 | } 277 | return name; 278 | } 279 | 280 | /** 281 | * Creates a module mapping that includes plugin prefix, module 282 | * name, and path. If parentModuleMap is provided it will 283 | * also normalize the name via require.normalize() 284 | * 285 | * @param {String} name the module name 286 | * @param {String} [parentModuleMap] parent module map 287 | * for the module name, used to resolve relative names. 288 | * 289 | * @returns {Object} 290 | */ 291 | function makeModuleMap(name, parentModuleMap) { 292 | var index = name ? name.indexOf("!") : -1, 293 | prefix = null, 294 | parentName = parentModuleMap ? parentModuleMap.name : null, 295 | originalName = name, 296 | normalizedName, url, pluginModule; 297 | 298 | if (index !== -1) { 299 | prefix = name.substring(0, index); 300 | name = name.substring(index + 1, name.length); 301 | } 302 | 303 | if (prefix) { 304 | prefix = normalize(prefix, parentName); 305 | } 306 | 307 | //Account for relative paths if there is a base name. 308 | if (name) { 309 | if (prefix) { 310 | pluginModule = defined[prefix]; 311 | if (pluginModule && pluginModule.normalize) { 312 | //Plugin is loaded, use its normalize method. 313 | normalizedName = pluginModule.normalize(name, function (name) { 314 | return normalize(name, parentName); 315 | }); 316 | } else { 317 | normalizedName = normalize(name, parentName); 318 | } 319 | } else { 320 | //A regular module. 321 | normalizedName = normalize(name, parentName); 322 | 323 | url = urlMap[normalizedName]; 324 | if (!url) { 325 | //Calculate url for the module, if it has a name. 326 | url = context.nameToUrl(normalizedName, null, parentModuleMap); 327 | 328 | //Store the URL mapping for later. 329 | urlMap[normalizedName] = url; 330 | } 331 | } 332 | } 333 | 334 | return { 335 | prefix: prefix, 336 | name: normalizedName, 337 | parentMap: parentModuleMap, 338 | url: url, 339 | originalName: originalName, 340 | fullName: prefix ? prefix + "!" + (normalizedName || '') : normalizedName 341 | }; 342 | } 343 | 344 | /** 345 | * Determine if priority loading is done. If so clear the priorityWait 346 | */ 347 | function isPriorityDone() { 348 | var priorityDone = true, 349 | priorityWait = config.priorityWait, 350 | priorityName, i; 351 | if (priorityWait) { 352 | for (i = 0; (priorityName = priorityWait[i]); i++) { 353 | if (!loaded[priorityName]) { 354 | priorityDone = false; 355 | break; 356 | } 357 | } 358 | if (priorityDone) { 359 | delete config.priorityWait; 360 | } 361 | } 362 | return priorityDone; 363 | } 364 | 365 | function makeContextModuleFunc(func, relModuleMap, enableBuildCallback) { 366 | return function () { 367 | //A version of a require function that passes a moduleName 368 | //value for items that may need to 369 | //look up paths relative to the moduleName 370 | var args = aps.call(arguments, 0), lastArg; 371 | if (enableBuildCallback && 372 | isFunction((lastArg = args[args.length - 1]))) { 373 | lastArg.__requireJsBuild = true; 374 | } 375 | args.push(relModuleMap); 376 | return func.apply(null, args); 377 | }; 378 | } 379 | 380 | /** 381 | * Helper function that creates a require function object to give to 382 | * modules that ask for it as a dependency. It needs to be specific 383 | * per module because of the implication of path mappings that may 384 | * need to be relative to the module name. 385 | */ 386 | function makeRequire(relModuleMap, enableBuildCallback) { 387 | var modRequire = makeContextModuleFunc(context.require, relModuleMap, enableBuildCallback); 388 | 389 | mixin(modRequire, { 390 | nameToUrl: makeContextModuleFunc(context.nameToUrl, relModuleMap), 391 | toUrl: makeContextModuleFunc(context.toUrl, relModuleMap), 392 | defined: makeContextModuleFunc(context.requireDefined, relModuleMap), 393 | specified: makeContextModuleFunc(context.requireSpecified, relModuleMap), 394 | isBrowser: req.isBrowser 395 | }); 396 | return modRequire; 397 | } 398 | 399 | /* 400 | * Queues a dependency for checking after the loader is out of a 401 | * "paused" state, for example while a script file is being loaded 402 | * in the browser, where it may have many modules defined in it. 403 | */ 404 | function queueDependency(manager) { 405 | context.paused.push(manager); 406 | } 407 | 408 | function execManager(manager) { 409 | var i, ret, err, errFile, errModuleTree, 410 | cb = manager.callback, 411 | map = manager.map, 412 | fullName = map.fullName, 413 | args = manager.deps, 414 | listeners = manager.listeners, 415 | cjsModule; 416 | 417 | //Call the callback to define the module, if necessary. 418 | if (cb && isFunction(cb)) { 419 | if (config.catchError.define) { 420 | try { 421 | ret = req.execCb(fullName, manager.callback, args, defined[fullName]); 422 | } catch (e) { 423 | err = e; 424 | } 425 | } else { 426 | ret = req.execCb(fullName, manager.callback, args, defined[fullName]); 427 | } 428 | 429 | if (fullName) { 430 | //If setting exports via "module" is in play, 431 | //favor that over return value and exports. After that, 432 | //favor a non-undefined return value over exports use. 433 | cjsModule = manager.cjsModule; 434 | if (cjsModule && 435 | cjsModule.exports !== undefined && 436 | //Make sure it is not already the exports value 437 | cjsModule.exports !== defined[fullName]) { 438 | ret = defined[fullName] = manager.cjsModule.exports; 439 | } else if (ret === undefined && manager.usingExports) { 440 | //exports already set the defined value. 441 | ret = defined[fullName]; 442 | } else { 443 | //Use the return value from the function. 444 | defined[fullName] = ret; 445 | //If this module needed full execution in a build 446 | //environment, mark that now. 447 | if (needFullExec[fullName]) { 448 | fullExec[fullName] = true; 449 | } 450 | } 451 | } 452 | } else if (fullName) { 453 | //May just be an object definition for the module. Only 454 | //worry about defining if have a module name. 455 | ret = defined[fullName] = cb; 456 | 457 | //If this module needed full execution in a build 458 | //environment, mark that now. 459 | if (needFullExec[fullName]) { 460 | fullExec[fullName] = true; 461 | } 462 | } 463 | 464 | //Clean up waiting. Do this before error calls, and before 465 | //calling back listeners, so that bookkeeping is correct 466 | //in the event of an error and error is reported in correct order, 467 | //since the listeners will likely have errors if the 468 | //onError function does not throw. 469 | if (waiting[manager.id]) { 470 | delete waiting[manager.id]; 471 | manager.isDone = true; 472 | context.waitCount -= 1; 473 | if (context.waitCount === 0) { 474 | //Clear the wait array used for cycles. 475 | waitAry = []; 476 | } 477 | } 478 | 479 | //Do not need to track manager callback now that it is defined. 480 | delete managerCallbacks[fullName]; 481 | 482 | //Allow instrumentation like the optimizer to know the order 483 | //of modules executed and their dependencies. 484 | if (req.onResourceLoad && !manager.placeholder) { 485 | req.onResourceLoad(context, map, manager.depArray); 486 | } 487 | 488 | if (err) { 489 | errFile = (fullName ? makeModuleMap(fullName).url : '') || 490 | err.fileName || err.sourceURL; 491 | errModuleTree = err.moduleTree; 492 | err = makeError('defineerror', 'Error evaluating ' + 493 | 'module "' + fullName + '" at location "' + 494 | errFile + '":\n' + 495 | err + '\nfileName:' + errFile + 496 | '\nlineNumber: ' + (err.lineNumber || err.line), err); 497 | err.moduleName = fullName; 498 | err.moduleTree = errModuleTree; 499 | return req.onError(err); 500 | } 501 | 502 | //Let listeners know of this manager's value. 503 | for (i = 0; (cb = listeners[i]); i++) { 504 | cb(ret); 505 | } 506 | 507 | return undefined; 508 | } 509 | 510 | /** 511 | * Helper that creates a callack function that is called when a dependency 512 | * is ready, and sets the i-th dependency for the manager as the 513 | * value passed to the callback generated by this function. 514 | */ 515 | function makeArgCallback(manager, i) { 516 | return function (value) { 517 | //Only do the work if it has not been done 518 | //already for a dependency. Cycle breaking 519 | //logic in forceExec could mean this function 520 | //is called more than once for a given dependency. 521 | if (!manager.depDone[i]) { 522 | manager.depDone[i] = true; 523 | manager.deps[i] = value; 524 | manager.depCount -= 1; 525 | if (!manager.depCount) { 526 | //All done, execute! 527 | execManager(manager); 528 | } 529 | } 530 | }; 531 | } 532 | 533 | function callPlugin(pluginName, depManager) { 534 | var map = depManager.map, 535 | fullName = map.fullName, 536 | name = map.name, 537 | plugin = plugins[pluginName] || 538 | (plugins[pluginName] = defined[pluginName]), 539 | load; 540 | 541 | //No need to continue if the manager is already 542 | //in the process of loading. 543 | if (depManager.loading) { 544 | return; 545 | } 546 | depManager.loading = true; 547 | 548 | load = function (ret) { 549 | depManager.callback = function () { 550 | return ret; 551 | }; 552 | execManager(depManager); 553 | 554 | loaded[depManager.id] = true; 555 | 556 | //The loading of this plugin 557 | //might have placed other things 558 | //in the paused queue. In particular, 559 | //a loader plugin that depends on 560 | //a different plugin loaded resource. 561 | resume(); 562 | }; 563 | 564 | //Allow plugins to load other code without having to know the 565 | //context or how to "complete" the load. 566 | load.fromText = function (moduleName, text) { 567 | /*jslint evil: true */ 568 | var hasInteractive = useInteractive; 569 | 570 | //Indicate a the module is in process of loading. 571 | loaded[moduleName] = false; 572 | context.scriptCount += 1; 573 | 574 | //Indicate this is not a "real" module, so do not track it 575 | //for builds, it does not map to a real file. 576 | context.fake[moduleName] = true; 577 | 578 | //Turn off interactive script matching for IE for any define 579 | //calls in the text, then turn it back on at the end. 580 | if (hasInteractive) { 581 | useInteractive = false; 582 | } 583 | 584 | req.exec(text); 585 | 586 | if (hasInteractive) { 587 | useInteractive = true; 588 | } 589 | 590 | //Support anonymous modules. 591 | context.completeLoad(moduleName); 592 | }; 593 | 594 | //No need to continue if the plugin value has already been 595 | //defined by a build. 596 | if (fullName in defined) { 597 | load(defined[fullName]); 598 | } else { 599 | //Use parentName here since the plugin's name is not reliable, 600 | //could be some weird string with no path that actually wants to 601 | //reference the parentName's path. 602 | plugin.load(name, makeRequire(map.parentMap, true), load, config); 603 | } 604 | } 605 | 606 | /** 607 | * Adds the manager to the waiting queue. Only fully 608 | * resolved items should be in the waiting queue. 609 | */ 610 | function addWait(manager) { 611 | if (!waiting[manager.id]) { 612 | waiting[manager.id] = manager; 613 | waitAry.push(manager); 614 | context.waitCount += 1; 615 | } 616 | } 617 | 618 | /** 619 | * Function added to every manager object. Created out here 620 | * to avoid new function creation for each manager instance. 621 | */ 622 | function managerAdd(cb) { 623 | this.listeners.push(cb); 624 | } 625 | 626 | function getManager(map, shouldQueue) { 627 | var fullName = map.fullName, 628 | prefix = map.prefix, 629 | plugin = prefix ? plugins[prefix] || 630 | (plugins[prefix] = defined[prefix]) : null, 631 | manager, created, pluginManager; 632 | 633 | if (fullName) { 634 | manager = managerCallbacks[fullName]; 635 | } 636 | 637 | if (!manager) { 638 | created = true; 639 | manager = { 640 | //ID is just the full name, but if it is a plugin resource 641 | //for a plugin that has not been loaded, 642 | //then add an ID counter to it. 643 | id: (prefix && !plugin ? 644 | (managerCounter++) + '__p@:' : '') + 645 | (fullName || '__r@' + (managerCounter++)), 646 | map: map, 647 | depCount: 0, 648 | depDone: [], 649 | depCallbacks: [], 650 | deps: [], 651 | listeners: [], 652 | add: managerAdd 653 | }; 654 | 655 | specified[manager.id] = true; 656 | 657 | //Only track the manager/reuse it if this is a non-plugin 658 | //resource. Also only track plugin resources once 659 | //the plugin has been loaded, and so the fullName is the 660 | //true normalized value. 661 | if (fullName && (!prefix || plugins[prefix])) { 662 | managerCallbacks[fullName] = manager; 663 | } 664 | } 665 | 666 | //If there is a plugin needed, but it is not loaded, 667 | //first load the plugin, then continue on. 668 | if (prefix && !plugin) { 669 | pluginManager = getManager(makeModuleMap(prefix), true); 670 | pluginManager.add(function (plugin) { 671 | //Create a new manager for the normalized 672 | //resource ID and have it call this manager when 673 | //done. 674 | var newMap = makeModuleMap(map.originalName, map.parentMap), 675 | normalizedManager = getManager(newMap, true); 676 | 677 | //Indicate this manager is a placeholder for the real, 678 | //normalized thing. Important for when trying to map 679 | //modules and dependencies, for instance, in a build. 680 | manager.placeholder = true; 681 | 682 | normalizedManager.add(function (resource) { 683 | manager.callback = function () { 684 | return resource; 685 | }; 686 | execManager(manager); 687 | }); 688 | }); 689 | } else if (created && shouldQueue) { 690 | //Indicate the resource is not loaded yet if it is to be 691 | //queued. 692 | loaded[manager.id] = false; 693 | queueDependency(manager); 694 | addWait(manager); 695 | } 696 | 697 | return manager; 698 | } 699 | 700 | function main(inName, depArray, callback, relModuleMap) { 701 | var moduleMap = makeModuleMap(inName, relModuleMap), 702 | name = moduleMap.name, 703 | fullName = moduleMap.fullName, 704 | manager = getManager(moduleMap), 705 | id = manager.id, 706 | deps = manager.deps, 707 | i, depArg, depName, depPrefix, cjsMod; 708 | 709 | if (fullName) { 710 | //If module already defined for context, or already loaded, 711 | //then leave. Also leave if jQuery is registering but it does 712 | //not match the desired version number in the config. 713 | if (fullName in defined || loaded[id] === true || 714 | (fullName === "jquery" && config.jQuery && 715 | config.jQuery !== callback().fn.jquery)) { 716 | return; 717 | } 718 | 719 | //Set specified/loaded here for modules that are also loaded 720 | //as part of a layer, where onScriptLoad is not fired 721 | //for those cases. Do this after the inline define and 722 | //dependency tracing is done. 723 | specified[id] = true; 724 | loaded[id] = true; 725 | 726 | //If module is jQuery set up delaying its dom ready listeners. 727 | if (fullName === "jquery" && callback) { 728 | jQueryCheck(callback()); 729 | } 730 | } 731 | 732 | //Attach real depArray and callback to the manager. Do this 733 | //only if the module has not been defined already, so do this after 734 | //the fullName checks above. IE can call main() more than once 735 | //for a module. 736 | manager.depArray = depArray; 737 | manager.callback = callback; 738 | 739 | //Add the dependencies to the deps field, and register for callbacks 740 | //on the dependencies. 741 | for (i = 0; i < depArray.length; i++) { 742 | depArg = depArray[i]; 743 | //There could be cases like in IE, where a trailing comma will 744 | //introduce a null dependency, so only treat a real dependency 745 | //value as a dependency. 746 | if (depArg) { 747 | //Split the dependency name into plugin and name parts 748 | depArg = makeModuleMap(depArg, (name ? moduleMap : relModuleMap)); 749 | depName = depArg.fullName; 750 | depPrefix = depArg.prefix; 751 | 752 | //Fix the name in depArray to be just the name, since 753 | //that is how it will be called back later. 754 | depArray[i] = depName; 755 | 756 | //Fast path CommonJS standard dependencies. 757 | if (depName === "require") { 758 | deps[i] = makeRequire(moduleMap); 759 | } else if (depName === "exports") { 760 | //CommonJS module spec 1.1 761 | deps[i] = defined[fullName] = {}; 762 | manager.usingExports = true; 763 | } else if (depName === "module") { 764 | //CommonJS module spec 1.1 765 | manager.cjsModule = cjsMod = deps[i] = { 766 | id: name, 767 | uri: name ? context.nameToUrl(name, null, relModuleMap) : undefined, 768 | exports: defined[fullName] 769 | }; 770 | } else if (depName in defined && !(depName in waiting) && 771 | (!(fullName in needFullExec) || 772 | (fullName in needFullExec && fullExec[depName]))) { 773 | //Module already defined, and not in a build situation 774 | //where the module is a something that needs full 775 | //execution and this dependency has not been fully 776 | //executed. See r.js's requirePatch.js for more info 777 | //on fullExec. 778 | deps[i] = defined[depName]; 779 | } else { 780 | //Mark this dependency as needing full exec if 781 | //the current module needs full exec. 782 | if (fullName in needFullExec) { 783 | needFullExec[depName] = true; 784 | //Reset state so fully executed code will get 785 | //picked up correctly. 786 | delete defined[depName]; 787 | urlFetched[depArg.url] = false; 788 | } 789 | 790 | //Either a resource that is not loaded yet, or a plugin 791 | //resource for either a plugin that has not 792 | //loaded yet. 793 | manager.depCount += 1; 794 | manager.depCallbacks[i] = makeArgCallback(manager, i); 795 | getManager(depArg, true).add(manager.depCallbacks[i]); 796 | } 797 | } 798 | } 799 | 800 | //Do not bother tracking the manager if it is all done. 801 | if (!manager.depCount) { 802 | //All done, execute! 803 | execManager(manager); 804 | } else { 805 | addWait(manager); 806 | } 807 | } 808 | 809 | /** 810 | * Convenience method to call main for a define call that was put on 811 | * hold in the defQueue. 812 | */ 813 | function callDefMain(args) { 814 | main.apply(null, args); 815 | } 816 | 817 | /** 818 | * jQuery 1.4.3+ supports ways to hold off calling 819 | * calling jQuery ready callbacks until all scripts are loaded. Be sure 820 | * to track it if the capability exists.. Also, since jQuery 1.4.3 does 821 | * not register as a module, need to do some global inference checking. 822 | * Even if it does register as a module, not guaranteed to be the precise 823 | * name of the global. If a jQuery is tracked for this context, then go 824 | * ahead and register it as a module too, if not already in process. 825 | */ 826 | jQueryCheck = function (jqCandidate) { 827 | if (!context.jQuery) { 828 | var $ = jqCandidate || (typeof jQuery !== "undefined" ? jQuery : null); 829 | 830 | if ($) { 831 | //If a specific version of jQuery is wanted, make sure to only 832 | //use this jQuery if it matches. 833 | if (config.jQuery && $.fn.jquery !== config.jQuery) { 834 | return; 835 | } 836 | 837 | if ("holdReady" in $ || "readyWait" in $) { 838 | context.jQuery = $; 839 | 840 | //Manually create a "jquery" module entry if not one already 841 | //or in process. Note this could trigger an attempt at 842 | //a second jQuery registration, but does no harm since 843 | //the first one wins, and it is the same value anyway. 844 | callDefMain(["jquery", [], function () { 845 | return jQuery; 846 | }]); 847 | 848 | //Ask jQuery to hold DOM ready callbacks. 849 | if (context.scriptCount) { 850 | jQueryHoldReady($, true); 851 | context.jQueryIncremented = true; 852 | } 853 | } 854 | } 855 | } 856 | }; 857 | 858 | function forceExec(manager, traced) { 859 | if (manager.isDone) { 860 | return undefined; 861 | } 862 | 863 | var fullName = manager.map.fullName, 864 | depArray = manager.depArray, 865 | i, depName, depManager, prefix, prefixManager, value; 866 | 867 | if (fullName) { 868 | if (traced[fullName]) { 869 | return defined[fullName]; 870 | } 871 | 872 | traced[fullName] = true; 873 | } 874 | 875 | //Trace through the dependencies. 876 | if (depArray) { 877 | for (i = 0; i < depArray.length; i++) { 878 | //Some array members may be null, like if a trailing comma 879 | //IE, so do the explicit [i] access and check if it has a value. 880 | depName = depArray[i]; 881 | if (depName) { 882 | //First, make sure if it is a plugin resource that the 883 | //plugin is not blocked. 884 | prefix = makeModuleMap(depName).prefix; 885 | if (prefix && (prefixManager = waiting[prefix])) { 886 | forceExec(prefixManager, traced); 887 | } 888 | depManager = waiting[depName]; 889 | if (depManager && !depManager.isDone && loaded[depName]) { 890 | value = forceExec(depManager, traced); 891 | manager.depCallbacks[i](value); 892 | } 893 | } 894 | } 895 | } 896 | 897 | return fullName ? defined[fullName] : undefined; 898 | } 899 | 900 | /** 901 | * Checks if all modules for a context are loaded, and if so, evaluates the 902 | * new ones in right dependency order. 903 | * 904 | * @private 905 | */ 906 | function checkLoaded() { 907 | var waitInterval = config.waitSeconds * 1000, 908 | //It is possible to disable the wait interval by using waitSeconds of 0. 909 | expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(), 910 | noLoads = "", hasLoadedProp = false, stillLoading = false, prop, 911 | err, manager; 912 | 913 | //If there are items still in the paused queue processing wait. 914 | //This is particularly important in the sync case where each paused 915 | //item is processed right away but there may be more waiting. 916 | if (context.pausedCount > 0) { 917 | return undefined; 918 | } 919 | 920 | //Determine if priority loading is done. If so clear the priority. If 921 | //not, then do not check 922 | if (config.priorityWait) { 923 | if (isPriorityDone()) { 924 | //Call resume, since it could have 925 | //some waiting dependencies to trace. 926 | resume(); 927 | } else { 928 | return undefined; 929 | } 930 | } 931 | 932 | //See if anything is still in flight. 933 | for (prop in loaded) { 934 | if (!(prop in empty)) { 935 | hasLoadedProp = true; 936 | if (!loaded[prop]) { 937 | if (expired) { 938 | noLoads += prop + " "; 939 | } else { 940 | stillLoading = true; 941 | break; 942 | } 943 | } 944 | } 945 | } 946 | 947 | //Check for exit conditions. 948 | if (!hasLoadedProp && !context.waitCount) { 949 | //If the loaded object had no items, then the rest of 950 | //the work below does not need to be done. 951 | return undefined; 952 | } 953 | if (expired && noLoads) { 954 | //If wait time expired, throw error of unloaded modules. 955 | err = makeError("timeout", "Load timeout for modules: " + noLoads); 956 | err.requireType = "timeout"; 957 | err.requireModules = noLoads; 958 | return req.onError(err); 959 | } 960 | if (stillLoading || context.scriptCount) { 961 | //Something is still waiting to load. Wait for it, but only 962 | //if a timeout is not already in effect. 963 | if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) { 964 | checkLoadedTimeoutId = setTimeout(function () { 965 | checkLoadedTimeoutId = 0; 966 | checkLoaded(); 967 | }, 50); 968 | } 969 | return undefined; 970 | } 971 | 972 | //If still have items in the waiting cue, but all modules have 973 | //been loaded, then it means there are some circular dependencies 974 | //that need to be broken. 975 | //However, as a waiting thing is fired, then it can add items to 976 | //the waiting cue, and those items should not be fired yet, so 977 | //make sure to redo the checkLoaded call after breaking a single 978 | //cycle, if nothing else loaded then this logic will pick it up 979 | //again. 980 | if (context.waitCount) { 981 | //Cycle through the waitAry, and call items in sequence. 982 | for (i = 0; (manager = waitAry[i]); i++) { 983 | forceExec(manager, {}); 984 | } 985 | 986 | //If anything got placed in the paused queue, run it down. 987 | if (context.paused.length) { 988 | resume(); 989 | } 990 | 991 | //Only allow this recursion to a certain depth. Only 992 | //triggered by errors in calling a module in which its 993 | //modules waiting on it cannot finish loading, or some circular 994 | //dependencies that then may add more dependencies. 995 | //The value of 5 is a bit arbitrary. Hopefully just one extra 996 | //pass, or two for the case of circular dependencies generating 997 | //more work that gets resolved in the sync node case. 998 | if (checkLoadedDepth < 5) { 999 | checkLoadedDepth += 1; 1000 | checkLoaded(); 1001 | } 1002 | } 1003 | 1004 | checkLoadedDepth = 0; 1005 | 1006 | //Check for DOM ready, and nothing is waiting across contexts. 1007 | req.checkReadyState(); 1008 | 1009 | return undefined; 1010 | } 1011 | 1012 | /** 1013 | * Resumes tracing of dependencies and then checks if everything is loaded. 1014 | */ 1015 | resume = function () { 1016 | var manager, map, url, i, p, args, fullName; 1017 | 1018 | resumeDepth += 1; 1019 | 1020 | if (context.scriptCount <= 0) { 1021 | //Synchronous envs will push the number below zero with the 1022 | //decrement above, be sure to set it back to zero for good measure. 1023 | //require() calls that also do not end up loading scripts could 1024 | //push the number negative too. 1025 | context.scriptCount = 0; 1026 | } 1027 | 1028 | //Make sure any remaining defQueue items get properly processed. 1029 | while (defQueue.length) { 1030 | args = defQueue.shift(); 1031 | if (args[0] === null) { 1032 | return req.onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1])); 1033 | } else { 1034 | callDefMain(args); 1035 | } 1036 | } 1037 | 1038 | //Skip the resume of paused dependencies 1039 | //if current context is in priority wait. 1040 | if (!config.priorityWait || isPriorityDone()) { 1041 | while (context.paused.length) { 1042 | p = context.paused; 1043 | context.pausedCount += p.length; 1044 | //Reset paused list 1045 | context.paused = []; 1046 | 1047 | for (i = 0; (manager = p[i]); i++) { 1048 | map = manager.map; 1049 | url = map.url; 1050 | fullName = map.fullName; 1051 | 1052 | //If the manager is for a plugin managed resource, 1053 | //ask the plugin to load it now. 1054 | if (map.prefix) { 1055 | callPlugin(map.prefix, manager); 1056 | } else { 1057 | //Regular dependency. 1058 | if (!urlFetched[url] && !loaded[fullName]) { 1059 | req.load(context, fullName, url); 1060 | 1061 | //Mark the URL as fetched, but only if it is 1062 | //not an empty: URL, used by the optimizer. 1063 | //In that case we need to be sure to call 1064 | //load() for each module that is mapped to 1065 | //empty: so that dependencies are satisfied 1066 | //correctly. 1067 | if (url.indexOf('empty:') !== 0) { 1068 | urlFetched[url] = true; 1069 | } 1070 | } 1071 | } 1072 | } 1073 | 1074 | //Move the start time for timeout forward. 1075 | context.startTime = (new Date()).getTime(); 1076 | context.pausedCount -= p.length; 1077 | } 1078 | } 1079 | 1080 | //Only check if loaded when resume depth is 1. It is likely that 1081 | //it is only greater than 1 in sync environments where a factory 1082 | //function also then calls the callback-style require. In those 1083 | //cases, the checkLoaded should not occur until the resume 1084 | //depth is back at the top level. 1085 | if (resumeDepth === 1) { 1086 | checkLoaded(); 1087 | } 1088 | 1089 | resumeDepth -= 1; 1090 | 1091 | return undefined; 1092 | }; 1093 | 1094 | //Define the context object. Many of these fields are on here 1095 | //just to make debugging easier. 1096 | context = { 1097 | contextName: contextName, 1098 | config: config, 1099 | defQueue: defQueue, 1100 | waiting: waiting, 1101 | waitCount: 0, 1102 | specified: specified, 1103 | loaded: loaded, 1104 | urlMap: urlMap, 1105 | urlFetched: urlFetched, 1106 | scriptCount: 0, 1107 | defined: defined, 1108 | paused: [], 1109 | pausedCount: 0, 1110 | plugins: plugins, 1111 | needFullExec: needFullExec, 1112 | fake: {}, 1113 | fullExec: fullExec, 1114 | managerCallbacks: managerCallbacks, 1115 | makeModuleMap: makeModuleMap, 1116 | normalize: normalize, 1117 | /** 1118 | * Set a configuration for the context. 1119 | * @param {Object} cfg config object to integrate. 1120 | */ 1121 | configure: function (cfg) { 1122 | var paths, prop, packages, pkgs, packagePaths, requireWait; 1123 | 1124 | //Make sure the baseUrl ends in a slash. 1125 | if (cfg.baseUrl) { 1126 | if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== "/") { 1127 | cfg.baseUrl += "/"; 1128 | } 1129 | } 1130 | 1131 | //Save off the paths and packages since they require special processing, 1132 | //they are additive. 1133 | paths = config.paths; 1134 | packages = config.packages; 1135 | pkgs = config.pkgs; 1136 | 1137 | //Mix in the config values, favoring the new values over 1138 | //existing ones in context.config. 1139 | mixin(config, cfg, true); 1140 | 1141 | //Adjust paths if necessary. 1142 | if (cfg.paths) { 1143 | for (prop in cfg.paths) { 1144 | if (!(prop in empty)) { 1145 | paths[prop] = cfg.paths[prop]; 1146 | } 1147 | } 1148 | config.paths = paths; 1149 | } 1150 | 1151 | packagePaths = cfg.packagePaths; 1152 | if (packagePaths || cfg.packages) { 1153 | //Convert packagePaths into a packages config. 1154 | if (packagePaths) { 1155 | for (prop in packagePaths) { 1156 | if (!(prop in empty)) { 1157 | configurePackageDir(pkgs, packagePaths[prop], prop); 1158 | } 1159 | } 1160 | } 1161 | 1162 | //Adjust packages if necessary. 1163 | if (cfg.packages) { 1164 | configurePackageDir(pkgs, cfg.packages); 1165 | } 1166 | 1167 | //Done with modifications, assing packages back to context config 1168 | config.pkgs = pkgs; 1169 | } 1170 | 1171 | //If priority loading is in effect, trigger the loads now 1172 | if (cfg.priority) { 1173 | //Hold on to requireWait value, and reset it after done 1174 | requireWait = context.requireWait; 1175 | 1176 | //Allow tracing some require calls to allow the fetching 1177 | //of the priority config. 1178 | context.requireWait = false; 1179 | //But first, call resume to register any defined modules that may 1180 | //be in a data-main built file before the priority config 1181 | //call. Also grab any waiting define calls for this context. 1182 | context.takeGlobalQueue(); 1183 | resume(); 1184 | 1185 | context.require(cfg.priority); 1186 | 1187 | //Trigger a resume right away, for the case when 1188 | //the script with the priority load is done as part 1189 | //of a data-main call. In that case the normal resume 1190 | //call will not happen because the scriptCount will be 1191 | //at 1, since the script for data-main is being processed. 1192 | resume(); 1193 | 1194 | //Restore previous state. 1195 | context.requireWait = requireWait; 1196 | config.priorityWait = cfg.priority; 1197 | } 1198 | 1199 | //If a deps array or a config callback is specified, then call 1200 | //require with those args. This is useful when require is defined as a 1201 | //config object before require.js is loaded. 1202 | if (cfg.deps || cfg.callback) { 1203 | context.require(cfg.deps || [], cfg.callback); 1204 | } 1205 | }, 1206 | 1207 | requireDefined: function (moduleName, relModuleMap) { 1208 | return makeModuleMap(moduleName, relModuleMap).fullName in defined; 1209 | }, 1210 | 1211 | requireSpecified: function (moduleName, relModuleMap) { 1212 | return makeModuleMap(moduleName, relModuleMap).fullName in specified; 1213 | }, 1214 | 1215 | require: function (deps, callback, relModuleMap) { 1216 | var moduleName, fullName, moduleMap; 1217 | if (typeof deps === "string") { 1218 | if (isFunction(callback)) { 1219 | //Invalid call 1220 | return req.onError(makeError("requireargs", "Invalid require call")); 1221 | } 1222 | 1223 | //Synchronous access to one module. If require.get is 1224 | //available (as in the Node adapter), prefer that. 1225 | //In this case deps is the moduleName and callback is 1226 | //the relModuleMap 1227 | if (req.get) { 1228 | return req.get(context, deps, callback); 1229 | } 1230 | 1231 | //Just return the module wanted. In this scenario, the 1232 | //second arg (if passed) is just the relModuleMap. 1233 | moduleName = deps; 1234 | relModuleMap = callback; 1235 | 1236 | //Normalize module name, if it contains . or .. 1237 | moduleMap = makeModuleMap(moduleName, relModuleMap); 1238 | fullName = moduleMap.fullName; 1239 | 1240 | if (!(fullName in defined)) { 1241 | return req.onError(makeError("notloaded", "Module name '" + 1242 | moduleMap.fullName + 1243 | "' has not been loaded yet for context: " + 1244 | contextName)); 1245 | } 1246 | return defined[fullName]; 1247 | } 1248 | 1249 | //Call main but only if there are dependencies or 1250 | //a callback to call. 1251 | if (deps && deps.length || callback) { 1252 | main(null, deps, callback, relModuleMap); 1253 | } 1254 | 1255 | //If the require call does not trigger anything new to load, 1256 | //then resume the dependency processing. 1257 | if (!context.requireWait) { 1258 | while (!context.scriptCount && context.paused.length) { 1259 | //For built layers, there can be some defined 1260 | //modules waiting for intake into the context, 1261 | //in particular module plugins. Take them. 1262 | context.takeGlobalQueue(); 1263 | resume(); 1264 | } 1265 | } 1266 | return context.require; 1267 | }, 1268 | 1269 | /** 1270 | * Internal method to transfer globalQueue items to this context's 1271 | * defQueue. 1272 | */ 1273 | takeGlobalQueue: function () { 1274 | //Push all the globalDefQueue items into the context's defQueue 1275 | if (globalDefQueue.length) { 1276 | //Array splice in the values since the context code has a 1277 | //local var ref to defQueue, so cannot just reassign the one 1278 | //on context. 1279 | apsp.apply(context.defQueue, 1280 | [context.defQueue.length - 1, 0].concat(globalDefQueue)); 1281 | globalDefQueue = []; 1282 | } 1283 | }, 1284 | 1285 | /** 1286 | * Internal method used by environment adapters to complete a load event. 1287 | * A load event could be a script load or just a load pass from a synchronous 1288 | * load call. 1289 | * @param {String} moduleName the name of the module to potentially complete. 1290 | */ 1291 | completeLoad: function (moduleName) { 1292 | var args; 1293 | 1294 | context.takeGlobalQueue(); 1295 | 1296 | while (defQueue.length) { 1297 | args = defQueue.shift(); 1298 | 1299 | if (args[0] === null) { 1300 | args[0] = moduleName; 1301 | break; 1302 | } else if (args[0] === moduleName) { 1303 | //Found matching define call for this script! 1304 | break; 1305 | } else { 1306 | //Some other named define call, most likely the result 1307 | //of a build layer that included many define calls. 1308 | callDefMain(args); 1309 | args = null; 1310 | } 1311 | } 1312 | if (args) { 1313 | callDefMain(args); 1314 | } else { 1315 | //A script that does not call define(), so just simulate 1316 | //the call for it. Special exception for jQuery dynamic load. 1317 | callDefMain([moduleName, [], 1318 | moduleName === "jquery" && typeof jQuery !== "undefined" ? 1319 | function () { 1320 | return jQuery; 1321 | } : null]); 1322 | } 1323 | 1324 | //Doing this scriptCount decrement branching because sync envs 1325 | //need to decrement after resume, otherwise it looks like 1326 | //loading is complete after the first dependency is fetched. 1327 | //For browsers, it works fine to decrement after, but it means 1328 | //the checkLoaded setTimeout 50 ms cost is taken. To avoid 1329 | //that cost, decrement beforehand. 1330 | if (req.isAsync) { 1331 | context.scriptCount -= 1; 1332 | } 1333 | resume(); 1334 | if (!req.isAsync) { 1335 | context.scriptCount -= 1; 1336 | } 1337 | }, 1338 | 1339 | /** 1340 | * Converts a module name + .extension into an URL path. 1341 | * *Requires* the use of a module name. It does not support using 1342 | * plain URLs like nameToUrl. 1343 | */ 1344 | toUrl: function (moduleNamePlusExt, relModuleMap) { 1345 | var index = moduleNamePlusExt.lastIndexOf("."), 1346 | ext = null; 1347 | 1348 | if (index !== -1) { 1349 | ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length); 1350 | moduleNamePlusExt = moduleNamePlusExt.substring(0, index); 1351 | } 1352 | 1353 | return context.nameToUrl(moduleNamePlusExt, ext, relModuleMap); 1354 | }, 1355 | 1356 | /** 1357 | * Converts a module name to a file path. Supports cases where 1358 | * moduleName may actually be just an URL. 1359 | */ 1360 | nameToUrl: function (moduleName, ext, relModuleMap) { 1361 | var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url, 1362 | config = context.config; 1363 | 1364 | //Normalize module name if have a base relative module name to work from. 1365 | moduleName = normalize(moduleName, relModuleMap && relModuleMap.fullName); 1366 | 1367 | //If a colon is in the URL, it indicates a protocol is used and it is just 1368 | //an URL to a file, or if it starts with a slash or ends with .js, it is just a plain file. 1369 | //The slash is important for protocol-less URLs as well as full paths. 1370 | if (req.jsExtRegExp.test(moduleName)) { 1371 | //Just a plain path, not module name lookup, so just return it. 1372 | //Add extension if it is included. This is a bit wonky, only non-.js things pass 1373 | //an extension, this method probably needs to be reworked. 1374 | url = moduleName + (ext ? ext : ""); 1375 | } else { 1376 | //A module that needs to be converted to a path. 1377 | paths = config.paths; 1378 | pkgs = config.pkgs; 1379 | 1380 | syms = moduleName.split("/"); 1381 | //For each module name segment, see if there is a path 1382 | //registered for it. Start with most specific name 1383 | //and work up from it. 1384 | for (i = syms.length; i > 0; i--) { 1385 | parentModule = syms.slice(0, i).join("/"); 1386 | if (paths[parentModule]) { 1387 | syms.splice(0, i, paths[parentModule]); 1388 | break; 1389 | } else if ((pkg = pkgs[parentModule])) { 1390 | //If module name is just the package name, then looking 1391 | //for the main module. 1392 | if (moduleName === pkg.name) { 1393 | pkgPath = pkg.location + '/' + pkg.main; 1394 | } else { 1395 | pkgPath = pkg.location; 1396 | } 1397 | syms.splice(0, i, pkgPath); 1398 | break; 1399 | } 1400 | } 1401 | 1402 | //Join the path parts together, then figure out if baseUrl is needed. 1403 | url = syms.join("/") + (ext || ".js"); 1404 | url = (url.charAt(0) === '/' || url.match(/^\w+:/) ? "" : config.baseUrl) + url; 1405 | } 1406 | 1407 | return config.urlArgs ? url + 1408 | ((url.indexOf('?') === -1 ? '?' : '&') + 1409 | config.urlArgs) : url; 1410 | } 1411 | }; 1412 | 1413 | //Make these visible on the context so can be called at the very 1414 | //end of the file to bootstrap 1415 | context.jQueryCheck = jQueryCheck; 1416 | context.resume = resume; 1417 | 1418 | return context; 1419 | } 1420 | 1421 | /** 1422 | * Main entry point. 1423 | * 1424 | * If the only argument to require is a string, then the module that 1425 | * is represented by that string is fetched for the appropriate context. 1426 | * 1427 | * If the first argument is an array, then it will be treated as an array 1428 | * of dependency string names to fetch. An optional function callback can 1429 | * be specified to execute when all of those dependencies are available. 1430 | * 1431 | * Make a local req variable to help Caja compliance (it assumes things 1432 | * on a require that are not standardized), and to give a short 1433 | * name for minification/local scope use. 1434 | */ 1435 | req = requirejs = function (deps, callback) { 1436 | 1437 | //Find the right context, use default 1438 | var contextName = defContextName, 1439 | context, config; 1440 | 1441 | // Determine if have config object in the call. 1442 | if (!isArray(deps) && typeof deps !== "string") { 1443 | // deps is a config object 1444 | config = deps; 1445 | if (isArray(callback)) { 1446 | // Adjust args if there are dependencies 1447 | deps = callback; 1448 | callback = arguments[2]; 1449 | } else { 1450 | deps = []; 1451 | } 1452 | } 1453 | 1454 | if (config && config.context) { 1455 | contextName = config.context; 1456 | } 1457 | 1458 | context = contexts[contextName] || 1459 | (contexts[contextName] = newContext(contextName)); 1460 | 1461 | if (config) { 1462 | context.configure(config); 1463 | } 1464 | 1465 | return context.require(deps, callback); 1466 | }; 1467 | 1468 | /** 1469 | * Support require.config() to make it easier to cooperate with other 1470 | * AMD loaders on globally agreed names. 1471 | */ 1472 | req.config = function (config) { 1473 | return req(config); 1474 | }; 1475 | 1476 | /** 1477 | * Export require as a global, but only if it does not already exist. 1478 | */ 1479 | if (!require) { 1480 | require = req; 1481 | } 1482 | 1483 | /** 1484 | * Global require.toUrl(), to match global require, mostly useful 1485 | * for debugging/work in the global space. 1486 | */ 1487 | req.toUrl = function (moduleNamePlusExt) { 1488 | return contexts[defContextName].toUrl(moduleNamePlusExt); 1489 | }; 1490 | 1491 | req.version = version; 1492 | 1493 | //Used to filter out dependencies that are already paths. 1494 | req.jsExtRegExp = /^\/|:|\?|\.js$/; 1495 | s = req.s = { 1496 | contexts: contexts, 1497 | //Stores a list of URLs that should not get async script tag treatment. 1498 | skipAsync: {} 1499 | }; 1500 | 1501 | req.isAsync = req.isBrowser = isBrowser; 1502 | if (isBrowser) { 1503 | head = s.head = document.getElementsByTagName("head")[0]; 1504 | //If BASE tag is in play, using appendChild is a problem for IE6. 1505 | //When that browser dies, this can be removed. Details in this jQuery bug: 1506 | //http://dev.jquery.com/ticket/2709 1507 | baseElement = document.getElementsByTagName("base")[0]; 1508 | if (baseElement) { 1509 | head = s.head = baseElement.parentNode; 1510 | } 1511 | } 1512 | 1513 | /** 1514 | * Any errors that require explicitly generates will be passed to this 1515 | * function. Intercept/override it if you want custom error handling. 1516 | * @param {Error} err the error object. 1517 | */ 1518 | req.onError = function (err) { 1519 | throw err; 1520 | }; 1521 | 1522 | /** 1523 | * Does the request to load a module for the browser case. 1524 | * Make this a separate function to allow other environments 1525 | * to override it. 1526 | * 1527 | * @param {Object} context the require context to find state. 1528 | * @param {String} moduleName the name of the module. 1529 | * @param {Object} url the URL to the module. 1530 | */ 1531 | req.load = function (context, moduleName, url) { 1532 | req.resourcesReady(false); 1533 | 1534 | context.scriptCount += 1; 1535 | req.attach(url, context, moduleName); 1536 | 1537 | //If tracking a jQuery, then make sure its ready callbacks 1538 | //are put on hold to prevent its ready callbacks from 1539 | //triggering too soon. 1540 | if (context.jQuery && !context.jQueryIncremented) { 1541 | jQueryHoldReady(context.jQuery, true); 1542 | context.jQueryIncremented = true; 1543 | } 1544 | }; 1545 | 1546 | function getInteractiveScript() { 1547 | var scripts, i, script; 1548 | if (interactiveScript && interactiveScript.readyState === 'interactive') { 1549 | return interactiveScript; 1550 | } 1551 | 1552 | scripts = document.getElementsByTagName('script'); 1553 | for (i = scripts.length - 1; i > -1 && (script = scripts[i]); i--) { 1554 | if (script.readyState === 'interactive') { 1555 | return (interactiveScript = script); 1556 | } 1557 | } 1558 | 1559 | return null; 1560 | } 1561 | 1562 | /** 1563 | * The function that handles definitions of modules. Differs from 1564 | * require() in that a string for the module should be the first argument, 1565 | * and the function to execute after dependencies are loaded should 1566 | * return a value to define the module corresponding to the first argument's 1567 | * name. 1568 | */ 1569 | define = function (name, deps, callback) { 1570 | var node, context; 1571 | 1572 | //Allow for anonymous functions 1573 | if (typeof name !== 'string') { 1574 | //Adjust args appropriately 1575 | callback = deps; 1576 | deps = name; 1577 | name = null; 1578 | } 1579 | 1580 | //This module may not have dependencies 1581 | if (!isArray(deps)) { 1582 | callback = deps; 1583 | deps = []; 1584 | } 1585 | 1586 | //If no name, and callback is a function, then figure out if it a 1587 | //CommonJS thing with dependencies. 1588 | if (!deps.length && isFunction(callback)) { 1589 | //Remove comments from the callback string, 1590 | //look for require calls, and pull them into the dependencies, 1591 | //but only if there are function args. 1592 | if (callback.length) { 1593 | callback 1594 | .toString() 1595 | .replace(commentRegExp, "") 1596 | .replace(cjsRequireRegExp, function (match, dep) { 1597 | deps.push(dep); 1598 | }); 1599 | 1600 | //May be a CommonJS thing even without require calls, but still 1601 | //could use exports, and module. Avoid doing exports and module 1602 | //work though if it just needs require. 1603 | //REQUIRES the function to expect the CommonJS variables in the 1604 | //order listed below. 1605 | deps = (callback.length === 1 ? ["require"] : ["require", "exports", "module"]).concat(deps); 1606 | } 1607 | } 1608 | 1609 | //If in IE 6-8 and hit an anonymous define() call, do the interactive 1610 | //work. 1611 | if (useInteractive) { 1612 | node = currentlyAddingScript || getInteractiveScript(); 1613 | if (node) { 1614 | if (!name) { 1615 | name = node.getAttribute("data-requiremodule"); 1616 | } 1617 | context = contexts[node.getAttribute("data-requirecontext")]; 1618 | } 1619 | } 1620 | 1621 | //Always save off evaluating the def call until the script onload handler. 1622 | //This allows multiple modules to be in a file without prematurely 1623 | //tracing dependencies, and allows for anonymous module support, 1624 | //where the module name is not known until the script onload event 1625 | //occurs. If no context, use the global queue, and get it processed 1626 | //in the onscript load callback. 1627 | (context ? context.defQueue : globalDefQueue).push([name, deps, callback]); 1628 | 1629 | return undefined; 1630 | }; 1631 | 1632 | define.amd = { 1633 | multiversion: true, 1634 | plugins: true, 1635 | jQuery: true 1636 | }; 1637 | 1638 | /** 1639 | * Executes the text. Normally just uses eval, but can be modified 1640 | * to use a more environment specific call. 1641 | * @param {String} text the text to execute/evaluate. 1642 | */ 1643 | req.exec = function (text) { 1644 | return eval(text); 1645 | }; 1646 | 1647 | /** 1648 | * Executes a module callack function. Broken out as a separate function 1649 | * solely to allow the build system to sequence the files in the built 1650 | * layer in the right sequence. 1651 | * 1652 | * @private 1653 | */ 1654 | req.execCb = function (name, callback, args, exports) { 1655 | return callback.apply(exports, args); 1656 | }; 1657 | 1658 | 1659 | /** 1660 | * Adds a node to the DOM. Public function since used by the order plugin. 1661 | * This method should not normally be called by outside code. 1662 | */ 1663 | req.addScriptToDom = function (node) { 1664 | //For some cache cases in IE 6-8, the script executes before the end 1665 | //of the appendChild execution, so to tie an anonymous define 1666 | //call to the module name (which is stored on the node), hold on 1667 | //to a reference to this node, but clear after the DOM insertion. 1668 | currentlyAddingScript = node; 1669 | if (baseElement) { 1670 | head.insertBefore(node, baseElement); 1671 | } else { 1672 | head.appendChild(node); 1673 | } 1674 | currentlyAddingScript = null; 1675 | }; 1676 | 1677 | /** 1678 | * callback for script loads, used to check status of loading. 1679 | * 1680 | * @param {Event} evt the event from the browser for the script 1681 | * that was loaded. 1682 | * 1683 | * @private 1684 | */ 1685 | req.onScriptLoad = function (evt) { 1686 | //Using currentTarget instead of target for Firefox 2.0's sake. Not 1687 | //all old browsers will be supported, but this one was easy enough 1688 | //to support and still makes sense. 1689 | var node = evt.currentTarget || evt.srcElement, contextName, moduleName, 1690 | context; 1691 | 1692 | if (evt.type === "load" || (node && readyRegExp.test(node.readyState))) { 1693 | //Reset interactive script so a script node is not held onto for 1694 | //to long. 1695 | interactiveScript = null; 1696 | 1697 | //Pull out the name of the module and the context. 1698 | contextName = node.getAttribute("data-requirecontext"); 1699 | moduleName = node.getAttribute("data-requiremodule"); 1700 | context = contexts[contextName]; 1701 | 1702 | contexts[contextName].completeLoad(moduleName); 1703 | 1704 | //Clean up script binding. Favor detachEvent because of IE9 1705 | //issue, see attachEvent/addEventListener comment elsewhere 1706 | //in this file. 1707 | if (node.detachEvent && !isOpera) { 1708 | //Probably IE. If not it will throw an error, which will be 1709 | //useful to know. 1710 | node.detachEvent("onreadystatechange", req.onScriptLoad); 1711 | } else { 1712 | node.removeEventListener("load", req.onScriptLoad, false); 1713 | } 1714 | } 1715 | }; 1716 | 1717 | /** 1718 | * Attaches the script represented by the URL to the current 1719 | * environment. Right now only supports browser loading, 1720 | * but can be redefined in other environments to do the right thing. 1721 | * @param {String} url the url of the script to attach. 1722 | * @param {Object} context the context that wants the script. 1723 | * @param {moduleName} the name of the module that is associated with the script. 1724 | * @param {Function} [callback] optional callback, defaults to require.onScriptLoad 1725 | * @param {String} [type] optional type, defaults to text/javascript 1726 | * @param {Function} [fetchOnlyFunction] optional function to indicate the script node 1727 | * should be set up to fetch the script but do not attach it to the DOM 1728 | * so that it can later be attached to execute it. This is a way for the 1729 | * order plugin to support ordered loading in IE. Once the script is fetched, 1730 | * but not executed, the fetchOnlyFunction will be called. 1731 | */ 1732 | req.attach = function (url, context, moduleName, callback, type, fetchOnlyFunction) { 1733 | var node; 1734 | if (isBrowser) { 1735 | //In the browser so use a script tag 1736 | callback = callback || req.onScriptLoad; 1737 | node = context && context.config && context.config.xhtml ? 1738 | document.createElementNS("http://www.w3.org/1999/xhtml", "html:script") : 1739 | document.createElement("script"); 1740 | node.type = type || "text/javascript"; 1741 | node.charset = "utf-8"; 1742 | //Use async so Gecko does not block on executing the script if something 1743 | //like a long-polling comet tag is being run first. Gecko likes 1744 | //to evaluate scripts in DOM order, even for dynamic scripts. 1745 | //It will fetch them async, but only evaluate the contents in DOM 1746 | //order, so a long-polling script tag can delay execution of scripts 1747 | //after it. But telling Gecko we expect async gets us the behavior 1748 | //we want -- execute it whenever it is finished downloading. Only 1749 | //Helps Firefox 3.6+ 1750 | //Allow some URLs to not be fetched async. Mostly helps the order! 1751 | //plugin 1752 | node.async = !s.skipAsync[url]; 1753 | 1754 | if (context) { 1755 | node.setAttribute("data-requirecontext", context.contextName); 1756 | } 1757 | node.setAttribute("data-requiremodule", moduleName); 1758 | 1759 | //Set up load listener. Test attachEvent first because IE9 has 1760 | //a subtle issue in its addEventListener and script onload firings 1761 | //that do not match the behavior of all other browsers with 1762 | //addEventListener support, which fire the onload event for a 1763 | //script right after the script execution. See: 1764 | //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution 1765 | //UNFORTUNATELY Opera implements attachEvent but does not follow the script 1766 | //script execution mode. 1767 | if (node.attachEvent && !isOpera) { 1768 | //Probably IE. IE (at least 6-8) do not fire 1769 | //script onload right after executing the script, so 1770 | //we cannot tie the anonymous define call to a name. 1771 | //However, IE reports the script as being in "interactive" 1772 | //readyState at the time of the define call. 1773 | useInteractive = true; 1774 | 1775 | 1776 | if (fetchOnlyFunction) { 1777 | //Need to use old school onreadystate here since 1778 | //when the event fires and the node is not attached 1779 | //to the DOM, the evt.srcElement is null, so use 1780 | //a closure to remember the node. 1781 | node.onreadystatechange = function (evt) { 1782 | //Script loaded but not executed. 1783 | //Clear loaded handler, set the real one that 1784 | //waits for script execution. 1785 | if (node.readyState === 'loaded') { 1786 | node.onreadystatechange = null; 1787 | node.attachEvent("onreadystatechange", callback); 1788 | fetchOnlyFunction(node); 1789 | } 1790 | }; 1791 | } else { 1792 | node.attachEvent("onreadystatechange", callback); 1793 | } 1794 | } else { 1795 | node.addEventListener("load", callback, false); 1796 | } 1797 | node.src = url; 1798 | 1799 | //Fetch only means waiting to attach to DOM after loaded. 1800 | if (!fetchOnlyFunction) { 1801 | req.addScriptToDom(node); 1802 | } 1803 | 1804 | return node; 1805 | } else if (isWebWorker) { 1806 | //In a web worker, use importScripts. This is not a very 1807 | //efficient use of importScripts, importScripts will block until 1808 | //its script is downloaded and evaluated. However, if web workers 1809 | //are in play, the expectation that a build has been done so that 1810 | //only one script needs to be loaded anyway. This may need to be 1811 | //reevaluated if other use cases become common. 1812 | importScripts(url); 1813 | 1814 | //Account for anonymous modules 1815 | context.completeLoad(moduleName); 1816 | } 1817 | return null; 1818 | }; 1819 | 1820 | //Look for a data-main script attribute, which could also adjust the baseUrl. 1821 | if (isBrowser) { 1822 | //Figure out baseUrl. Get it from the script tag with require.js in it. 1823 | scripts = document.getElementsByTagName("script"); 1824 | 1825 | for (i = scripts.length - 1; i > -1 && (script = scripts[i]); i--) { 1826 | //Set the "head" where we can append children by 1827 | //using the script's parent. 1828 | if (!head) { 1829 | head = script.parentNode; 1830 | } 1831 | 1832 | //Look for a data-main attribute to set main script for the page 1833 | //to load. If it is there, the path to data main becomes the 1834 | //baseUrl, if it is not already set. 1835 | if ((dataMain = script.getAttribute('data-main'))) { 1836 | if (!cfg.baseUrl) { 1837 | //Pull off the directory of data-main for use as the 1838 | //baseUrl. 1839 | src = dataMain.split('/'); 1840 | mainScript = src.pop(); 1841 | subPath = src.length ? src.join('/') + '/' : './'; 1842 | 1843 | //Set final config. 1844 | cfg.baseUrl = subPath; 1845 | //Strip off any trailing .js since dataMain is now 1846 | //like a module name. 1847 | dataMain = mainScript.replace(jsSuffixRegExp, ''); 1848 | } 1849 | 1850 | //Put the data-main script in the files to load. 1851 | cfg.deps = cfg.deps ? cfg.deps.concat(dataMain) : [dataMain]; 1852 | 1853 | break; 1854 | } 1855 | } 1856 | } 1857 | 1858 | //See if there is nothing waiting across contexts, and if not, trigger 1859 | //resourcesReady. 1860 | req.checkReadyState = function () { 1861 | var contexts = s.contexts, prop; 1862 | for (prop in contexts) { 1863 | if (!(prop in empty)) { 1864 | if (contexts[prop].waitCount) { 1865 | return; 1866 | } 1867 | } 1868 | } 1869 | req.resourcesReady(true); 1870 | }; 1871 | 1872 | /** 1873 | * Internal function that is triggered whenever all scripts/resources 1874 | * have been loaded by the loader. Can be overridden by other, for 1875 | * instance the domReady plugin, which wants to know when all resources 1876 | * are loaded. 1877 | */ 1878 | req.resourcesReady = function (isReady) { 1879 | var contexts, context, prop; 1880 | 1881 | //First, set the public variable indicating that resources are loading. 1882 | req.resourcesDone = isReady; 1883 | 1884 | if (req.resourcesDone) { 1885 | //If jQuery with DOM ready delayed, release it now. 1886 | contexts = s.contexts; 1887 | for (prop in contexts) { 1888 | if (!(prop in empty)) { 1889 | context = contexts[prop]; 1890 | if (context.jQueryIncremented) { 1891 | jQueryHoldReady(context.jQuery, false); 1892 | context.jQueryIncremented = false; 1893 | } 1894 | } 1895 | } 1896 | } 1897 | }; 1898 | 1899 | //FF < 3.6 readyState fix. Needed so that domReady plugin 1900 | //works well in that environment, since require.js is normally 1901 | //loaded via an HTML script tag so it will be there before window load, 1902 | //where the domReady plugin is more likely to be loaded after window load. 1903 | req.pageLoaded = function () { 1904 | if (document.readyState !== "complete") { 1905 | document.readyState = "complete"; 1906 | } 1907 | }; 1908 | if (isBrowser) { 1909 | if (document.addEventListener) { 1910 | if (!document.readyState) { 1911 | document.readyState = "loading"; 1912 | window.addEventListener("load", req.pageLoaded, false); 1913 | } 1914 | } 1915 | } 1916 | 1917 | //Set up default context. If require was a configuration object, use that as base config. 1918 | req(cfg); 1919 | 1920 | //If modules are built into require.js, then need to make sure dependencies are 1921 | //traced. Use a setTimeout in the browser world, to allow all the modules to register 1922 | //themselves. In a non-browser env, assume that modules are not built into require.js, 1923 | //which seems odd to do on the server. 1924 | if (req.isAsync && typeof setTimeout !== "undefined") { 1925 | ctx = s.contexts[(cfg.context || defContextName)]; 1926 | //Indicate that the script that includes require() is still loading, 1927 | //so that require()'d dependencies are not traced until the end of the 1928 | //file is parsed (approximated via the setTimeout call). 1929 | ctx.requireWait = true; 1930 | setTimeout(function () { 1931 | ctx.requireWait = false; 1932 | 1933 | //Any modules included with the require.js file will be in the 1934 | //global queue, assign them to this context. 1935 | ctx.takeGlobalQueue(); 1936 | 1937 | if (!ctx.scriptCount) { 1938 | ctx.resume(); 1939 | } 1940 | req.checkReadyState(); 1941 | }, 0); 1942 | } 1943 | }()); --------------------------------------------------------------------------------