123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846 |
- /**
- * Sea.js 2.3.0 | seajs.org/LICENSE.md
- */
- (function(global, undefined) {
- // Avoid conflicting when `sea.js` is loaded multiple times
- if (global.seajs) {
- return
- }
- var seajs = global.seajs = {
- // The current version of Sea.js being used
- version: "2.3.0"
- }
- var data = seajs.data = {}
- /**
- * util-lang.js - The minimal language enhancement
- */
- function isType(type) {
- return function(obj) {
- return {}.toString.call(obj) == "[object " + type + "]"
- }
- }
- var isObject = isType("Object")
- var isString = isType("String")
- var isArray = Array.isArray || isType("Array")
- var isFunction = isType("Function")
- var _cid = 0
- function cid() {
- return _cid++
- }
- /**
- * util-events.js - The minimal events support
- */
- var events = data.events = {}
- // Bind event
- seajs.on = function(name, callback) {
- var list = events[name] || (events[name] = [])
- list.push(callback)
- return seajs
- }
- // Remove event. If `callback` is undefined, remove all callbacks for the
- // event. If `event` and `callback` are both undefined, remove all callbacks
- // for all events
- seajs.off = function(name, callback) {
- // Remove *all* events
- if (!(name || callback)) {
- events = data.events = {}
- return seajs
- }
- var list = events[name]
- if (list) {
- if (callback) {
- for (var i = list.length - 1; i >= 0; i--) {
- if (list[i] === callback) {
- list.splice(i, 1)
- }
- }
- }
- else {
- delete events[name]
- }
- }
- return seajs
- }
- // Emit event, firing all bound callbacks. Callbacks receive the same
- // arguments as `emit` does, apart from the event name
- var emit = seajs.emit = function(name, data) {
- var list = events[name], fn
- if (list) {
- // Copy callback lists to prevent modification
- list = list.slice()
- // Execute event callbacks, use index because it's the faster.
- for(var i = 0, len = list.length; i < len; i++) {
- list[i](data)
- }
- }
- return seajs
- }
- /**
- * util-path.js - The utilities for operating path such as id, uri
- */
- var DIRNAME_RE = /[^?#]*\//
- var DOT_RE = /\/\.\//g
- var DOUBLE_DOT_RE = /\/[^/]+\/\.\.\//
- var MULTI_SLASH_RE = /([^:/])\/+\//g
- // Extract the directory portion of a path
- // dirname("a/b/c.js?t=123#xx/zz") ==> "a/b/"
- // ref: http://jsperf.com/regex-vs-split/2
- function dirname(path) {
- return path.match(DIRNAME_RE)[0]
- }
- // Canonicalize a path
- // realpath("http://test.com/a//./b/../c") ==> "http://test.com/a/c"
- function realpath(path) {
- // /a/b/./c/./d ==> /a/b/c/d
- path = path.replace(DOT_RE, "/")
- /*
- @author wh1100717
- a//b/c ==> a/b/c
- a///b/////c ==> a/b/c
- DOUBLE_DOT_RE matches a/b/c//../d path correctly only if replace // with / first
- */
- path = path.replace(MULTI_SLASH_RE, "$1/")
- // a/b/c/../../d ==> a/b/../d ==> a/d
- while (path.match(DOUBLE_DOT_RE)) {
- path = path.replace(DOUBLE_DOT_RE, "/")
- }
- return path
- }
- // Normalize an id
- // normalize("path/to/a") ==> "path/to/a.js"
- // NOTICE: substring is faster than negative slice and RegExp
- function normalize(path) {
- var last = path.length - 1
- var lastC = path.charAt(last)
- // If the uri ends with `#`, just return it without '#'
- if (lastC === "#") {
- return path.substring(0, last)
- }
- return (path.substring(last - 2) === ".js" ||
- path.indexOf("?") > 0 ||
- lastC === "/") ? path : path + ".js"
- }
- var PATHS_RE = /^([^/:]+)(\/.+)$/
- var VARS_RE = /{([^{]+)}/g
- function parseAlias(id) {
- var alias = data.alias
- return alias && isString(alias[id]) ? alias[id] : id
- }
- function parsePaths(id) {
- var paths = data.paths
- var m
- if (paths && (m = id.match(PATHS_RE)) && isString(paths[m[1]])) {
- id = paths[m[1]] + m[2]
- }
- return id
- }
- function parseVars(id) {
- var vars = data.vars
- if (vars && id.indexOf("{") > -1) {
- id = id.replace(VARS_RE, function(m, key) {
- return isString(vars[key]) ? vars[key] : m
- })
- }
- return id
- }
- function parseMap(uri) {
- var map = data.map
- var ret = uri
- if (map) {
- for (var i = 0, len = map.length; i < len; i++) {
- var rule = map[i]
- ret = isFunction(rule) ?
- (rule(uri) || uri) :
- uri.replace(rule[0], rule[1])
- // Only apply the first matched rule
- if (ret !== uri) break
- }
- }
- return ret
- }
- var ABSOLUTE_RE = /^\/\/.|:\//
- var ROOT_DIR_RE = /^.*?\/\/.*?\//
- function addBase(id, refUri) {
- var ret
- var first = id.charAt(0)
- // Absolute
- if (ABSOLUTE_RE.test(id)) {
- ret = id
- }
- // Relative
- else if (first === ".") {
- ret = realpath((refUri ? dirname(refUri) : data.cwd) + id)
- }
- // Root
- else if (first === "/") {
- var m = data.cwd.match(ROOT_DIR_RE)
- ret = m ? m[0] + id.substring(1) : id
- }
- // Top-level
- else {
- ret = data.base + id
- }
- // Add default protocol when uri begins with "//"
- if (ret.indexOf("//") === 0) {
- ret = location.protocol + ret
- }
- return ret
- }
- function id2Uri(id, refUri) {
- if (!id) return ""
- id = parseAlias(id)
- id = parsePaths(id)
- id = parseVars(id)
- id = normalize(id)
- var uri = addBase(id, refUri)
- uri = parseMap(uri)
- return uri
- }
- var doc = document
- var cwd = (!location.href || location.href.indexOf('about:') === 0) ? '' : dirname(location.href)
- var scripts = doc.scripts
- // Recommend to add `seajsnode` id for the `sea.js` script element
- var loaderScript = doc.getElementById("seajsnode") ||
- scripts[scripts.length - 1]
- // When `sea.js` is inline, set loaderDir to current working directory
- var loaderDir = dirname(getScriptAbsoluteSrc(loaderScript) || cwd)
- function getScriptAbsoluteSrc(node) {
- return node.hasAttribute ? // non-IE6/7
- node.src :
- // see http://msdn.microsoft.com/en-us/library/ms536429(VS.85).aspx
- node.getAttribute("src", 4)
- }
- // For Developers
- seajs.resolve = id2Uri
- /**
- * util-request.js - The utilities for requesting script and style files
- * ref: tests/research/load-js-css/test.html
- */
- var head = doc.head || doc.getElementsByTagName("head")[0] || doc.documentElement
- var baseElement = head.getElementsByTagName("base")[0]
- var currentlyAddingScript
- var interactiveScript
- function request(url, callback, charset) {
- var node = doc.createElement("script")
- if (charset) {
- var cs = isFunction(charset) ? charset(url) : charset
- if (cs) {
- node.charset = cs
- }
- }
- addOnload(node, callback, url)
- node.async = true
- node.src = url
- // For some cache cases in IE 6-8, the script executes IMMEDIATELY after
- // the end of the insert execution, so use `currentlyAddingScript` to
- // hold current node, for deriving url in `define` call
- currentlyAddingScript = node
- // ref: #185 & http://dev.jquery.com/ticket/2709
- baseElement ?
- head.insertBefore(node, baseElement) :
- head.appendChild(node)
- currentlyAddingScript = null
- }
- function addOnload(node, callback, url) {
- var supportOnload = "onload" in node
- if (supportOnload) {
- node.onload = onload
- node.onerror = function() {
- emit("error", { uri: url, node: node })
- onload()
- }
- }
- else {
- node.onreadystatechange = function() {
- if (/loaded|complete/.test(node.readyState)) {
- onload()
- }
- }
- }
- function onload() {
- // Ensure only run once and handle memory leak in IE
- node.onload = node.onerror = node.onreadystatechange = null
- // Remove the script to reduce memory leak
- if (!data.debug) {
- head.removeChild(node)
- }
- // Dereference the node
- node = null
- callback()
- }
- }
- function getCurrentScript() {
- if (currentlyAddingScript) {
- return currentlyAddingScript
- }
- // For IE6-9 browsers, the script onload event may not fire right
- // after the script is evaluated. Kris Zyp found that it
- // could query the script nodes and the one that is in "interactive"
- // mode indicates the current script
- // ref: http://goo.gl/JHfFW
- if (interactiveScript && interactiveScript.readyState === "interactive") {
- return interactiveScript
- }
- var scripts = head.getElementsByTagName("script")
- for (var i = scripts.length - 1; i >= 0; i--) {
- var script = scripts[i]
- if (script.readyState === "interactive") {
- interactiveScript = script
- return interactiveScript
- }
- }
- }
- // For Developers
- seajs.request = request
- /**
- * util-deps.js - The parser for dependencies
- * ref: tests/research/parse-dependencies/test.html
- */
- var REQUIRE_RE = /"(?:\\"|[^"])*"|'(?:\\'|[^'])*'|\/\*[\S\s]*?\*\/|\/(?:\\\/|[^\/\r\n])+\/(?=[^\/])|\/\/.*|\.\s*require|(?:^|[^$])\brequire\s*\(\s*(["'])(.+?)\1\s*\)/g
- var SLASH_RE = /\\\\/g
- function parseDependencies(code) {
- var ret = []
- code.replace(SLASH_RE, "")
- .replace(REQUIRE_RE, function(m, m1, m2) {
- if (m2) {
- ret.push(m2)
- }
- })
- return ret
- }
- /**
- * module.js - The core of module loader
- */
- var cachedMods = seajs.cache = {}
- var anonymousMeta
- var fetchingList = {}
- var fetchedList = {}
- var callbackList = {}
- var STATUS = Module.STATUS = {
- // 1 - The `module.uri` is being fetched
- FETCHING: 1,
- // 2 - The meta data has been saved to cachedMods
- SAVED: 2,
- // 3 - The `module.dependencies` are being loaded
- LOADING: 3,
- // 4 - The module are ready to execute
- LOADED: 4,
- // 5 - The module is being executed
- EXECUTING: 5,
- // 6 - The `module.exports` is available
- EXECUTED: 6
- }
- function Module(uri, deps) {
- this.uri = uri
- this.dependencies = deps || []
- this.exports = null
- this.status = 0
- // Who depends on me
- this._waitings = {}
- // The number of unloaded dependencies
- this._remain = 0
- }
- // Resolve module.dependencies
- Module.prototype.resolve = function() {
- var mod = this
- var ids = mod.dependencies
- var uris = []
- for (var i = 0, len = ids.length; i < len; i++) {
- uris[i] = Module.resolve(ids[i], mod.uri)
- }
- return uris
- }
- // Load module.dependencies and fire onload when all done
- Module.prototype.load = function() {
- var mod = this
- // If the module is being loaded, just wait it onload call
- if (mod.status >= STATUS.LOADING) {
- return
- }
- mod.status = STATUS.LOADING
- // Emit `load` event for plugins such as combo plugin
- var uris = mod.resolve()
- emit("load", uris)
- var len = mod._remain = uris.length
- var m
- // Initialize modules and register waitings
- for (var i = 0; i < len; i++) {
- m = Module.get(uris[i])
- if (m.status < STATUS.LOADED) {
- // Maybe duplicate: When module has dupliate dependency, it should be it's count, not 1
- m._waitings[mod.uri] = (m._waitings[mod.uri] || 0) + 1
- }
- else {
- mod._remain--
- }
- }
- if (mod._remain === 0) {
- mod.onload()
- return
- }
- // Begin parallel loading
- var requestCache = {}
- for (i = 0; i < len; i++) {
- m = cachedMods[uris[i]]
- if (m.status < STATUS.FETCHING) {
- m.fetch(requestCache)
- }
- else if (m.status === STATUS.SAVED) {
- m.load()
- }
- }
- // Send all requests at last to avoid cache bug in IE6-9. Issues#808
- for (var requestUri in requestCache) {
- if (requestCache.hasOwnProperty(requestUri)) {
- requestCache[requestUri]()
- }
- }
- }
- // Call this method when module is loaded
- Module.prototype.onload = function() {
- var mod = this
- mod.status = STATUS.LOADED
- if (mod.callback) {
- mod.callback()
- }
- // Notify waiting modules to fire onload
- var waitings = mod._waitings
- var uri, m
- for (uri in waitings) {
- if (waitings.hasOwnProperty(uri)) {
- m = cachedMods[uri]
- m._remain -= waitings[uri]
- if (m._remain === 0) {
- m.onload()
- }
- }
- }
- // Reduce memory taken
- delete mod._waitings
- delete mod._remain
- }
- // Fetch a module
- Module.prototype.fetch = function(requestCache) {
- var mod = this
- var uri = mod.uri
- mod.status = STATUS.FETCHING
- // Emit `fetch` event for plugins such as combo plugin
- var emitData = { uri: uri }
- emit("fetch", emitData)
- var requestUri = emitData.requestUri || uri
- // Empty uri or a non-CMD module
- if (!requestUri || fetchedList[requestUri]) {
- mod.load()
- return
- }
- if (fetchingList[requestUri]) {
- callbackList[requestUri].push(mod)
- return
- }
- fetchingList[requestUri] = true
- callbackList[requestUri] = [mod]
- // Emit `request` event for plugins such as text plugin
- emit("request", emitData = {
- uri: uri,
- requestUri: requestUri,
- onRequest: onRequest,
- charset: data.charset
- })
- if (!emitData.requested) {
- requestCache ?
- requestCache[emitData.requestUri] = sendRequest :
- sendRequest()
- }
- function sendRequest() {
- seajs.request(emitData.requestUri, emitData.onRequest, emitData.charset)
- }
- function onRequest() {
- delete fetchingList[requestUri]
- fetchedList[requestUri] = true
- // Save meta data of anonymous module
- if (anonymousMeta) {
- Module.save(uri, anonymousMeta)
- anonymousMeta = null
- }
- // Call callbacks
- var m, mods = callbackList[requestUri]
- delete callbackList[requestUri]
- while ((m = mods.shift())) m.load()
- }
- }
- // Execute a module
- Module.prototype.exec = function () {
- var mod = this
- // When module is executed, DO NOT execute it again. When module
- // is being executed, just return `module.exports` too, for avoiding
- // circularly calling
- if (mod.status >= STATUS.EXECUTING) {
- return mod.exports
- }
- mod.status = STATUS.EXECUTING
- // Create require
- var uri = mod.uri
- function require(id) {
- return Module.get(require.resolve(id)).exec()
- }
- require.resolve = function(id) {
- return Module.resolve(id, uri)
- }
- require.async = function(ids, callback) {
- Module.use(ids, callback, uri + "_async_" + cid())
- return require
- }
- // Exec factory
- var factory = mod.factory
- var exports = isFunction(factory) ?
- factory(require, mod.exports = {}, mod) :
- factory
- if (exports === undefined) {
- exports = mod.exports
- }
- // Reduce memory leak
- delete mod.factory
- mod.exports = exports
- mod.status = STATUS.EXECUTED
- // Emit `exec` event
- emit("exec", mod)
- return exports
- }
- // Resolve id to uri
- Module.resolve = function(id, refUri) {
- // Emit `resolve` event for plugins such as text plugin
- var emitData = { id: id, refUri: refUri }
- emit("resolve", emitData)
- return emitData.uri || seajs.resolve(emitData.id, refUri)
- }
- // Define a module
- Module.define = function (id, deps, factory) {
- var argsLen = arguments.length
- // define(factory)
- if (argsLen === 1) {
- factory = id
- id = undefined
- }
- else if (argsLen === 2) {
- factory = deps
- // define(deps, factory)
- if (isArray(id)) {
- deps = id
- id = undefined
- }
- // define(id, factory)
- else {
- deps = undefined
- }
- }
- // Parse dependencies according to the module factory code
- if (!isArray(deps) && isFunction(factory)) {
- deps = parseDependencies(factory.toString())
- }
- var meta = {
- id: id,
- uri: Module.resolve(id),
- deps: deps,
- factory: factory
- }
- // Try to derive uri in IE6-9 for anonymous modules
- if (!meta.uri && doc.attachEvent) {
- var script = getCurrentScript()
- if (script) {
- meta.uri = script.src
- }
- // NOTE: If the id-deriving methods above is failed, then falls back
- // to use onload event to get the uri
- }
- // Emit `define` event, used in nocache plugin, seajs node version etc
- emit("define", meta)
- meta.uri ? Module.save(meta.uri, meta) :
- // Save information for "saving" work in the script onload event
- anonymousMeta = meta
- }
- // Save meta data to cachedMods
- Module.save = function(uri, meta) {
- var mod = Module.get(uri)
- // Do NOT override already saved modules
- if (mod.status < STATUS.SAVED) {
- mod.id = meta.id || uri
- mod.dependencies = meta.deps || []
- mod.factory = meta.factory
- mod.status = STATUS.SAVED
- emit("save", mod)
- }
- }
- // Get an existed module or create a new one
- Module.get = function(uri, deps) {
- return cachedMods[uri] || (cachedMods[uri] = new Module(uri, deps))
- }
- // Use function is equal to load a anonymous module
- Module.use = function (ids, callback, uri) {
- var mod = Module.get(uri, isArray(ids) ? ids : [ids])
- mod.callback = function() {
- var exports = []
- var uris = mod.resolve()
- for (var i = 0, len = uris.length; i < len; i++) {
- exports[i] = cachedMods[uris[i]].exec()
- }
- if (callback) {
- callback.apply(global, exports)
- }
- delete mod.callback
- }
- mod.load()
- }
- // Public API
- seajs.use = function(ids, callback) {
- Module.use(ids, callback, data.cwd + "_use_" + cid())
- return seajs
- }
- Module.define.cmd = {}
- global.define = Module.define
- // For Developers
- seajs.Module = Module
- data.fetchedList = fetchedList
- data.cid = cid
- seajs.require = function(id) {
- var mod = Module.get(Module.resolve(id))
- if (mod.status < STATUS.EXECUTING) {
- mod.onload()
- mod.exec()
- }
- return mod.exports
- }
- /**
- * config.js - The configuration for the loader
- */
- // The root path to use for id2uri parsing
- data.base = loaderDir
- // The loader directory
- data.dir = loaderDir
- // The current working directory
- data.cwd = cwd
- // The charset for requesting files
- data.charset = "utf-8"
- // data.alias - An object containing shorthands of module id
- // data.paths - An object containing path shorthands in module id
- // data.vars - The {xxx} variables in module id
- // data.map - An array containing rules to map module uri
- // data.debug - Debug mode. The default value is false
- seajs.config = function(configData) {
- for (var key in configData) {
- var curr = configData[key]
- var prev = data[key]
- // Merge object config such as alias, vars
- if (prev && isObject(prev)) {
- for (var k in curr) {
- prev[k] = curr[k]
- }
- }
- else {
- // Concat array config such as map
- if (isArray(prev)) {
- curr = prev.concat(curr)
- }
- // Make sure that `data.base` is an absolute path
- else if (key === "base") {
- // Make sure end with "/"
- if (curr.slice(-1) !== "/") {
- curr += "/"
- }
- curr = addBase(curr)
- }
- // Set config
- data[key] = curr
- }
- }
- emit("config", configData)
- return seajs
- }
- })(this);
|