diff --git a/.bithoundrc b/.bithoundrc new file mode 100644 index 0000000..b30de9a --- /dev/null +++ b/.bithoundrc @@ -0,0 +1,10 @@ +{ + "ignore": [ + "assets/js/lib/**", + "assets/test/jasmine/**" + ], + "test": [ + "test/**", + "assets/test/**" + ] +} \ No newline at end of file diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..2536d66 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# http://editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 4 +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.jshintrc b/.jshintrc index 05c8cb5..6bc7f03 100644 --- a/.jshintrc +++ b/.jshintrc @@ -19,5 +19,5 @@ "browser": true, "scripturl": true, "jquery": true, - "predef": [ "define", "Prism", "SourceGetSections"] + "predef": [ "sourcejs", "Prism", "SourceGetSections"] } diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..9349107 --- /dev/null +++ b/.npmignore @@ -0,0 +1,24 @@ +*.idea +*.iml + +.travis.yml +.jshintrc +appveyor.yml +source.sh + +# Generated data for API +/core/api/data/ +/log/ + +# Generated JSdoc +/jsdoc/ + +# Build folder for assets +/build/ + +# Web server root, and your specs home +# You can store other repository in this path +/user/ + +# Folder with tests +/test/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 494dab7..5a32382 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,14 @@ language: node_js node_js: - - "0.10" - - "0.11" - - "0.12" + - "6" + - "7" sudo: false +install: + - npm cache clean + - npm install notifications: email: on_success: never on_failure: always before_script: "git clone https://github.com/sourcejs/init.git user" -script: npm run ci-test \ No newline at end of file +script: npm run ci-test diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 95341d2..c736f58 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ Please read [this doc](MAINTAINING.md) for information on how we're running deve * [@SourceJS](https://twitter.com/SourceJS) * [Web site](http://sourcejs.com) * [General documentation](http://sourcejs.com/docs/) -* [Quick Start guide](http://sourcejs.com/docs/base/) +* [Quick Start guide](http://sourcejs.com/docs/getting-started/) * [More information on contributing](MAINTAINING.md) ## Team members @@ -26,3 +26,4 @@ All inquiries should be forwarded to [Robert Haritonov](mailto:r@rhr.me). Core contributors and maintainers: * [Robert Haritonov](https://github.com/operatino) * [Ilya Mikhailov](https://github.com/cheshirsky) +* [Norbert de Langen](https://github.com/ndelangen) diff --git a/Gruntfile.js b/Gruntfile.js index 727399a..f6ba48e 100755 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -12,7 +12,7 @@ var getLoaderPackageName = function() { var packageName; var parentFolderName = path.basename(path.resolve('..')); var isSubPackage = parentFolderName === 'node_modules'; - var isLocalDepsAvailable = fs.existsSync('node_modules/grunt-autoprefixer') && fs.existsSync('node_modules/grunt-contrib-cssmin'); + var isLocalDepsAvailable = fs.existsSync('node_modules/grunt-autoprefixer') && fs.existsSync('node_modules/grunt-contrib-copy'); if (isSubPackage && !isLocalDepsAvailable) { packageName = 'load-grunt-parent-tasks'; @@ -27,7 +27,7 @@ module.exports = function(grunt) { var appPort = grunt.option('app-port') || 8080; // load all grunt tasks matching the `grunt-*` pattern - require(getLoaderPackageName())(grunt); + require(getLoaderPackageName())(grunt, {pattern: ['grunt-*', '@*/grunt-*']}); // measuring processing time require('time-grunt')(grunt); @@ -40,7 +40,7 @@ module.exports = function(grunt) { banner:'/*!\n' + '* SourceJS - Living Style Guides Engine and Integrated Maintenance Environment for Front-end Components.\n' + '* @copyright 2013-2015 Sourcejs.com\n' + - '* @license MIT license: http://github.com/sourcejs/source/wiki/MIT-License\n' + + '* @license MIT license: http://github.com/sourcejs/sourcejs/wiki/MIT-License\n' + '* */\n', // clean files after build @@ -230,8 +230,6 @@ module.exports = function(grunt) { }); grunt.registerTask('resolve-js-bundles', 'Resolving JS imports in _**.bundle.js', function(){ - var gruntOpts = grunt.config.get('options'); - // Setting custom delimiters for grunt.template grunt.template.addDelimiters('customBundleDelimiter', '"{%', '%}"'); @@ -250,11 +248,7 @@ module.exports = function(grunt) { grunt.file.write( outputFullPath, grunt.template.process(grunt.file.read(pathToFile), { - delimiters: 'customBundleDelimiter', - data: { - // npmPluginsEnabled object is filled from loadOptions.js - npmPluginsEnabled: JSON.stringify(gruntOpts.assets.npmPluginsEnabled, null, 4) - } + delimiters: 'customBundleDelimiter' }) ); grunt.log.ok('Writing to '+outputFullPath); @@ -328,7 +322,7 @@ module.exports = function(grunt) { // Test task. Execute with running app grunt.registerTask('test', 'Run ALL tests or specified by second param', function () { - // if custom mask set - `grunt test --spec=test/unit/middleware/**/*.js` + // if custom mask set - `grunt test --spec=test/unit/**/*.js` var spec = grunt.option('spec'); if (spec) { grunt.config.set('mochaTest.test.src', [spec]); @@ -340,7 +334,7 @@ module.exports = function(grunt) { // Test task. Execute with running app grunt.registerTask('test-func', 'Run ALL functional tests or specified by second param', function () { - // if custom mask set - `grunt test --spec=test/unit/middleware/**/*.js` + // if custom mask set - `grunt test --spec=test/functional/**/*.js` var spec = grunt.option('spec'); if (spec) { grunt.config.set('casperjs.files', [spec]); diff --git a/README.md b/README.md index d773212..533d88f 100755 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ **The most advanced tool for documenting, testing and managing Front-end Components achieving productive team work.** -🚀 [**Quick Start**](http://sourcejs.com/docs/base) +🚀 [**Quick Start**](http://sourcejs.com/docs/getting-started/) SourceJS powered workflow allows developers to **code new components directly in the documentation.** Combining web components development with documentation and team communication processes, makes SourceJS a powerful tool for Front-end developers and designers. @@ -19,7 +19,7 @@ Our main goal is to provide flexible, modular environment for managing reusable ___ -[**Source engine project page**](http://sourcejs.com)     [**Documentation**](http://sourcejs.com/docs)     [**Examples**](http://sourcejs.com/docs/base/#examples)    [**How-to's**](https://github.com/sourcejs/blog-howto) +[**Source engine project page**](http://sourcejs.com)     [**Documentation**](http://sourcejs.com/docs)     [**Examples**](http://sourcejs.com/docs/getting-started/#examples)    [**How-to's**](https://github.com/sourcejs/blog-howto) ___ @@ -52,22 +52,22 @@ If you notice some bugs, or need to help finding a better solution in your proce [Materials for presentations](https://github.com/sourcejs/pres). ## Updates -* 20.09.15 [0.5.6](https://github.com/sourcejs/Source/releases/tag/0.5.6) and [0.5.6-no-jsdom](https://github.com/sourcejs/Source/releases/tag/0.5.6-no-jsdom) with EJS helpers, NPM 3 support and navigation improvements -* 16.08.15 [0.5.5](https://github.com/sourcejs/Source/releases/tag/0.5.5) and [0.5.5-no-jsdom](https://github.com/sourcejs/Source/releases/tag/0.5.5-no-jsdom) patch release with `` tag fix and set of functional tests -* 15.08.15 [0.5.4](https://github.com/sourcejs/Source/releases/tag/0.5.4) and [0.5.4-no-jsdom](https://github.com/sourcejs/Source/releases/tag/0.5.4-no-jsdom) with middleware loader, relative paths in navigation support and other improvements -* 28.05.15 [0.5.3](https://github.com/sourcejs/Source/releases/tag/0.5.3) context options support, source-as-npm package, CI integration, watcher stability improvements and other great features -* 28.05.15 [0.5.3-no-jsdom](https://github.com/sourcejs/Source/releases/tag/0.5.3-no-jsdom) special release without JSDom for Windows users -* 15.04.15 [0.5.2](https://github.com/sourcejs/Source/releases/tag/0.5.2) patch release with improved markdown support and `index.src.html` -* 28.03.15 [0.5.1](https://github.com/sourcejs/Source/releases/tag/0.5.1) patch release with EJS pre-rendering and various bugfixes +* 20.09.15 [0.5.6](https://github.com/sourcejs/sourcejs/releases/tag/0.5.6) and [0.5.6-no-jsdom](https://github.com/sourcejs/sourcejs/releases/tag/0.5.6-no-jsdom) with EJS helpers, NPM 3 support and navigation improvements +* 16.08.15 [0.5.5](https://github.com/sourcejs/sourcejs/releases/tag/0.5.5) and [0.5.5-no-jsdom](https://github.com/sourcejs/sourcejs/releases/tag/0.5.5-no-jsdom) patch release with `` tag fix and set of functional tests +* 15.08.15 [0.5.4](https://github.com/sourcejs/sourcejs/releases/tag/0.5.4) and [0.5.4-no-jsdom](https://github.com/sourcejs/sourcejs/releases/tag/0.5.4-no-jsdom) with middleware loader, relative paths in navigation support and other improvements +* 28.05.15 [0.5.3](https://github.com/sourcejs/sourcejs/releases/tag/0.5.3) context options support, source-as-npm package, CI integration, watcher stability improvements and other great features +* 28.05.15 [0.5.3-no-jsdom](https://github.com/sourcejs/sourcejs/releases/tag/0.5.3-no-jsdom) special release without JSDom for Windows users +* 15.04.15 [0.5.2](https://github.com/sourcejs/sourcejs/releases/tag/0.5.2) patch release with improved markdown support and `index.src.html` +* 28.03.15 [0.5.1](https://github.com/sourcejs/sourcejs/releases/tag/0.5.1) patch release with EJS pre-rendering and various bugfixes * 28.03.15. SourceJS [Bootstrap example bundle](https://github.com/sourcejs/example-bootstrap-bundle) and [How-to articles blog](https://github.com/sourcejs/blog-howto) * 15.03.15. New example [Specs showcase](http://sourcejs.com/specs/) ([source code](https://github.com/sourcejs/example-specs-showcase)) * 15.03.15. CSS Documentation support with [SourceJS DSS plugin](https://github.com/sourcejs/sourcejs-contrib-dss) -* 12.03.15. **[0.5.0](https://github.com/sourcejs/Source/releases/tag/0.5.0) release** with full Markdown support, GitHub auth, `info.json` watchers and other improvements -* 24.02.15. [0.4.1](https://github.com/sourcejs/Source/releases/tag/0.4.1) patch release +* 12.03.15. **[0.5.0](https://github.com/sourcejs/sourcejs/releases/tag/0.5.0) release** with full Markdown support, GitHub auth, `info.json` watchers and other improvements +* 24.02.15. [0.4.1](https://github.com/sourcejs/sourcejs/releases/tag/0.4.1) patch release * 05.02.15. Mentioned at in-depth [Style Guides Tools overview talk](http://youtu.be/Fr23VpM6wl4ds) * 18.01.15. Published an [intro video about SourceJS](http://youtu.be/y4KHmX8vCc0) -* 07.01.15. **[0.4.0](https://github.com/sourcejs/Source/releases/tag/0.4.0) stable release.** From now, we move to fast, semantic release cycle. No globally breaking changes till 1.0.0 -* 08.10.14. 0.4.0-rc release, migration [instructions](https://github.com/sourcejs/Source/tree/master/docs/migration) +* 07.01.15. **[0.4.0](https://github.com/sourcejs/sourcejs/releases/tag/0.4.0) stable release.** From now, we move to fast, semantic release cycle. No globally breaking changes till 1.0.0 +* 08.10.14. 0.4.0-rc release, migration [instructions](https://github.com/sourcejs/sourcejs/tree/master/docs/migration) * 01.08.14. [Video review](http://youtu.be/ukFeZnJjrLs?list=PL20zJcC2wnX7RY1CDrKLhSvYxEe6jtMbB) of SourceJS engine and workflow example (RU with EN subtitles) * 31.07.14. 0.4.0-beta release * 01.05.14. Engine presentation from [Front-end Ops Conf](http://www.feopsconf.com/), San Francisco - [Taking Development Tools To The Next Level](http://rhr.me/pres/ime/) with [video](https://www.youtube.com/watch?v=cMIad0zl00I) @@ -102,4 +102,4 @@ ___ Copyright © 2013-2015 [SourceJS](http://sourcejs.com) -Licensed under [MIT License](http://en.wikipedia.org/wiki/MIT_License), read more at [license page](http://github.com/sourcejs/source/wiki/MIT-License). +Licensed under [MIT License](http://en.wikipedia.org/wiki/MIT_License), read more at [license page](http://github.com/sourcejs/sourcejs/wiki/MIT-License). diff --git a/app.js b/app.js index f8a626f..79b37be 100644 --- a/app.js +++ b/app.js @@ -1,7 +1,7 @@ /*! * SourceJS - Living Style Guides Engine and Integrated Maintenance Environment for Front-end Components * @copyright 2013-2015 Sourcejs.com -* @license MIT license: http://github.com/sourcejs/source/wiki/MIT-License +* @license MIT license: http://github.com/sourcejs/sourcejs/wiki/MIT-License * */ 'use strict'; @@ -17,7 +17,7 @@ var favicon = require('serve-favicon'); /* Globals */ // Define absolute path to app, normalizing windows disk name global.pathToApp = __dirname.replace(/^\w:\\/, function (match) { - return match.toLowerCase(); + return match.toUpperCase(); }); var app = global.app = express(); @@ -27,10 +27,10 @@ global.opts = loadOptions(); // Arguments parse */ commander + .allowUnknownOption() .option('-l, --log [string]', 'Log level (default: ' + global.opts.core.common.defaultLogLevel + ').', global.opts.core.common.defaultLogLevel) - .option('-p, --port [number]', 'Server port (default: ' + global.opts.core.server.port + ').') + .option('-p, --port [number]', 'Server port (default: ' + global.opts.core.server.port + '). Note: `process.env.PORT` will override this option if present.') .option('--hostname [string]', 'Server hostname (default: ' + global.opts.core.server.hostname + ').') - .option('--html', 'Turn on HTML parser on app start (requires installed and enabled parser).') .option('--test', 'Run app with tests.') .option('--no-watch', 'Run with disabled watcher.') .option('--post-grunt [string]', 'Define Grunt command to run after app start', 'ci-post-run') @@ -40,8 +40,14 @@ global.commander = commander; var trackStats = require(path.join(global.pathToApp, 'core/trackStats')); -app.set('views', path.join(__dirname, 'core/views')); -app.set('user', path.join(__dirname, global.opts.core.common.pathToUser)); +var getUserPath = require('./core/lib/getUserPath'); +var userPath = global.userPath = getUserPath(); +global.isNodeModule = getUserPath.isNodeModule; + +// Legacy support +app.set('user', userPath); + +console.log('Running user contents from', '`' + userPath + '`.'); // We support `development` (default), `production` and `presentation` (for demos) var MODE = global.MODE = process.env.NODE_ENV || 'development'; @@ -53,15 +59,6 @@ var logger = require('./core/logger'); var log = logger.log; global.log = log; -if (commander.html) { - trackStats.event({ - group: 'features', - event: 'enabled html parser' - }); - - global.opts.plugins.htmlParser.enabled = true; - global.opts.plugins.htmlParser.onStart = true; -} if (commander.port) global.opts.core.server.port = parseInt(commander.port); if (commander.hostname) global.opts.core.server.hostname = commander.hostname; if (!commander.watch) { @@ -71,6 +68,11 @@ if (!commander.watch) { }); global.opts.core.watch.enabled = false; } + +if (process.env.PORT) { + global.opts.core.server.port = process.env.PORT; + console.log('Using defined app PORT from environment variable: ' + process.env.PORT); +} /* /Globals */ @@ -120,7 +122,7 @@ app.use(function (req, res, next) { }); // Favicon -var faviconPath = path.join(app.get('user'), 'favicon.ico'); +var faviconPath = path.join(userPath, 'favicon.ico'); if (fs.existsSync(faviconPath)){ app.use(favicon(faviconPath)); } @@ -167,6 +169,9 @@ app.use('/api/updateFileTree', function(req, res){ }); +// Intercept static serve to localize requirejs +app.use(require(path.join(global.pathToApp, 'core/privateAmdTransformer.js'))); + // Routes require('./core/routes'); @@ -177,10 +182,16 @@ require('./core/api/optionsApi'); // User extenstions require("./core/loadPlugins.js"); -try { - // User additional functionality - require(app.get('user') + "/core/app.js"); -} catch(e){} +// User extended app.js +var pathToUserAppExtension = path.join(userPath, 'core/app.js'); + +if (fs.existsSync(pathToUserAppExtension)) { + try { + require(pathToUserAppExtension); + } catch(e){ + log.warn('Error loading user app.js from ' + pathToUserAppExtension, e); + } +} // Watchers @@ -201,22 +212,22 @@ if (global.opts.core.watch.enabled && global.MODE === 'development') { var headerFooter = require('./core/headerFooter'); // Static content -app.use(express.static(app.get('user'))); +app.use(express.static(userPath)); // Page 404 app.use(function(req, res){ - if (req.accepts('html')) { + if (req.accepts('html')) { if (req.url === '/') { res.redirect('/docs'); return; } var headerFooterHTML = headerFooter.getHeaderAndFooter(); - res.status(404).render(path.join(__dirname, '/core/views/404.ejs'), { + res.status(404).render(path.join(__dirname, '/core/views/404.ejs'), { header: headerFooterHTML.header, footer: headerFooterHTML.footer - }); - } + }); + } }); /* /Serving content */ @@ -228,7 +239,7 @@ var logErrors = function(err, req, res, next) { var url = req.url || ''; log.debug(req.method, req.headers); - log.error(('Requested url: ' + url).red, ('Error: ' + err.stack).red); + log.error(('Error on requesting url: ' + url).red +'.', ('Error: ' + err.stack).red); if (req.xhr) { res.status(500).json({msg: 'Server error'}); @@ -243,10 +254,7 @@ var logErrors = function(err, req, res, next) { app.use(logErrors); /* /Error handling */ - - -/* Server start */ -if (!module.parent) { +var startServer = function () { var serverOpts = global.opts.core.server; var port = serverOpts.port; @@ -256,7 +264,7 @@ if (!module.parent) { if (commander.test) { var spawn = require('cross-spawn'); - spawn('./node_modules/grunt-cli/bin/grunt', [commander.postGrunt, '--port='+port], {stdio: 'inherit'}) + spawn('./node_modules/grunt-cli/bin/grunt', [commander.postGrunt, '--port=' + port], { stdio: 'inherit' }) .on('close', function (code) { if (code === 0) { log.info('Test successful'); @@ -279,5 +287,14 @@ if (!module.parent) { }, true); } } +}; + +/* Server start */ +if (!module.parent) { + startServer(); } /* Server start */ + +module.exports = { + startServer: startServer +}; diff --git a/appveyor.yml b/appveyor.yml index ae75ddf..8ac32b6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,11 +3,12 @@ environment: matrix: - - nodejs_version: 0.10 - - nodejs_version: 0.12 + - nodejs_version: 6 + - nodejs_version: 7 install: - ps: Install-Product node $env:nodejs_version + - npm cache clean - npm install build: off @@ -23,6 +24,4 @@ matrix: fast_finish: true cache: - - C:\Users\appveyor\AppData\Roaming\npm\node_modules -> package.json # global npm modules - - C:\Users\appveyor\AppData\Roaming\npm-cache -> package.json # npm cache - - node_modules -> package.json # local npm modules \ No newline at end of file + - node_modules -> package.json # Local npm modules diff --git a/assets/css/base/buttons.less b/assets/css/base/buttons.less index 4605ff9..c3604ed 100644 --- a/assets/css/base/buttons.less +++ b/assets/css/base/buttons.less @@ -3,19 +3,19 @@ /* TODO: cosmetic changes needed */ .source_btn { - position:relative; + position:relative; - display: inline-block; - padding: 4px 17px; + display: inline-block; + padding: 4px 17px; - background-color:#65A7D6; - border: #5B9ECB solid 1px; - border-radius:3px; + background-color:#65A7D6; + border: #5B9ECB solid 1px; + border-radius:3px; - color:#fff; - font-weight:normal; - text-decoration:none; - font-size: 12px; + color:#fff; + font-weight:normal; + text-decoration:none; + font-size: 12px; &:hover { background-color: #5B9ECB; @@ -23,7 +23,7 @@ &:active { top:1px; } - } + } /* /Buttons ----------------------------------------------------------------------------------- */ \ No newline at end of file +---------------------------------------------------------------------------------- */ diff --git a/assets/css/base/grids.less b/assets/css/base/grids.less index bf80d83..62921b9 100644 --- a/assets/css/base/grids.less +++ b/assets/css/base/grids.less @@ -2,56 +2,56 @@ ---------------------------------------------------------------------------------- */ .source_col-main { - margin: 0 auto; - padding: 0 @layout_col-main--padding; - max-width: @layout_col-main--max-width; - box-sizing: content-box; - } + margin: 0 auto; + padding: 0; + max-width: @layout_col-main--max-width; + box-sizing: content-box; +} .source_col { - display: inline-block; + display: inline-block; - vertical-align: top; - width: 33%; - padding-right: 25px; + vertical-align: top; + width: 33%; + padding-right: 25px; - box-sizing: border-box; + box-sizing: border-box; &.__15 { - width: 20%; - } + width: 20%; + } &.__14 { - width: 24.5%; - } + width: 24.5%; + } &__23 { - width: 66.2%; - } + width: 66.2%; + } &.__right { - float: right; - padding-right: 0; - } + float: right; + padding-right: 0; + } - } +} /* Justified layout -------------------------------------------------- */ -/* justified inline data */ +/* justified inline data */ .jcol-l, .jcol-r { - display: inline-block; - width: 50%; - vertical-align: middle; + display: inline-block; + width: 50%; + vertical-align: middle; - text-align: left; - } + text-align: left; +} .jcol-r { - text-align: right; - } + text-align: right; +} /* /Justified layout */ diff --git a/assets/css/base/navigation.less b/assets/css/base/navigation.less index 918e75f..cf134f4 100644 --- a/assets/css/base/navigation.less +++ b/assets/css/base/navigation.less @@ -2,56 +2,56 @@ ---------------------------------------------------------------------------------- */ .source_nav { - white-space: nowrap; - display: none; + white-space: nowrap; + display: none; - font-family: @font-family-main; - color: @color-main; + font-family: @font-family-main; + color: @color-main; - &.__loaded { - display: block; - } + &.__loaded { + display: block; + } &:empty { - display: none; - } - } - - @media all and (min-width: 990px) { - .source_nav:before { - content: ''; - display: inline-block; - vertical-align: middle; - height: 100%; - } - } + display: none; + } + } + + @media all and (min-width: 990px) { + .source_nav:before { + content: ''; + display: inline-block; + vertical-align: middle; + height: 100%; + } + } .source_nav_c { - display: inline-block; - vertical-align: top; - border-radius: 10px; - width: 100%; + display: inline-block; + vertical-align: top; + border-radius: 10px; + width: 100%; - box-sizing: border-box; + box-sizing: border-box; - padding: 20px 21px 10px; - background-color: @light-gray; - } + padding: 20px 21px 10px; + background-color: @light-gray; + } .source_nav_ul { - list-style: none; - margin: 0; - padding: 0; + list-style: none; + margin: 0; + padding: 0; li:first-child { - margin-top: 0; - } + margin-top: 0; + } a { - display: block; + display: block; line-height: inherit; - } - } + } + } .source_main_nav_ul2 { margin: 0; diff --git a/assets/css/base/ntf.less b/assets/css/base/ntf.less index fd650de..e2929a4 100644 --- a/assets/css/base/ntf.less +++ b/assets/css/base/ntf.less @@ -1,29 +1,29 @@ .source_ntf { - position: fixed; z-index: 50; - top: 50px; /* toolbar height */ + position: fixed; z-index: 50; + top: 50px; /* toolbar height */ left: 0; right: 0; - font-size: @fz-size-m; - font-family: @font-family-main; - color: #333; - text-align: center; + font-size: @fz-size-m; + font-family: @font-family-main; + color: #333; + text-align: center; - height: 50px; - line-height: 48px; - white-space: nowrap; - overflow: hidden; + height: 50px; + line-height: 48px; + white-space: nowrap; + overflow: hidden; - background: #FFF6DD; - border-bottom: 1px solid #ccc; - box-shadow: 0 0 6px -2px rgba(0, 0, 0, .3); + background: #FFF6DD; + border-bottom: 1px solid #ccc; + box-shadow: 0 0 6px -2px rgba(0, 0, 0, .3); - opacity: 0; - visibility: hidden; + opacity: 0; + visibility: hidden; - transition: opacity .2s, visibility .2s; - } + transition: opacity .2s, visibility .2s; + } - .source_ntf.__active { - opacity: 1; - visibility: visible; - } \ No newline at end of file + .source_ntf.__active { + opacity: 1; + visibility: visible; + } diff --git a/assets/css/base/togglers.less b/assets/css/base/togglers.less index b40e69f..a25cd53 100644 --- a/assets/css/base/togglers.less +++ b/assets/css/base/togglers.less @@ -2,53 +2,53 @@ ---------------------------------------------------------------------------------- */ .source_slider_frame { - position: absolute; - right: 0; - top: 0; - display: block; - margin: 0 auto; - width: 50px; - height: 20px; - - background-color: rgb(246, 249, 251); - border-radius: 4px; - box-shadow: inset 0px 0px 4px 0 rgba(0, 0, 0, 0.25); + position: absolute; + right: 0; + top: 0; + display: block; + margin: 0 auto; + width: 50px; + height: 20px; + + background-color: rgb(246, 249, 251); + border-radius: 4px; + box-shadow: inset 0px 0px 4px 0 rgba(0, 0, 0, 0.25); -webkit-touch-callout: none; - user-select: none; - } + user-select: none; + } .source_slider_button { - display: block; - width: 30px; - height: 20px; - line-height: 20px; - - background: #EDF2F7; - border-radius: 4px; - transition: all 0.25s ease-in-out; - color: #000; - font-family: sans-serif; - font-size: 9px; - text-align: center; - cursor: pointer; - box-shadow: inset 0px 0px 4px 0 rgba(0, 0, 0, 0.25); - } + display: block; + width: 30px; + height: 20px; + line-height: 20px; + + background: #EDF2F7; + border-radius: 4px; + transition: all 0.25s ease-in-out; + color: #000; + font-family: sans-serif; + font-size: 9px; + text-align: center; + cursor: pointer; + box-shadow: inset 0px 0px 4px 0 rgba(0, 0, 0, 0.25); + } .source_slider_frame__on .source_slider_button { - margin-left: 20px; - background: #EDF2F7; - } + margin-left: 20px; + background: #EDF2F7; + } .source_slider_frame .source_slider_text_on { display: none; } - .source_slider_frame__on .source_slider_text_off { display: none; } + .source_slider_frame__on .source_slider_text_off { display: none; } - .source_slider_frame__on .source_slider_text_on { display: block; } + .source_slider_frame__on .source_slider_text_on { display: block; } - .source_slider_frame__on .source_slider_button { - background: #73c051; - color: #fff; - } + .source_slider_frame__on .source_slider_button { + background: #73c051; + color: #fff; + } /* /Togglers ---------------------------------------------------------------------------------- */ diff --git a/assets/css/cosmetic/helpers.less b/assets/css/cosmetic/helpers.less index 85e6199..2f55859 100644 --- a/assets/css/cosmetic/helpers.less +++ b/assets/css/cosmetic/helpers.less @@ -2,38 +2,38 @@ ---------------------------------------------------------------------------------- */ .source_delim { - background: none; - border: 0 none; - border-top: 1px dotted @black; - height: 0; padding: 0; - margin: 20px 0; - } + background: none; + border: 0 none; + border-top: 1px dotted @black; + height: 0; padding: 0; + margin: 20px 0; + } .source_clear { - width: 100%; - clear: both; - height: 0; - font-size:0; - line-height:0; - } + width: 100%; + clear: both; + height: 0; + font-size:0; + line-height:0; + } .source_tx { - margin: 5px 0 20px; - } + margin: 5px 0 20px; + } .source_huge { - font-size: 1.2em; - } + font-size: 1.2em; + } .source_ul { - margin: 0; padding: 0; - margin-left: 18px; + margin: 0; padding: 0; + margin-left: 18px; - list-style: outside disc; - } - .source_ul li { - margin: 5px 0; - } + list-style: outside disc; + } + .source_ul li { + margin: 5px 0; + } /* /Helpers ----------------------------------------------------------------------------------- */ \ No newline at end of file +---------------------------------------------------------------------------------- */ diff --git a/assets/css/cosmetic/links.less b/assets/css/cosmetic/links.less index f6fc5ec..b05781d 100644 --- a/assets/css/cosmetic/links.less +++ b/assets/css/cosmetic/links.less @@ -38,67 +38,67 @@ /* TODO: rename classes */ .source_a_hl, /* Higlight link */ .source_a_o { /* Regular link */ - &:link, - &:visited { - text-decoration:none; - color: lighten(@blue, 10%); - } + &:link, + &:visited { + text-decoration:none; + color: lighten(@blue, 10%); + } &:hover { - color: @blue; - text-decoration: underline; - } - } + color: @blue; + text-decoration: underline; + } + } .source_a_bl { /* Emphasized link */ - &:link, - &:visited { - color: @black; - } - } + &:link, + &:visited { + color: @black; + } + } .source_a_l { /* Inverted link */ - &:link, - &:visited { - color: lighten(@black, 40%); - text-decoration: none; + &:link, + &:visited { + color: lighten(@black, 40%); + text-decoration: none; line-height: 1.5; - } + } &:hover { - color: #fff; - } - } + color: #fff; + } + } .source_a_g { /* Object link */ - &:link, - &:visited { - color: @blue; - text-decoration: none; - } + &:link, + &:visited { + color: @blue; + text-decoration: none; + } &:hover { - color: @blue; - text-decoration: underline; - } - } + color: @blue; + text-decoration: underline; + } + } .source_a_hl { /* Higlight link */ - font-size: 16px !important; - line-height: 2; + font-size: 16px !important; + line-height: 2; &:after { - content:"\A"; - white-space:pre; - } - } + content:"\A"; + white-space:pre; + } + } .source_a_d { /* Design link */ - &:link, - &:visited { - color: @green !important; - font-size: 16px; - } + &:link, + &:visited { + color: @green !important; + font-size: 16px; + } &:hover { color: @green; @@ -108,18 +108,18 @@ &:before { content: ''; display: inline; - padding-right: 25px; + padding-right: 25px; background: url(/source/assets/i/spec_design_link.svg) 50% no-repeat; } } .source_a_s { /* Spec link */ - &:link, - &:visited { - color: @green !important; - font-size: 16px; - } + &:link, + &:visited { + color: @green !important; + font-size: 16px; + } &:hover { color: @green; @@ -129,9 +129,9 @@ &:before { content: ''; display: inline; - padding-right: 25px; + padding-right: 25px; background: url(/source/assets/i/spec_link.svg) 50% no-repeat; - } + } } @@ -143,4 +143,4 @@ } /* /Links ----------------------------------------------------------------------------------- */ \ No newline at end of file +---------------------------------------------------------------------------------- */ diff --git a/assets/css/defaults.less b/assets/css/defaults.less index 77b775e..12dd05c 100644 --- a/assets/css/defaults.less +++ b/assets/css/defaults.less @@ -22,6 +22,7 @@ @import url('project/layout.less'); @import url('project/header.less'); @import url('project/footer.less'); +@import url('project/breadcrumb.less'); @import url('project/catalog.less'); @import url('project/navigation.less'); @import url('project/info.less'); @@ -39,4 +40,4 @@ @import url('cosmetic/links.less'); @import url('cosmetic/helpers.less'); -/*# sourceMappingURL=defaults.css.map */ \ No newline at end of file +/*# sourceMappingURL=defaults.css.map */ diff --git a/assets/css/project/auth.less b/assets/css/project/auth.less index 994cafc..c37fb55 100644 --- a/assets/css/project/auth.less +++ b/assets/css/project/auth.less @@ -1,35 +1,35 @@ .source_login { - display: inline-block; - height: 40px; - float: right; + display: inline-block; + height: 40px; + float: right; - margin-top: 2px; - vertical-align: top; - } + margin-top: 2px; + vertical-align: top; + } .source_login-avatar { - width: 25px; - height: 25px; + width: 25px; + height: 25px; - border-radius: 50%; - border: 1px solid #FFF; - cursor: pointer; - } + border-radius: 50%; + border: 1px solid #FFF; + cursor: pointer; + } - .source_login-avatar.anonymous { - border: 1px solid #333; - } + .source_login-avatar.anonymous { + border: 1px solid #333; + } .source_login-button { - display: inline-block; + display: inline-block; - color: #999; - text-decoration: none; - line-height: 1; - cursor: pointer; - vertical-align: top; - margin: 5px 0px 0px 10px; - } - .source_login-button:hover { - color: #FFF - } \ No newline at end of file + color: #999; + text-decoration: none; + line-height: 1; + cursor: pointer; + vertical-align: top; + margin: 5px 0px 0px 10px; + } + .source_login-button:hover { + color: #FFF + } diff --git a/assets/css/project/autocomplete.less b/assets/css/project/autocomplete.less index bc6cfd0..21906f4 100644 --- a/assets/css/project/autocomplete.less +++ b/assets/css/project/autocomplete.less @@ -1,68 +1,68 @@ /* Autocomplete ---------------------------------------------------------------------------------- */ .autocomplete-wrapper { - border: 1px solid #ccc; - border-radius: 4px; - background: #FFF; - font-size: 12px; + border: 1px solid #ccc; + border-radius: 4px; + background: #FFF; + font-size: 12px; - font-family: @font-family-main; - line-height: 1.5; - } + font-family: @font-family-main; + line-height: 1.5; + } .autocomplete-suggestions { - overflow: auto; + overflow: auto; - margin-top: 1px; - } + margin-top: 1px; + } - .autocomplete-suggestions strong { - font-weight: normal; - text-shadow: 0 0 1px @light-gray; - color: #00A0FE; - } + .autocomplete-suggestions strong { + font-weight: normal; + text-shadow: 0 0 1px @light-gray; + color: #00A0FE; + } - .autocomplete-suggestions span { - color: @gray; - } + .autocomplete-suggestions span { + color: @gray; + } .autocomplete-suggestion { - padding: 4px 8px; - padding-left: 28px; + padding: 4px 8px; + padding-left: 28px; - white-space: nowrap; - overflow: hidden; - max-width: 100%; + white-space: nowrap; + overflow: hidden; + max-width: 100%; - text-overflow: ellipsis; - cursor: pointer; - } + text-overflow: ellipsis; + cursor: pointer; + } - .autocomplete-suggestion > a { - color: @black; - text-decoration: none; - } + .autocomplete-suggestion > a { + color: @black; + text-decoration: none; + } .autocomplete-selected { - background: @light-gray; - } + background: @light-gray; + } - .autocomplete-selected:before, + .autocomplete-selected:before, .autocomplete-show-all:hover:before, .autocomplete-show-all.__active:before { - content: "►"; - color: @gray; - margin: 0 6px 0 -18px; - } + content: "►"; + color: @gray; + margin: 0 6px 0 -18px; + } .autocomplete-show-all { - background: @light-gray; - } + background: @light-gray; + } - .autocomplete-show-all:hover, + .autocomplete-show-all:hover, .autocomplete-show-all.__active { - background: #d1d2d3; - } + background: #d1d2d3; + } /* /Autocomplete ----------------------------------------------------------------------------------- */ \ No newline at end of file +---------------------------------------------------------------------------------- */ diff --git a/assets/css/project/breadcrumb.less b/assets/css/project/breadcrumb.less new file mode 100644 index 0000000..18bb2ac --- /dev/null +++ b/assets/css/project/breadcrumb.less @@ -0,0 +1,50 @@ +/* Breadcrumb +-------------------------------------------------- */ + +.source_breadcrumb { + display: block; + vertical-align: 1px; + background: #f1f2f3; + margin: 0 -25px; + padding: 10px 25px; + + white-space: nowrap; + overflow: hidden; + overflow-x: auto; + -webkit-overflow-scrolling: touch; +} + +.source_breadcrumb_lst { + margin-top: 0; + margin-bottom: 0; + padding: 0; + list-style: none; +} + +.source_breadcrumb_i { + display: inline-block; + margin: 0 5px; + + font-family: Arial, Helvetica, sans-serif; + font-size: 14px; + line-height: 1.5; + white-space: nowrap; + + &:first-child { + margin-left: 0; + } + &:last-child { + margin-right: 0; + + &:after { + display: none; + } + } +} +.source_breadcrumb_i:after { + display: inline-block;; + margin: 0 0 0 13px; + content: '/'; + color: rgba(0,0,0,0.3); +} +/* /Breadcrumb */ diff --git a/assets/css/project/catalog.less b/assets/css/project/catalog.less index 6dbaa9b..2152d3e 100644 --- a/assets/css/project/catalog.less +++ b/assets/css/project/catalog.less @@ -69,7 +69,7 @@ .source_catalog > p, .source_catalog_tx { - margin: 0 0 20px !important; + margin: 0 0 20px !important; color: @gray !important; font-size: @fz-size-s !important; @@ -79,9 +79,9 @@ } p { - margin: 0 0 10px; - } - } + margin: 0 0 10px; + } + } .source_subhead > p, .source_subhead .source_catalog_tx { @@ -90,17 +90,17 @@ } .source_catalog_list { - list-style: none; - margin: 0; - padding: 0; - } + list-style: none; + margin: 0; + padding: 0; + } .source_catalog_list_i { - width: 30%; - margin-right: 3% !important; - display: inline-block; - vertical-align: top; - } + width: 30%; + margin-right: 3% !important; + display: inline-block; + vertical-align: top; + } .source_catalog.__show-preview .source_catalog_list_i { vertical-align: baseline; @@ -123,15 +123,15 @@ } .source_catalog_a { - position: relative; - display: block; - margin-left: -10px; - padding: 5px 10px; + position: relative; + display: block; + margin-left: -10px; + padding: 5px 10px; - font-size: @fz-size-m; - text-decoration: none; + font-size: @fz-size-m; + text-decoration: none; - a&:hover { //tag for weight + a&:hover { //tag for weight text-decoration: none; background-color: @blue__hover !important; color: #fff; @@ -142,7 +142,7 @@ } } - } + } .source_catalog_update-button, .source_catalog_image-tumbler { @@ -173,14 +173,14 @@ } .source_catalog_footer { - color: @gray; - font-size: 11px; + color: @gray; + font-size: 11px; line-height: 1.5; - text-decoration: none !important; - } + text-decoration: none !important; + } .source_catalog_all { - margin: 20px 0 0 0; + margin: 20px 0 0 0; a.source_a_bl { color: @gray; @@ -191,7 +191,7 @@ } } - } + } .source_catalog-filter { float: right; @@ -244,4 +244,4 @@ } } /* /Catalog ----------------------------------------------------------------------------------- */ \ No newline at end of file +---------------------------------------------------------------------------------- */ diff --git a/assets/css/project/clarify.less b/assets/css/project/clarify.less index fa5d38d..de7be04 100644 --- a/assets/css/project/clarify.less +++ b/assets/css/project/clarify.less @@ -23,7 +23,7 @@ -------------------------------------------------- */ .source_clarify_content { - padding: 0 20px 20px; + padding: 0 20px 20px; } /* /Layout */ diff --git a/assets/css/project/examples.less b/assets/css/project/examples.less index bdc9035..bbebb90 100644 --- a/assets/css/project/examples.less +++ b/assets/css/project/examples.less @@ -2,24 +2,24 @@ ---------------------------------------------------------------------------------- */ .source_example { - position: relative; + position: relative; - display: inline-block; - vertical-align: top; + display: inline-block; + vertical-align: top; - padding: 20px; - min-width: 500px; - border: 5px solid #f0f0f0; - margin: 10px 0 15px; + padding: 20px; + min-width: 500px; + border: 5px solid #f0f0f0; + margin: 10px 0 15px; - background: none; - } - .source_example:hover { - z-index: 20; - } - .source_example:empty { - display: none; - } + background: none; + } + .source_example:hover { + z-index: 20; + } + .source_example:empty { + display: none; + } .source_example__2 { width: 215px; } .source_example__3 { width: 730px; } @@ -28,9 +28,9 @@ .source_example__auto { width: auto; } .source_example__full { - width: 100%; - box-sizing: border-box; - } + width: 100%; + box-sizing: border-box; + } .source_example__2, .source_example__3, @@ -38,15 +38,15 @@ .source_example__5, .source_example__auto, .source_example__full { - min-width: 0; - } + min-width: 0; + } .source_example__3, .source_example__4, .source_example__5, .source_example__full { - margin-right: 0; - } + margin-right: 0; + } /* /Code examples ----------------------------------------------------------------------------------- */ \ No newline at end of file +---------------------------------------------------------------------------------- */ diff --git a/assets/css/project/footer.less b/assets/css/project/footer.less index c9a4552..f7e5508 100644 --- a/assets/css/project/footer.less +++ b/assets/css/project/footer.less @@ -2,47 +2,47 @@ ---------------------------------------------------------------------------------- */ .source_footer { - position: relative; - z-index: 11; /* Higher than nav */ + position: relative; + z-index: 11; /* Higher than nav */ - margin: 0 -25px; + margin: 0 -25px; - -ms-flex-preferred-size: auto; + -ms-flex-preferred-size: auto; - border-top: 1px solid #eee; - padding: 30px 0; - background: @black; + border-top: 1px solid #eee; + padding: 30px 25px; + background: @black; - box-sizing: border-box; + box-sizing: border-box; font-family: @font-family-main; - font-size: @fz-size-xs; + font-size: @fz-size-xs; line-height: 1.5; - color: @gray; - } - - .source_footer h2 { - .reset(); - margin-bottom: 10px; - font-weight: normal; - font-size: 15px; - color: #666; - } - - .source_footer .source_ul { - color: @gray; - margin: 0; - list-style: none; - } + color: @gray; +} + +.source_footer h2 { + .reset(); + margin-bottom: 10px; + font-weight: normal; + font-size: 15px; + color: #666; +} + +.source_footer .source_ul { + color: @gray; + margin: 0; + list-style: none; +} .source_footer_copy { - margin-top: 40px; - line-height: 2; - } + margin-top: 40px; + line-height: 2; +} .source_footer_version { - color: @color-aux2; - } + color: @color-aux2; +} /* /Footer ----------------------------------------------------------------------------------- */ \ No newline at end of file +---------------------------------------------------------------------------------- */ diff --git a/assets/css/project/header.less b/assets/css/project/header.less index 6cea823..86e30a5 100644 --- a/assets/css/project/header.less +++ b/assets/css/project/header.less @@ -5,18 +5,17 @@ position: relative; margin: -50px -25px 0; - height: 50px; - min-width: 990px; - padding-top: 11px; - padding-bottom: 10px; - z-index: 9999; /* overlap all */ - top: 0; left: 0; right: 0; + height: 50px; + min-width: 990px; + padding: 11px 25px 10px 25px; + z-index: 9999; /* overlap all */ + top: 0; left: 0; right: 0; - background: @black; + background: @black; - box-sizing: border-box; + box-sizing: border-box; - transition: opacity .2s; + transition: opacity .2s; white-space: nowrap; @@ -24,74 +23,74 @@ font-size: @fz-size-m; @media @media_min-step-m { - position: fixed; + position: fixed; margin: 0; - } - + } + .source__scrolled-down & { opacity: 1; @media @media_min-step-m {opacity: .1;} - } + } .source__scrolled-down &:hover { opacity: 1; - } - } + } +} .source__scrolled-down .source_header__focus, .source_header__focus { - opacity: 1; - } + opacity: 1; +} .source_header .source_logo { - display: inline-block; - vertical-align: baseline; + display: inline-block; + vertical-align: baseline; - margin-right: 25px; + margin-right: 25px; - line-height: 30px !important; + line-height: 30px !important; - color: #67a9d4; - font-size: 24px !important; + color: #67a9d4; + font-size: 24px !important; font-family: 'Museo', Arial; - text-decoration: none; + text-decoration: none; &:hover { - color: #67a9d4; + color: #67a9d4; - text-decoration: underline; - } - } + text-decoration: underline; + } +} /* Navigation -------------------------------------------------- */ .source_header_nav { - display: inline-block; - vertical-align: 1px; - } + display: inline-block; + vertical-align: 1px; +} .source_header_nav_lst { - margin: 0; - padding: 0; - list-style: none; - } + margin: 0; + padding: 0; + list-style: none; +} .source_header_nav_i { - display: inline-block; - margin-left: 20px; + display: inline-block; + margin-left: 20px; - /* Reset */ - line-height: 1.5; + /* Reset */ + line-height: 1.5; &:first-child { - margin-left: 0; - } - } + margin-left: 0; + } +} /* /Navigation */ /* /Header ----------------------------------------------------------------------------------- */ \ No newline at end of file +---------------------------------------------------------------------------------- */ diff --git a/assets/css/project/info.less b/assets/css/project/info.less index 8ebae3d..1db657f 100644 --- a/assets/css/project/info.less +++ b/assets/css/project/info.less @@ -8,18 +8,18 @@ .source_note, .source_warn, .source_info { - display: block; - position: relative; + display: block; + position: relative; box-sizing: content-box !important; margin-top: 20px !important; margin-bottom: 20px !important; line-height: 1.5; - border-radius: @border-radius !important; + border-radius: @border-radius !important; @media @media_min-step-m { // Legacy - margin-right: @layout_spec--inner-margin-right !important; + margin-right: @layout_spec--inner-margin-right !important; // New spec page modifier .source_page.__spec & { margin-right: 0 !important;} @@ -34,16 +34,16 @@ } &:empty { - display: none; - } + display: none; + } p { - margin: 0 0 10px !important; + margin: 0 0 10px !important; &:last-child { - margin-bottom: 0 !important; - } - } + margin-bottom: 0 !important; + } + } th, td { border-color: #868686 !important; @@ -55,23 +55,23 @@ } .source_info { - background: #FFF6DD !important; + background: #FFF6DD !important; - padding: 15px 25px !important; - min-height: 50px !important; + padding: 15px 25px !important; + min-height: 50px !important; margin-top: 15px !important; margin-bottom: 15px !important; - } + } .source_warn { - padding: 10px 10px 10px 35px !important; + padding: 10px 10px 10px 35px !important; - background: #ffe2e5 url(/source/assets/i/warn.png) no-repeat 13px 13px !important; + background: #ffe2e5 url(/source/assets/i/warn.png) no-repeat 13px 13px !important; .source_section & { margin-right: 0 !important; } - } + } .source_note { padding: 10px 10px 10px 35px !important; @@ -100,4 +100,4 @@ } /* /Info blocks ----------------------------------------------------------------------------------- */ \ No newline at end of file +---------------------------------------------------------------------------------- */ diff --git a/assets/css/project/layout.less b/assets/css/project/layout.less index 6c33509..2132374 100644 --- a/assets/css/project/layout.less +++ b/assets/css/project/layout.less @@ -2,62 +2,62 @@ ---------------------------------------------------------------------------------- */ .source_container { - position: relative; - padding: 50px 25px 0; /*350px; /* Footer height + margin */ + position: relative; + padding: 50px 25px 0; /*350px; /* Footer height + margin */ - min-height: 100vh; - overflow-x: hidden; - width: 100%; + min-height: 100vh; + overflow-x: hidden; + width: 100%; - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; - box-sizing: border-box; + box-sizing: border-box; - .opera12 & { - display: block; - } + .opera12 & { + display: block; + } @media @media_min-step-m { - min-width: 990px; + min-width: 990px; } - } + } .source_main { - position: relative; - padding: 35px 0 120px; - margin-bottom: 40px; + position: relative; + padding: 35px 0 120px; + margin-bottom: 40px; - flex: 1; - -ms-flex: none; + flex: 1; + -ms-flex: none; - width: 100%; - box-sizing: border-box; + width: 100%; + box-sizing: border-box; - counter-reset: h2; + counter-reset: h2; @media @media_min-step-m { - .source_page.__spec & { - padding-right: @layout_spec--inner-margin-right; - } - } - - &.__loading:after { - content: ''; - position: absolute; - width: 100%; - height: 90px; - left: 0; - bottom: 15px; - - background-image: url(data:image/gif;base64,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); - background-repeat: no-repeat; - background-position: 50% 0; - } - } + .source_page.__spec & { + padding-right: @layout_spec--inner-margin-right; + } + } + + &.__loading:after { + content: ''; + position: absolute; + width: 100%; + height: 90px; + left: 0; + bottom: 15px; + + background-image: url(data:image/gif;base64,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); + background-repeat: no-repeat; + background-position: 50% 0; + } + } .source_main_h1 { - margin: 0; + margin: 0; padding: 10px 0 0 0; font-size: 36px; @@ -70,11 +70,11 @@ } .source_header-meta { - font-size: @fz-size-xs !important; - line-height: 1.2 !important; + font-size: @fz-size-xs !important; + line-height: 1.2 !important; color: @color-aux; - margin-bottom: 20px; - } + margin-bottom: 20px; + } .source-main-only(h1,{ .source_main_h1; @@ -92,7 +92,7 @@ font-family: @font-family-main; font-size: @fz-size-m; - color: @gray; + color: @gray; line-height: 1.5; // Clearfix @@ -110,9 +110,9 @@ .source_main_descr > ul, .source_main_descr > p, .source_main_descr { - margin-bottom: 20px; - font-size: @fz-size-m; - } + margin-bottom: 20px; + font-size: @fz-size-m; + } /* /Layout ---------------------------------------------------------------------------------- */ diff --git a/assets/css/project/navigation.less b/assets/css/project/navigation.less index 22010ea..3f89482 100644 --- a/assets/css/project/navigation.less +++ b/assets/css/project/navigation.less @@ -4,7 +4,7 @@ .source_main_nav { margin-top: 40px; - @media @media_min-step-m { + @media @media_min-step-m { position: fixed; z-index: 10; @@ -20,11 +20,11 @@ transition: top 0.3s; .source__scrolled-down & { - top: 70px; - } - } + top: 70px; + } + } - @media @media_min-step-l { + @media @media_min-step-l { position: fixed; z-index: 10; @@ -35,108 +35,108 @@ margin-top: 0; //reset margin-right: 0; //reset - } - } - - .source_main_nav:hover { - z-index: 20; /* Higher than any other elements */ - } - - .source_main_nav h2 { - font-weight: normal; - font-size: 15px; - color: @black; - margin: 0 0 5px; - line-height: 1.5; - font-family: inherit; - text-rendering: auto; - } - - .source_main_nav.__menuScroll { - overflow-x: hidden; - overflow-y: auto; - bottom: 15px; - } - - .source_main_nav_i { - margin: 10px 0; - font-size: @fz-size-xs; - } - .source_main_nav_i:first-child { - margin-top: 0; - } - - .source_main_nav_i + .source_main_nav_i { - padding-top: 10px; - border-top: 1px solid #dfe2e4; - } + } + } + + .source_main_nav:hover { + z-index: 20; /* Higher than any other elements */ + } + + .source_main_nav h2 { + font-weight: normal; + font-size: 15px; + color: @black; + margin: 0 0 5px; + line-height: 1.5; + font-family: inherit; + text-rendering: auto; + } + + .source_main_nav.__menuScroll { + overflow-x: hidden; + overflow-y: auto; + bottom: 15px; + } + + .source_main_nav_i { + margin: 10px 0; + font-size: @fz-size-xs; + } + .source_main_nav_i:first-child { + margin-top: 0; + } + + .source_main_nav_i + .source_main_nav_i { + padding-top: 10px; + border-top: 1px solid #dfe2e4; + } .source_main_nav_ul { - margin-left: -21px; /* menu padding compensation */ - margin-right: -21px; - } + margin-left: -21px; /* menu padding compensation */ + margin-right: -21px; + } .source_main_nav_li { - line-height: 20px; - margin-bottom: 2px; - } + line-height: 20px; + margin-bottom: 2px; + } .source_main_nav_ul2 { - padding: 0; - } + padding: 0; + } .source_main_nav_li2 { - color: #666; - overflow: hidden; - display: none; - text-overflow: ellipsis; - white-space: nowrap; - } - .source_main_nav_li.__active .source_main_nav_li2 { - display: block; - } + color: #666; + overflow: hidden; + display: none; + text-overflow: ellipsis; + white-space: nowrap; + } + .source_main_nav_li.__active .source_main_nav_li2 { + display: block; + } .source_nav_ul .source_main_nav_a { - overflow: hidden; - text-overflow: ellipsis; + overflow: hidden; + text-overflow: ellipsis; text-decoration: none; - padding: 0 21px; + padding: 0 21px; color: #4792D2; &:hover { color: #1c76c2; text-decoration: underline; } - } - .source_main_nav_li2 .source_main_nav_a { - padding: 0 37px; - } - .source_main_nav .source_main_nav_a.__active { /* for weight */ - background-color: #8AB5D6; - color: #F9FBFD; - } + } + .source_main_nav_li2 .source_main_nav_a { + padding: 0 37px; + } + .source_main_nav .source_main_nav_a.__active { /* for weight */ + background-color: #8AB5D6; + color: #F9FBFD; + } .source_main_nav_ac_item { - position: relative; - line-height: 24px; + position: relative; + line-height: 24px; &.__simple { text-align: right; } - } + } .source_main_nav_ac_tx { line-height: 24px; } .source_main_nav_ac_item.__simple { - text-align: right; + text-align: right; white-space: normal; - } + } .source_main_nav_ac_item.__simple .source_main_nav_ac_tx { float: left; } /* /Navigation ----------------------------------------------------------------------------------- */ \ No newline at end of file +---------------------------------------------------------------------------------- */ diff --git a/assets/css/project/search.less b/assets/css/project/search.less index f831a9c..1434384 100644 --- a/assets/css/project/search.less +++ b/assets/css/project/search.less @@ -2,60 +2,60 @@ ---------------------------------------------------------------------------------- */ .source_search { - display: inline-block; - overflow: hidden; - height: 28px; - width: 100%; + display: inline-block; + overflow: hidden; + height: 28px; + width: 100%; - border: 1px solid #444; - border-radius: 5px; - vertical-align: top; - } + border: 1px solid #444; + border-radius: 5px; + vertical-align: top; + } - .source_search.__light { - border-color: #ccc; - } + .source_search.__light { + border-color: #ccc; + } - .source_search.__light input.source_search_it { /* Cascade for weight */ - background-color: #FFF; - } + .source_search.__light input.source_search_it { /* Cascade for weight */ + background-color: #FFF; + } .source_container input.source_search_it { /* Cascade for weight */ - padding: 6px 8px; - padding-left: 28px; - height: 30px; - margin: -1px 0 0 -1px; - width: 101%; + padding: 6px 8px; + padding-left: 28px; + height: 30px; + margin: -1px 0 0 -1px; + width: 101%; - border: 0 none; - line-height: 15px; - background: #000 url(/source/assets/i/search.png) no-repeat 8px 50%; + border: 0 none; + line-height: 15px; + background: #000 url(/source/assets/i/search.png) no-repeat 8px 50%; - box-sizing: border-box; + box-sizing: border-box; color: @gray; - /* Resets */ - display: block; + /* Resets */ + display: block; - box-shadow: none; + box-shadow: none; - border-radius: 0; + border-radius: 0; - transition: none; + transition: none; - font-weight: 400; - font-family: @font-family-main; - font-size: @fz-size-m; - line-height: 1.5; + font-weight: 400; + font-family: @font-family-main; + font-size: @fz-size-m; + line-height: 1.5; - vertical-align: middle; - } + vertical-align: middle; + } .source_container input.source_search_it:focus { - background: #fff url(/source/assets/i/search.png) no-repeat 8px 50%; - color: @black; - } + background: #fff url(/source/assets/i/search.png) no-repeat 8px 50%; + color: @black; + } /* /Search ----------------------------------------------------------------------------------- */ \ No newline at end of file +---------------------------------------------------------------------------------- */ diff --git a/assets/css/project/section.less b/assets/css/project/section.less index da3edb5..f993928 100644 --- a/assets/css/project/section.less +++ b/assets/css/project/section.less @@ -2,192 +2,192 @@ ---------------------------------------------------------------------------------- */ .source_section { - padding-left: @layout_spec--inner-padding; - counter-reset: h3; + padding-left: @layout_spec--inner-padding; + counter-reset: h3; @media @media_min-step-m { - // Legacy - margin-right: @layout_spec--inner-margin-right; + // Legacy + margin-right: @layout_spec--inner-margin-right; - // New spec page modifier - .source_page.__spec & { margin-right: 0; } - } + // New spec page modifier + .source_page.__spec & { margin-right: 0; } + } & > h2:first-child { - margin-left: -@layout_spec--inner-padding !important; + margin-left: -@layout_spec--inner-padding !important; &:before { - counter-increment: h2 1; - content: counter(h2)". "; - color: #666; - } - } + counter-increment: h2 1; + content: counter(h2)". "; + color: #666; + } + } /* Error detection */ & > h2:not(:first-child) { - .reset(); + .reset(); - background-color: rgba(250, 0, 0, .2); - outline: 3px solid red; - outline-offset: 3px; + background-color: rgba(250, 0, 0, .2); + outline: 3px solid red; + outline-offset: 3px; - &:after { - content: " error - duplicate h2 or not first tag in section"; - font-weight: normal; - color: @black; - } - } + &:after { + content: " error - duplicate h2 or not first tag in section"; + font-weight: normal; + color: @black; + } + } & > h3 { - position: relative; - margin: 30px 0 15px -25px; - padding: 0 25px; + position: relative; + margin: 30px 0 15px -25px; + padding: 0 25px; - font-size: 16px; - color: #000; - font-weight: normal; - line-height: 1.5; - font-family: inherit; + font-size: 16px; + color: #000; + font-weight: normal; + line-height: 1.5; + font-family: inherit; - counter-reset: h4; + counter-reset: h4; &:after { - content: ""; - border-bottom: 1px dotted #666; - position: absolute; - left: 0; right: 0; top: 50%; - } - } + content: ""; + border-bottom: 1px dotted #666; + position: absolute; + left: 0; right: 0; top: 50%; + } + } & > h3 > span { - position: relative; z-index: 1; - display: inline-block; - padding: 0 5px; background: #fff; + position: relative; z-index: 1; + display: inline-block; + padding: 0 5px; background: #fff; &:before { - color: @gray; - counter-increment: h3 1; - content: counter(h2)"."counter(h3)". "; - } - } + color: @gray; + counter-increment: h3 1; + content: counter(h2)"."counter(h3)". "; + } + } & > h4 { - margin: 30px 0 10px; - padding: 0; - font-size: @fz-size-m; - font-family: @font-family-main; - color: @black; - font-weight: normal; - text-indent: .5ex; - line-height: 1.5; + margin: 30px 0 10px; + padding: 0; + font-size: @fz-size-m; + font-family: @font-family-main; + color: @black; + font-weight: normal; + text-indent: .5ex; + line-height: 1.5; &:before { - color: @gray; - counter-increment: h4 1; - content: counter(h2)"."counter(h3)"."counter(h4)". "; - } - } + color: @gray; + counter-increment: h4 1; + content: counter(h2)"."counter(h3)"."counter(h4)". "; + } + } - & > p { - margin: 15px 0; - } + & > p { + margin: 15px 0; + } - & > pre { - .reset(); - } - } + & > pre { + .reset(); + } + } /* Dynamics -------------------------------------------------- */ /* Everything closed by default */ .source_section { - position: absolute; - height: 0; - width: 0; - top: -9999px; - overflow: hidden; - - &.__loaded { - position: relative; - height: auto; - width: auto; - overflow: visible; - top: 0; - margin-top: 20px; - margin-bottom: 40px; - } + position: absolute; + height: 0; + width: 0; + top: -9999px; + overflow: hidden; + + &.__loaded { + position: relative; + height: auto; + width: auto; + overflow: visible; + top: 0; + margin-top: 20px; + margin-bottom: 40px; + } & > script, & > style { - display: none !important; - } + display: none !important; + } body & > * { //body for weihgt display: none; } body & > h2:first-child { //body for weihgt - display: block; - } - } + display: block; + } + } .source_section__open { & > *:not(.source_example) { - display: block; - } + display: block; + } & > .source_a_hl { - display: inline; - } + display: inline; + } .source_example { - display: inline-block; - } + display: inline-block; + } .spoiler-cont_css_w, - .spoiler-cont_js_w, - .spoiler-cont_xml_w { - display: none !important; - } + .spoiler-cont_js_w, + .spoiler-cont_xml_w { + display: none !important; + } .source_section_h_expand:after { - content: "▼"; - } + content: "▼"; + } .source_source-code__show, .source_source-code__static, .source_context.__show { - display: block !important; - } + display: block !important; + } .source_context { display: none !important; } - } + } /* Header actions */ .source_section > h2:first-child, .source_section_h { - .reset(); + .reset(); - position: relative; - margin: 0 0 25px; + position: relative; + margin: 0 0 25px; - padding: 5px @layout_spec--inner-padding; - line-height: 28px; - color: @black; + padding: 5px @layout_spec--inner-padding; + line-height: 28px; + color: @black; - border-radius: 10px; - background-color: @light-gray; + border-radius: 10px; + background-color: @light-gray; - font-size: @fz-size-l; - font-family: @font-family-main; + font-size: @fz-size-l; + font-family: @font-family-main; &:hover .source_section_h_expand { - color:#4792D2 !important; //important to override link style - } - } + color:#4792D2 !important; //important to override link style + } + } .source_subsection_h { background-color: #fff !important; @@ -195,16 +195,16 @@ } .source_section_h_expand { - position: absolute; - top: 0; left: -20px; + position: absolute; + top: 0; left: -20px; - width: 20px; - height: 38px; - margin: 0 10px 0 0; + width: 20px; + height: 38px; + margin: 0 10px 0 0; - font-size: 12px !important; //override reset styles - text-decoration: none; - color: @gray !important; //important to override link style + font-size: 12px !important; //override reset styles + text-decoration: none; + color: @gray !important; //important to override link style &:after { content: "►"; @@ -216,11 +216,11 @@ text-align: left; line-height: 38px; } - } + } /* /Header actions */ /* /Dynamics */ /* /Section ----------------------------------------------------------------------------------- */ \ No newline at end of file +---------------------------------------------------------------------------------- */ diff --git a/assets/css/project/source-code.less b/assets/css/project/source-code.less index 3a0cd2a..c3ecc84 100644 --- a/assets/css/project/source-code.less +++ b/assets/css/project/source-code.less @@ -3,57 +3,57 @@ .source_source-code, code.brush { - display: none !important; /* Hide all code source by default */ - } + display: none !important; /* Hide all code source by default */ + } .source_source-code { - font-size: @fz-size-m; - } + font-size: @fz-size-m; + } .source_source-code .source_source-code_toggle .source_show {display: none;} /* Default maximazed */ .source_source-code__min .source_source-code_toggle .source_hide {display: none;} /* minimized */ .source_source-code__min .source_source-code_toggle .source_show {display: inline;} .source_source-code__min .source_source-code_cnt { - display: none; - } + display: none; + } .source_source-code_toggle { - display: inline-block; - height: 14px; - margin-bottom: 10px; - border-bottom: #25588D dashed 1px !important; - font-size: 10px !important; - text-decoration: none; - - & span { - color: inherit !important; - } - } - .source_source-code_toggle:hover { - border-bottom: none !important; + display: inline-block; + height: 14px; + margin-bottom: 10px; + border-bottom: #25588D dashed 1px !important; + font-size: 10px !important; + text-decoration: none; + + & span { + color: inherit !important; + } + } + .source_source-code_toggle:hover { + border-bottom: none !important; text-decoration: none !important; - padding-bottom: 1px; - } + padding-bottom: 1px; + } - .source_source-code_toggle__css .source_show:after, - .source_source-code_toggle__css .source_hide:after { - content: " CSS"; - } + .source_source-code_toggle__css .source_show:after, + .source_source-code_toggle__css .source_hide:after { + content: " CSS"; + } - .source_source-code_toggle__html .source_show:after, - .source_source-code_toggle__html .source_hide:after { - content: " HTML"; - } + .source_source-code_toggle__html .source_show:after, + .source_source-code_toggle__html .source_hide:after { + content: " HTML"; + } - .source_source-code_toggle__js .source_show:after, - .source_source-code_toggle__js .source_hide:after { - content: " JavaScript"; - } + .source_source-code_toggle__js .source_show:after, + .source_source-code_toggle__js .source_hide:after { + content: " JavaScript"; + } .source_source-code_toggle-all .source_hide {display: none;} /* Default hidden */ .source_source-code_toggle-all__hide .source_show {display: none;} .source_source-code_toggle-all__hide .source_hide {display: inline;} /* /Code highlighting ----------------------------------------------------------------------------------- */ \ No newline at end of file +---------------------------------------------------------------------------------- */ diff --git a/assets/css/reset.less b/assets/css/reset.less index 13a70d8..ea879bb 100644 --- a/assets/css/reset.less +++ b/assets/css/reset.less @@ -71,7 +71,7 @@ font-weight: normal; font-style: normal; } - } + } /* /Fonts */ @@ -228,4 +228,4 @@ body { /* /Spec page resets */ /* /Reset ----------------------------------------------------------------------------------- */ \ No newline at end of file +---------------------------------------------------------------------------------- */ diff --git a/assets/css/source.css b/assets/css/source.css index 987c70e..0700603 100644 --- a/assets/css/source.css +++ b/assets/css/source.css @@ -1,11 +1,11 @@ /*! * SourceJS - Living Style Guides Engine and Integrated Maintenance Environment for Front-end Components * @copyright 2013-2015 SourceJS.com -* @license MIT license: http://github.com/sourcejs/source/wiki/MIT-License +* @license MIT license: http://github.com/sourcejs/sourcejs/wiki/MIT-License * */ /* Default core styles */ @import url('/source/assets/css/defaults.css'); /* Users override */ -@import url('/assets/css/defaults.css'); \ No newline at end of file +@import url('/assets/css/defaults.css'); diff --git a/assets/js/_require-config.js b/assets/js/_require-config.js new file mode 100644 index 0000000..a0c9d41 --- /dev/null +++ b/assets/js/_require-config.js @@ -0,0 +1,36 @@ +// Joined to require.bundle.js + +sourcejs.amd.requirejs.config({ + paths: { + // /source/assets requests are routed to /assets + source: '/source/assets/js', + sourceModules: '/source/assets/js/modules', + sourceLib: '/source/assets/js/lib', + sourceTemplates: '/source/assets/templates', + + // libs + jquery: '/source/assets/js/lib/jquery-2.1.4.min', + lodash: '/source/assets/js/lib/lodash', + + // Require.js plugins + text: '/source/assets/js/lib/text', + + // Relative to user root + js: '/assets/js', + plugins: '/plugins', + node_modules: '/node_modules' + }, + + map: { + // '*' means all modules will use private versions + '*': { + 'jquery': 'sourceLib/jquery-private', + 'lodash': 'sourceLib/lodash-private', + 'sourceLib/lodash': 'sourceLib/lodash-private' + }, + + // but private version should first render the original ones + 'sourceLib/jquery-private': { 'jquery': 'jquery' }, + 'sourceLib/lodash-private': { 'lodash': 'lodash' } + } +}); diff --git a/assets/js/_require.bundle.js b/assets/js/_require.bundle.js index 50236d1..009d402 100644 --- a/assets/js/_require.bundle.js +++ b/assets/js/_require.bundle.js @@ -1,22 +1,2 @@ "{%= grunt.file.read('assets/js/lib/require.js') %}" -"{%= grunt.file.read('assets/js/lib/jquery-2.1.4.min.js') %}" -"{%= grunt.file.read('assets/js/require-config.js') %}" - -// Extending base js config with npm packages list -requirejs.config({ - // Create shorthands routes to clint-side npm plugins - packages: function () { - var modulesList = "{%= npmPluginsEnabled %}"; - - var npmPackages = []; - for (var module in modulesList) { - npmPackages.push({ - name: module, - location: '/node_modules/' + module + '/assets', - main: 'index' - }) - } - - return npmPackages; - }() -}); +"{%= grunt.file.read('assets/js/_require-config.js') %}" diff --git a/assets/js/clarify.js b/assets/js/clarify.js index 69f2ed0..5f20293 100644 --- a/assets/js/clarify.js +++ b/assets/js/clarify.js @@ -1,24 +1,21 @@ /*! * SourceJS - Front-end documentation engine * @copyright 2013-2015 Sourcejs.com -* @license MIT license: http://github.com/sourcejs/source/wiki/MIT-License +* @license MIT license: http://github.com/sourcejs/sourcejs/wiki/MIT-License * */ -require([ +sourcejs.amd.require([ "jquery", 'text!/api/options', "sourceModules/utils", "sourceLib/lodash", "text!sourceTemplates/clarifyPanel.inc.html" - ], function ($, options, u, _, clarifyPanelTpl){ - - // If we have data from Clarify output - if (window.sourceClarifyData){ - var _options = JSON.parse(options); - var htmlParser = _options.plugins && _options.plugins.htmlParser && _options.plugins.htmlParser.enabled; +], function ($, options, u, _, clarifyPanelTpl){ + var triesLimit = 2; + var triesCount = 0; + var handler = function() { var $panelTemplate = $(_.template(clarifyPanelTpl, { - htmlParser: htmlParser, showApiTargetOption: window.sourceClarifyData.showApiTargetOption, specUrl: window.sourceClarifyData.specUrl, tplList: window.sourceClarifyData.tplList, @@ -85,7 +82,21 @@ require([ location.href = clarifyBaseUrl + constructedParams; }); - } else { - console.log('Clarify panel failed to receive expected data from clarify, check your tpl.'); - } + }; + + var renderClarify = function(){ + // If we have data from Clarify output + if (window.sourceClarifyData){ + handler(); + } else { + if (triesCount < triesLimit) { + triesCount++; + setTimeout(renderClarify, 1000); + } else { + console.log('Clarify panel failed to receive expected data from clarify, check your tpl.'); + } + } + }; + + renderClarify(); }); diff --git a/assets/js/enter-the-source.js b/assets/js/enter-the-source.js index 72707c2..e6ea264 100644 --- a/assets/js/enter-the-source.js +++ b/assets/js/enter-the-source.js @@ -1,10 +1,10 @@ /*! * SourceJS - Front-end documentation engine * @copyright 2013-2015 Sourcejs.com -* @license MIT license: http://github.com/sourcejs/source/wiki/MIT-License +* @license MIT license: http://github.com/sourcejs/sourcejs/wiki/MIT-License * */ -require([ +sourcejs.amd.require([ "jquery", "source/load-options", // TODO: remove when all modules inherit Module() "sourceModules/browser", diff --git a/assets/js/lib/autocomplete.js b/assets/js/lib/autocomplete.js index f4546b9..c07d2f8 100644 --- a/assets/js/lib/autocomplete.js +++ b/assets/js/lib/autocomplete.js @@ -452,4 +452,4 @@ var searchInstance = new Autocomplete(this, options); }); }; -}); \ No newline at end of file +}); diff --git a/assets/js/lib/codeFormat.js b/assets/js/lib/codeFormat.js index 5369ee7..4b4ef15 100644 --- a/assets/js/lib/codeFormat.js +++ b/assets/js/lib/codeFormat.js @@ -6,8 +6,7 @@ * * */ - -define([ +sourcejs.amd.define([ "jquery" ], function($) { @@ -65,4 +64,4 @@ define([ }); } -}); \ No newline at end of file +}); diff --git a/assets/js/lib/jquery-private.js b/assets/js/lib/jquery-private.js new file mode 100644 index 0000000..071194e --- /dev/null +++ b/assets/js/lib/jquery-private.js @@ -0,0 +1,3 @@ +sourcejs.amd.define(['jquery'], function (jq) { + return jq.noConflict(true); +}); diff --git a/assets/js/lib/jquery.autocomplete.js b/assets/js/lib/jquery.autocomplete.js index bd8bfff..d5e3410 100755 --- a/assets/js/lib/jquery.autocomplete.js +++ b/assets/js/lib/jquery.autocomplete.js @@ -643,4 +643,4 @@ } }); }; -})); \ No newline at end of file +})); diff --git a/assets/js/lib/jquery.couch.js b/assets/js/lib/jquery.couch.js index 6abac2c..96911a3 100644 --- a/assets/js/lib/jquery.couch.js +++ b/assets/js/lib/jquery.couch.js @@ -11,1069 +11,1079 @@ // the License. /** - * @namespace - * $.couch is used to communicate with a CouchDB server, the server methods can - * be called directly without creating an instance. Typically all methods are - * passed an options object which defines a success callback which - * is called with the data returned from the http request to CouchDB, you can - * find the other settings that can be used in the options object - * from - * jQuery.ajax settings - *
$.couch.activeTasks({
- *   success: function (data) {
- *     console.log(data);
- *   }
- * });
- * Outputs (for example): - *
[
- *  {
- *   "pid" : "<0.11599.0>",
- *   "status" : "Copied 0 of 18369 changes (0%)",
- *   "task" : "recipes",
- *   "type" : "Database Compaction"
- *  }
- *]
+ * Modified in SourceJS to use custom `define` namespace and local jquery */ -(function($) { - $.couch = $.couch || {}; - /** @lends $.couch */ +sourcejs.amd.define([ + 'jquery' +], function(jQuery) { /** - * @private + * @namespace + * $.couch is used to communicate with a CouchDB server, the server methods can + * be called directly without creating an instance. Typically all methods are + * passed an options object which defines a success callback which + * is called with the data returned from the http request to CouchDB, you can + * find the other settings that can be used in the options object + * from + * jQuery.ajax settings + *
$.couch.activeTasks({
+   *   success: function (data) {
+   *     console.log(data);
+   *   }
+   * });
+ * Outputs (for example): + *
[
+   *  {
+   *   "pid" : "<0.11599.0>",
+   *   "status" : "Copied 0 of 18369 changes (0%)",
+   *   "task" : "recipes",
+   *   "type" : "Database Compaction"
+   *  }
+   *]
*/ - function encodeDocId(docID) { - var parts = docID.split("/"); - if (parts[0] == "_design") { - parts.shift(); - return "_design/" + encodeURIComponent(parts.join('/')); - } - return encodeURIComponent(docID); - } - - /** - * @private - */ - - var uuidCache = []; + (function($) { - $.extend($.couch, { - urlPrefix: '', + $.couch = $.couch || {}; + /** @lends $.couch */ /** - * You can obtain a list of active tasks by using the /_active_tasks URL. - * The result is a JSON array of the currently running tasks, with each task - * being described with a single object. - * @see docs for /_active_tasks - * @param {ajaxSettings} options jQuery ajax settings + * @private */ - activeTasks: function(options) { - ajax( - {url: this.urlPrefix + "/_active_tasks"}, - options, - "Active task status could not be retrieved" - ); - }, + function encodeDocId(docID) { + var parts = docID.split("/"); + if (parts[0] == "_design") { + parts.shift(); + return "_design/" + encodeURIComponent(parts.join('/')); + } + return encodeURIComponent(docID); + } /** - * Returns a list of all the databases in the CouchDB instance - * @see docs for /_all_dbs - * @param {ajaxSettings} options jQuery ajax settings + * @private */ - allDbs: function(options) { - ajax( - {url: this.urlPrefix + "/_all_dbs"}, - options, - "An error occurred retrieving the list of all databases" - ); - }, - /** - * View and edit the CouchDB configuration, called with just the options - * parameter the entire config is returned, you can be more specific by - * passing the section and option parameters, if you specify a value that - * value will be stored in the configuration. - * @see docs for /_config - * @param {ajaxSettings} options - * - * jQuery ajax settings - * @param {String} [section] the section of the config - * @param {String} [option] the particular config option - * @param {String} [value] value to be set - */ - config: function(options, section, option, value) { - var req = {url: this.urlPrefix + "/_config/"}; - if (section) { - req.url += encodeURIComponent(section) + "/"; - if (option) { - req.url += encodeURIComponent(option); - } - } - if (value === null) { - req.type = "DELETE"; - } else if (value !== undefined) { - req.type = "PUT"; - req.data = toJSON(value); - req.contentType = "application/json"; - req.processData = false - } + var uuidCache = []; - ajax(req, options, - "An error occurred retrieving/updating the server configuration" - ); - }, - - /** - * Returns the session information for the currently logged in user. - * @param {ajaxSettings} options - * - * jQuery ajax settings - */ - session: function(options) { - options = options || {}; - ajax({ - type: "GET", url: this.urlPrefix + "/_session", - beforeSend: function(xhr) { - xhr.setRequestHeader('Accept', 'application/json'); - }, - complete: function(req) { - var resp = $.parseJSON(req.responseText); - if (req.status == 200) { - if (options.success) options.success(resp); - } else if (options.error) { - options.error(req.status, resp.error, resp.reason); - } else { - throw "An error occurred getting session info: " + resp.reason; + $.extend($.couch, { + urlPrefix: '', + + /** + * You can obtain a list of active tasks by using the /_active_tasks URL. + * The result is a JSON array of the currently running tasks, with each task + * being described with a single object. + * @see docs for /_active_tasks + * @param {ajaxSettings} options jQuery ajax settings + */ + activeTasks: function(options) { + ajax( + {url: this.urlPrefix + "/_active_tasks"}, + options, + "Active task status could not be retrieved" + ); + }, + + /** + * Returns a list of all the databases in the CouchDB instance + * @see docs for /_all_dbs + * @param {ajaxSettings} options jQuery ajax settings + */ + allDbs: function(options) { + ajax( + {url: this.urlPrefix + "/_all_dbs"}, + options, + "An error occurred retrieving the list of all databases" + ); + }, + + /** + * View and edit the CouchDB configuration, called with just the options + * parameter the entire config is returned, you can be more specific by + * passing the section and option parameters, if you specify a value that + * value will be stored in the configuration. + * @see docs for /_config + * @param {ajaxSettings} options + * + * jQuery ajax settings + * @param {String} [section] the section of the config + * @param {String} [option] the particular config option + * @param {String} [value] value to be set + */ + config: function(options, section, option, value) { + var req = {url: this.urlPrefix + "/_config/"}; + if (section) { + req.url += encodeURIComponent(section) + "/"; + if (option) { + req.url += encodeURIComponent(option); } } - }); - }, - - /** - * @private - */ - userDb : function(callback) { - $.couch.session({ - success : function(resp) { - var userDb = $.couch.db(resp.info.authentication_db); - callback(userDb); + if (value === null) { + req.type = "DELETE"; + } else if (value !== undefined) { + req.type = "PUT"; + req.data = toJSON(value); + req.contentType = "application/json"; + req.processData = false } - }); - }, - /** - * Create a new user on the CouchDB server, user_doc is an - * object with a name field and other information you want - * to store relating to that user, for example - * {"name": "daleharvey"} - * @param {Object} user_doc Users details - * @param {String} password Users password - * @param {ajaxSettings} options - * - * jQuery ajax settings - */ - signup: function(user_doc, password, options) { - options = options || {}; - user_doc.password = password; - user_doc.roles = user_doc.roles || []; - user_doc.type = user_doc.type = "user" || []; - var user_prefix = "org.couchdb.user:"; - user_doc._id = user_doc._id || user_prefix + user_doc.name; + ajax(req, options, + "An error occurred retrieving/updating the server configuration" + ); + }, - $.couch.userDb(function(db) { - db.saveDoc(user_doc, options); - }); - }, + /** + * Returns the session information for the currently logged in user. + * @param {ajaxSettings} options + * + * jQuery ajax settings + */ + session: function(options) { + options = options || {}; + ajax({ + type: "GET", url: this.urlPrefix + "/_session", + beforeSend: function(xhr) { + xhr.setRequestHeader('Accept', 'application/json'); + }, + complete: function(req) { + var resp = $.parseJSON(req.responseText); + if (req.status == 200) { + if (options.success) options.success(resp); + } else if (options.error) { + options.error(req.status, resp.error, resp.reason); + } else { + throw "An error occurred getting session info: " + resp.reason; + } + } + }); + }, - /** - * Authenticate against CouchDB, the options parameter is - *expected to have name and password fields. - * @param {ajaxSettings} options - * - * jQuery ajax settings - */ - login: function(options) { - options = options || {}; - $.ajax({ - type: "POST", url: this.urlPrefix + "/_session", dataType: "json", - data: {name: options.name, password: options.password}, - beforeSend: function(xhr) { - xhr.setRequestHeader('Accept', 'application/json'); - }, - complete: function(req) { - var resp = $.parseJSON(req.responseText); - if (req.status == 200) { - if (options.success) options.success(resp); - } else if (options.error) { - options.error(req.status, resp.error, resp.reason); - } else { - throw 'An error occurred logging in: ' + resp.reason; + /** + * @private + */ + userDb : function(callback) { + $.couch.session({ + success : function(resp) { + var userDb = $.couch.db(resp.info.authentication_db); + callback(userDb); } - } - }); - }, + }); + }, + /** + * Create a new user on the CouchDB server, user_doc is an + * object with a name field and other information you want + * to store relating to that user, for example + * {"name": "daleharvey"} + * @param {Object} user_doc Users details + * @param {String} password Users password + * @param {ajaxSettings} options + * + * jQuery ajax settings + */ + signup: function(user_doc, password, options) { + options = options || {}; + user_doc.password = password; + user_doc.roles = user_doc.roles || []; + user_doc.type = user_doc.type = "user" || []; + var user_prefix = "org.couchdb.user:"; + user_doc._id = user_doc._id || user_prefix + user_doc.name; - /** - * Delete your current CouchDB user session - * @param {ajaxSettings} options - * - * jQuery ajax settings - */ - logout: function(options) { - options = options || {}; - $.ajax({ - type: "DELETE", url: this.urlPrefix + "/_session", dataType: "json", - username : "_", password : "_", - beforeSend: function(xhr) { - xhr.setRequestHeader('Accept', 'application/json'); - }, - complete: function(req) { - var resp = $.parseJSON(req.responseText); - if (req.status == 200) { - if (options.success) options.success(resp); - } else if (options.error) { - options.error(req.status, resp.error, resp.reason); - } else { - throw 'An error occurred logging out: ' + resp.reason; - } - } - }); - }, + $.couch.userDb(function(db) { + db.saveDoc(user_doc, options); + }); + }, - /** - * @namespace - * $.couch.db is used to communicate with a specific CouchDB database - *
var $db = $.couch.db("mydatabase");
-     *$db.allApps({
-     *  success: function (data) {
-     *    ... process data ...
-     *  }
-     *});
-     * 
- */ - db: function(name, db_opts) { - db_opts = db_opts || {}; - var rawDocs = {}; - function maybeApplyVersion(doc) { - if (doc._id && doc._rev && rawDocs[doc._id] && - rawDocs[doc._id].rev == doc._rev) { - // todo: can we use commonjs require here? - if (typeof Base64 == "undefined") { - throw 'Base64 support not found.'; - } else { - doc._attachments = doc._attachments || {}; - doc._attachments["rev-"+doc._rev.split("-")[0]] = { - content_type :"application/json", - data : Base64.encode(rawDocs[doc._id].raw) - }; - return true; + /** + * Authenticate against CouchDB, the options parameter is + *expected to have name and password fields. + * @param {ajaxSettings} options + * + * jQuery ajax settings + */ + login: function(options) { + options = options || {}; + $.ajax({ + type: "POST", url: this.urlPrefix + "/_session", dataType: "json", + data: {name: options.name, password: options.password}, + beforeSend: function(xhr) { + xhr.setRequestHeader('Accept', 'application/json'); + }, + complete: function(req) { + var resp = $.parseJSON(req.responseText); + if (req.status == 200) { + if (options.success) options.success(resp); + } else if (options.error) { + options.error(req.status, resp.error, resp.reason); + } else { + throw 'An error occurred logging in: ' + resp.reason; + } } - } - }; - return /** @lends $.couch.db */{ - name: name, - uri: this.urlPrefix + "/" + encodeURIComponent(name) + "/", + }); + }, - /** - * Request compaction of the specified database. - * @see docs for /db/_compact - * @param {ajaxSettings} options - * - * jQuery ajax settings - */ - compact: function(options) { - $.extend(options, {successStatus: 202}); - ajax({ - type: "POST", url: this.uri + "_compact", - data: "", processData: false - }, - options, - "The database could not be compacted" - ); - }, - /** - * Cleans up the cached view output on disk for a given view. - * @see docs for /db/_compact - * @param {ajaxSettings} options jQuery ajax settings - */ - viewCleanup: function(options) { - $.extend(options, {successStatus: 202}); - ajax({ - type: "POST", url: this.uri + "_view_cleanup", - data: "", processData: false - }, - options, - "The views could not be cleaned up" - ); - }, + /** + * Delete your current CouchDB user session + * @param {ajaxSettings} options + * + * jQuery ajax settings + */ + logout: function(options) { + options = options || {}; + $.ajax({ + type: "DELETE", url: this.urlPrefix + "/_session", dataType: "json", + username : "_", password : "_", + beforeSend: function(xhr) { + xhr.setRequestHeader('Accept', 'application/json'); + }, + complete: function(req) { + var resp = $.parseJSON(req.responseText); + if (req.status == 200) { + if (options.success) options.success(resp); + } else if (options.error) { + options.error(req.status, resp.error, resp.reason); + } else { + throw 'An error occurred logging out: ' + resp.reason; + } + } + }); + }, - /** - * Compacts the view indexes associated with the specified design - * document. You can use this in place of the full database compaction - * if you know a specific set of view indexes have been affected by a - * recent database change. - * @see docs for /db/_compact/design-doc - * @param {String} groupname Name of design-doc to compact - * @param {ajaxSettings} options jQuery ajax settings - */ - compactView: function(groupname, options) { - $.extend(options, {successStatus: 202}); - ajax({ - type: "POST", url: this.uri + "_compact/" + groupname, - data: "", processData: false - }, - options, - "The view could not be compacted" - ); - }, + /** + * @namespace + * $.couch.db is used to communicate with a specific CouchDB database + *
var $db = $.couch.db("mydatabase");
+       *$db.allApps({
+       *  success: function (data) {
+       *    ... process data ...
+       *  }
+       *});
+       * 
+ */ + db: function(name, db_opts) { + db_opts = db_opts || {}; + var rawDocs = {}; + function maybeApplyVersion(doc) { + if (doc._id && doc._rev && rawDocs[doc._id] && + rawDocs[doc._id].rev == doc._rev) { + // todo: can we use commonjs require here? + if (typeof Base64 == "undefined") { + throw 'Base64 support not found.'; + } else { + doc._attachments = doc._attachments || {}; + doc._attachments["rev-"+doc._rev.split("-")[0]] = { + content_type :"application/json", + data : Base64.encode(rawDocs[doc._id].raw) + }; + return true; + } + } + }; + return /** @lends $.couch.db */{ + name: name, + uri: this.urlPrefix + "/" + encodeURIComponent(name) + "/", - /** - * Create a new database - * @see docs for PUT /db/ - * @param {ajaxSettings} options jQuery ajax settings - */ - create: function(options) { - $.extend(options, {successStatus: 201}); - ajax({ - type: "PUT", url: this.uri, contentType: "application/json", - data: "", processData: false - }, - options, - "The database could not be created" - ); - }, + /** + * Request compaction of the specified database. + * @see docs for /db/_compact + * @param {ajaxSettings} options + * + * jQuery ajax settings + */ + compact: function(options) { + $.extend(options, {successStatus: 202}); + ajax({ + type: "POST", url: this.uri + "_compact", + data: "", processData: false + }, + options, + "The database could not be compacted" + ); + }, - /** - * Deletes the specified database, and all the documents and - * attachments contained within it. - * @see docs for DELETE /db/ - * @param {ajaxSettings} options jQuery ajax settings - */ - drop: function(options) { - ajax( - {type: "DELETE", url: this.uri}, - options, - "The database could not be deleted" - ); - }, + /** + * Cleans up the cached view output on disk for a given view. + * @see docs for /db/_compact + * @param {ajaxSettings} options jQuery ajax settings + */ + viewCleanup: function(options) { + $.extend(options, {successStatus: 202}); + ajax({ + type: "POST", url: this.uri + "_view_cleanup", + data: "", processData: false + }, + options, + "The views could not be cleaned up" + ); + }, - /** - * Gets information about the specified database. - * @see docs for GET /db/ - * @param {ajaxSettings} options jQuery ajax settings - */ - info: function(options) { - ajax( - {url: this.uri}, - options, - "Database information could not be retrieved" - ); - }, + /** + * Compacts the view indexes associated with the specified design + * document. You can use this in place of the full database compaction + * if you know a specific set of view indexes have been affected by a + * recent database change. + * @see docs for /db/_compact/design-doc + * @param {String} groupname Name of design-doc to compact + * @param {ajaxSettings} options jQuery ajax settings + */ + compactView: function(groupname, options) { + $.extend(options, {successStatus: 202}); + ajax({ + type: "POST", url: this.uri + "_compact/" + groupname, + data: "", processData: false + }, + options, + "The view could not be compacted" + ); + }, - /** - * @namespace - * $.couch.db.changes provides an API for subscribing to the changes - * feed - *
var $changes = $.couch.db("mydatabase").changes();
-         *$changes.onChange = function (data) {
-         *    ... process data ...
-         * }
-         * $changes.stop();
-         * 
- */ - changes: function(since, options) { + /** + * Create a new database + * @see docs for PUT /db/ + * @param {ajaxSettings} options jQuery ajax settings + */ + create: function(options) { + $.extend(options, {successStatus: 201}); + ajax({ + type: "PUT", url: this.uri, contentType: "application/json", + data: "", processData: false + }, + options, + "The database could not be created" + ); + }, - options = options || {}; - // set up the promise object within a closure for this handler - var timeout = 100, db = this, active = true, - listeners = [], - promise = /** @lends $.couch.db.changes */ { - /** - * Add a listener callback - * @see docs for /db/_changes - * @param {Function} fun Callback function to run when - * notified of changes. - */ - onChange : function(fun) { - listeners.push(fun); - }, - /** - * Stop subscribing to the changes feed - */ - stop : function() { - active = false; - } - }; - // call each listener when there is a change - function triggerListeners(resp) { - $.each(listeners, function() { - this(resp); - }); - }; - // when there is a change, call any listeners, then check for - // another change - options.success = function(resp) { - timeout = 100; - if (active) { - since = resp.last_seq; - triggerListeners(resp); - getChangesSince(); - }; - }; - options.error = function() { - if (active) { - setTimeout(getChangesSince, timeout); - timeout = timeout * 2; - } - }; - // actually make the changes request - function getChangesSince() { - var opts = $.extend({heartbeat : 10 * 1000}, options, { - feed : "longpoll", - since : since - }); + /** + * Deletes the specified database, and all the documents and + * attachments contained within it. + * @see docs for DELETE /db/ + * @param {ajaxSettings} options jQuery ajax settings + */ + drop: function(options) { ajax( - {url: db.uri + "_changes"+encodeOptions(opts)}, + {type: "DELETE", url: this.uri}, options, - "Error connecting to "+db.uri+"/_changes." + "The database could not be deleted" ); - } - // start the first request - if (since) { - getChangesSince(); - } else { - db.info({ - success : function(info) { - since = info.update_seq; + }, + + /** + * Gets information about the specified database. + * @see docs for GET /db/ + * @param {ajaxSettings} options jQuery ajax settings + */ + info: function(options) { + ajax( + {url: this.uri}, + options, + "Database information could not be retrieved" + ); + }, + + /** + * @namespace + * $.couch.db.changes provides an API for subscribing to the changes + * feed + *
var $changes = $.couch.db("mydatabase").changes();
+           *$changes.onChange = function (data) {
+           *    ... process data ...
+           * }
+           * $changes.stop();
+           * 
+ */ + changes: function(since, options) { + + options = options || {}; + // set up the promise object within a closure for this handler + var timeout = 100, db = this, active = true, + listeners = [], + promise = /** @lends $.couch.db.changes */ { + /** + * Add a listener callback + * @see docs for /db/_changes + * @param {Function} fun Callback function to run when + * notified of changes. + */ + onChange : function(fun) { + listeners.push(fun); + }, + /** + * Stop subscribing to the changes feed + */ + stop : function() { + active = false; + } + }; + // call each listener when there is a change + function triggerListeners(resp) { + $.each(listeners, function() { + this(resp); + }); + }; + // when there is a change, call any listeners, then check for + // another change + options.success = function(resp) { + timeout = 100; + if (active) { + since = resp.last_seq; + triggerListeners(resp); getChangesSince(); + }; + }; + options.error = function() { + if (active) { + setTimeout(getChangesSince, timeout); + timeout = timeout * 2; } - }); - } - return promise; - }, + }; + // actually make the changes request + function getChangesSince() { + var opts = $.extend({heartbeat : 10 * 1000}, options, { + feed : "longpoll", + since : since + }); + ajax( + {url: db.uri + "_changes"+encodeOptions(opts)}, + options, + "Error connecting to "+db.uri+"/_changes." + ); + } + // start the first request + if (since) { + getChangesSince(); + } else { + db.info({ + success : function(info) { + since = info.update_seq; + getChangesSince(); + } + }); + } + return promise; + }, - /** - * Fetch all the docs in this db, you can specify an array of keys to - * fetch by passing the keys field in the - * options - * parameter. - * @see docs for /db/all_docs/ - * @param {ajaxSettings} options jQuery ajax settings - */ - allDocs: function(options) { - var type = "GET"; - var data = null; - if (options["keys"]) { - type = "POST"; - var keys = options["keys"]; - delete options["keys"]; - data = toJSON({ "keys": keys }); - } - ajax({ - type: type, - data: data, - url: this.uri + "_all_docs" + encodeOptions(options) - }, - options, - "An error occurred retrieving a list of all documents" - ); - }, + /** + * Fetch all the docs in this db, you can specify an array of keys to + * fetch by passing the keys field in the + * options + * parameter. + * @see docs for /db/all_docs/ + * @param {ajaxSettings} options jQuery ajax settings + */ + allDocs: function(options) { + var type = "GET"; + var data = null; + if (options["keys"]) { + type = "POST"; + var keys = options["keys"]; + delete options["keys"]; + data = toJSON({ "keys": keys }); + } + ajax({ + type: type, + data: data, + url: this.uri + "_all_docs" + encodeOptions(options) + }, + options, + "An error occurred retrieving a list of all documents" + ); + }, - /** - * Fetch all the design docs in this db - * @param {ajaxSettings} options jQuery ajax settings - */ - allDesignDocs: function(options) { - this.allDocs($.extend( - {startkey:"_design", endkey:"_design0"}, options)); - }, + /** + * Fetch all the design docs in this db + * @param {ajaxSettings} options jQuery ajax settings + */ + allDesignDocs: function(options) { + this.allDocs($.extend( + {startkey:"_design", endkey:"_design0"}, options)); + }, - /** - * Fetch all the design docs with an index.html, options - * parameter expects an eachApp field which is a callback - * called on each app found. - * @param {ajaxSettings} options jQuery ajax settings - */ - allApps: function(options) { - options = options || {}; - var self = this; - if (options.eachApp) { - this.allDesignDocs({ - success: function(resp) { - $.each(resp.rows, function() { - self.openDoc(this.id, { - success: function(ddoc) { - var index, appPath, appName = ddoc._id.split('/'); - appName.shift(); - appName = appName.join('/'); - index = ddoc.couchapp && ddoc.couchapp.index; - if (index) { - appPath = ['', name, ddoc._id, index].join('/'); - } else if (ddoc._attachments && - ddoc._attachments["index.html"]) { - appPath = ['', name, ddoc._id, "index.html"].join('/'); + /** + * Fetch all the design docs with an index.html, options + * parameter expects an eachApp field which is a callback + * called on each app found. + * @param {ajaxSettings} options jQuery ajax settings + */ + allApps: function(options) { + options = options || {}; + var self = this; + if (options.eachApp) { + this.allDesignDocs({ + success: function(resp) { + $.each(resp.rows, function() { + self.openDoc(this.id, { + success: function(ddoc) { + var index, appPath, appName = ddoc._id.split('/'); + appName.shift(); + appName = appName.join('/'); + index = ddoc.couchapp && ddoc.couchapp.index; + if (index) { + appPath = ['', name, ddoc._id, index].join('/'); + } else if (ddoc._attachments && + ddoc._attachments["index.html"]) { + appPath = ['', name, ddoc._id, "index.html"].join('/'); + } + if (appPath) options.eachApp(appName, appPath, ddoc); } - if (appPath) options.eachApp(appName, appPath, ddoc); - } + }); }); - }); - } - }); - } else { - throw 'Please provide an eachApp function for allApps()'; - } - }, + } + }); + } else { + throw 'Please provide an eachApp function for allApps()'; + } + }, - /** - * Returns the specified doc from the specified db. - * @see docs for GET /db/doc - * @param {String} docId id of document to fetch - * @param {ajaxSettings} options jQuery ajax settings - * @param {ajaxSettings} ajaxOptions jQuery ajax settings - */ - openDoc: function(docId, options, ajaxOptions) { - options = options || {}; - if (db_opts.attachPrevRev || options.attachPrevRev) { - $.extend(options, { - beforeSuccess : function(req, doc) { - rawDocs[doc._id] = { - rev : doc._rev, - raw : req.responseText - }; - } - }); - } else { - $.extend(options, { - beforeSuccess : function(req, doc) { - if (doc["jquery.couch.attachPrevRev"]) { + /** + * Returns the specified doc from the specified db. + * @see docs for GET /db/doc + * @param {String} docId id of document to fetch + * @param {ajaxSettings} options jQuery ajax settings + * @param {ajaxSettings} ajaxOptions jQuery ajax settings + */ + openDoc: function(docId, options, ajaxOptions) { + options = options || {}; + if (db_opts.attachPrevRev || options.attachPrevRev) { + $.extend(options, { + beforeSuccess : function(req, doc) { rawDocs[doc._id] = { rev : doc._rev, raw : req.responseText }; } - } - }); - } - ajax({url: this.uri + encodeDocId(docId) + encodeOptions(options)}, - options, - "The document could not be retrieved", - ajaxOptions - ); - }, + }); + } else { + $.extend(options, { + beforeSuccess : function(req, doc) { + if (doc["jquery.couch.attachPrevRev"]) { + rawDocs[doc._id] = { + rev : doc._rev, + raw : req.responseText + }; + } + } + }); + } + ajax({url: this.uri + encodeDocId(docId) + encodeOptions(options)}, + options, + "The document could not be retrieved", + ajaxOptions + ); + }, - /** - * Create a new document in the specified database, using the supplied - * JSON document structure. If the JSON structure includes the _id - * field, then the document will be created with the specified document - * ID. If the _id field is not specified, a new unique ID will be - * generated. - * @see docs for GET /db/doc - * @param {String} doc document to save - * @param {ajaxSettings} options jQuery ajax settings - */ - saveDoc: function(doc, options) { - options = options || {}; - var db = this; - var beforeSend = fullCommit(options); - if (doc._id === undefined) { - var method = "POST"; - var uri = this.uri; - } else { - var method = "PUT"; - var uri = this.uri + encodeDocId(doc._id); - } - var versioned = maybeApplyVersion(doc); - $.ajax({ - type: method, url: uri + encodeOptions(options), - contentType: "application/json", - dataType: "json", data: toJSON(doc), - beforeSend : beforeSend, - complete: function(req) { - var resp = $.parseJSON(req.responseText); - if (req.status == 200 || req.status == 201 || req.status == 202) { - doc._id = resp.id; - doc._rev = resp.rev; - if (versioned) { - db.openDoc(doc._id, { - attachPrevRev : true, - success : function(d) { - doc._attachments = d._attachments; - if (options.success) options.success(resp); - } - }); + /** + * Create a new document in the specified database, using the supplied + * JSON document structure. If the JSON structure includes the _id + * field, then the document will be created with the specified document + * ID. If the _id field is not specified, a new unique ID will be + * generated. + * @see docs for GET /db/doc + * @param {String} doc document to save + * @param {ajaxSettings} options jQuery ajax settings + */ + saveDoc: function(doc, options) { + options = options || {}; + var db = this; + var beforeSend = fullCommit(options); + if (doc._id === undefined) { + var method = "POST"; + var uri = this.uri; + } else { + var method = "PUT"; + var uri = this.uri + encodeDocId(doc._id); + } + var versioned = maybeApplyVersion(doc); + $.ajax({ + type: method, url: uri + encodeOptions(options), + contentType: "application/json", + dataType: "json", data: toJSON(doc), + beforeSend : beforeSend, + complete: function(req) { + var resp = $.parseJSON(req.responseText); + if (req.status == 200 || req.status == 201 || req.status == 202) { + doc._id = resp.id; + doc._rev = resp.rev; + if (versioned) { + db.openDoc(doc._id, { + attachPrevRev : true, + success : function(d) { + doc._attachments = d._attachments; + if (options.success) options.success(resp); + } + }); + } else { + if (options.success) options.success(resp); + } + } else if (options.error) { + options.error(req.status, resp.error, resp.reason); } else { - if (options.success) options.success(resp); + throw "The document could not be saved: " + resp.reason; } - } else if (options.error) { - options.error(req.status, resp.error, resp.reason); - } else { - throw "The document could not be saved: " + resp.reason; } - } - }); - }, + }); + }, - /** - * Save a list of documents - * @see docs for /db/_bulk_docs - * @param {Object[]} docs List of documents to save - * @param {ajaxSettings} options jQuery ajax settings - */ - bulkSave: function(docs, options) { - var beforeSend = fullCommit(options); - $.extend(options, {successStatus: 201, beforeSend : beforeSend}); - ajax({ - type: "POST", - url: this.uri + "_bulk_docs" + encodeOptions(options), - contentType: "application/json", data: toJSON(docs) - }, - options, - "The documents could not be saved" - ); - }, + /** + * Save a list of documents + * @see docs for /db/_bulk_docs + * @param {Object[]} docs List of documents to save + * @param {ajaxSettings} options jQuery ajax settings + */ + bulkSave: function(docs, options) { + var beforeSend = fullCommit(options); + $.extend(options, {successStatus: 201, beforeSend : beforeSend}); + ajax({ + type: "POST", + url: this.uri + "_bulk_docs" + encodeOptions(options), + contentType: "application/json", data: toJSON(docs) + }, + options, + "The documents could not be saved" + ); + }, - /** - * Deletes the specified document from the database. You must supply - * the current (latest) revision and id of the document - * to delete eg removeDoc({_id:"mydoc", _rev: "1-2345"}) - * @see docs for DELETE /db/doc - * @param {Object} doc Document to delete - * @param {ajaxSettings} options jQuery ajax settings - */ - removeDoc: function(doc, options) { - ajax({ - type: "DELETE", - url: this.uri + - encodeDocId(doc._id) + - encodeOptions({rev: doc._rev}) - }, - options, - "The document could not be deleted" - ); - }, + /** + * Deletes the specified document from the database. You must supply + * the current (latest) revision and id of the document + * to delete eg removeDoc({_id:"mydoc", _rev: "1-2345"}) + * @see docs for DELETE /db/doc + * @param {Object} doc Document to delete + * @param {ajaxSettings} options jQuery ajax settings + */ + removeDoc: function(doc, options) { + ajax({ + type: "DELETE", + url: this.uri + + encodeDocId(doc._id) + + encodeOptions({rev: doc._rev}) + }, + options, + "The document could not be deleted" + ); + }, - /** - * Remove a set of documents - * @see docs for /db/_bulk_docs - * @param {String[]} docs List of document id's to remove - * @param {ajaxSettings} options jQuery ajax settings - */ - bulkRemove: function(docs, options){ - docs.docs = $.each( - docs.docs, function(i, doc){ - doc._deleted = true; - } - ); - $.extend(options, {successStatus: 201}); - ajax({ - type: "POST", - url: this.uri + "_bulk_docs" + encodeOptions(options), - data: toJSON(docs) - }, - options, - "The documents could not be deleted" - ); - }, + /** + * Remove a set of documents + * @see docs for /db/_bulk_docs + * @param {String[]} docs List of document id's to remove + * @param {ajaxSettings} options jQuery ajax settings + */ + bulkRemove: function(docs, options){ + docs.docs = $.each( + docs.docs, function(i, doc){ + doc._deleted = true; + } + ); + $.extend(options, {successStatus: 201}); + ajax({ + type: "POST", + url: this.uri + "_bulk_docs" + encodeOptions(options), + data: toJSON(docs) + }, + options, + "The documents could not be deleted" + ); + }, - /** - * The COPY command (which is non-standard HTTP) copies an existing - * document to a new or existing document. - * @see docs for COPY /db/doc - * @param {String[]} docId document id to copy - * @param {ajaxSettings} options jQuery ajax settings - * @param {ajaxSettings} options jQuery ajax settings - */ - copyDoc: function(docId, options, ajaxOptions) { - ajaxOptions = $.extend(ajaxOptions, { - complete: function(req) { - var resp = $.parseJSON(req.responseText); - if (req.status == 201) { - if (options.success) options.success(resp); - } else if (options.error) { - options.error(req.status, resp.error, resp.reason); - } else { - throw "The document could not be copied: " + resp.reason; + /** + * The COPY command (which is non-standard HTTP) copies an existing + * document to a new or existing document. + * @see docs for COPY /db/doc + * @param {String[]} docId document id to copy + * @param {ajaxSettings} options jQuery ajax settings + * @param {ajaxSettings} options jQuery ajax settings + */ + copyDoc: function(docId, options, ajaxOptions) { + ajaxOptions = $.extend(ajaxOptions, { + complete: function(req) { + var resp = $.parseJSON(req.responseText); + if (req.status == 201) { + if (options.success) options.success(resp); + } else if (options.error) { + options.error(req.status, resp.error, resp.reason); + } else { + throw "The document could not be copied: " + resp.reason; + } } + }); + ajax({ + type: "COPY", + url: this.uri + encodeDocId(docId) + }, + options, + "The document could not be copied", + ajaxOptions + ); + }, + + /** + * Creates (and executes) a temporary view based on the view function + * supplied in the JSON request. + * @see docs for /db/_temp_view + * @param {Function} mapFun Map function + * @param {Function} reduceFun Reduce function + * @param {Function} language Language the map / reduce funs are + * implemented in + * @param {ajaxSettings} options jQuery ajax settings + */ + query: function(mapFun, reduceFun, language, options) { + language = language || "javascript"; + if (typeof(mapFun) !== "string") { + mapFun = mapFun.toSource ? mapFun.toSource() + : "(" + mapFun.toString() + ")"; } - }); - ajax({ - type: "COPY", - url: this.uri + encodeDocId(docId) - }, - options, - "The document could not be copied", - ajaxOptions - ); - }, + var body = {language: language, map: mapFun}; + if (reduceFun != null) { + if (typeof(reduceFun) !== "string") + reduceFun = reduceFun.toSource ? reduceFun.toSource() + : "(" + reduceFun.toString() + ")"; + body.reduce = reduceFun; + } + ajax({ + type: "POST", + url: this.uri + "_temp_view" + encodeOptions(options), + contentType: "application/json", data: toJSON(body) + }, + options, + "An error occurred querying the database" + ); + }, - /** - * Creates (and executes) a temporary view based on the view function - * supplied in the JSON request. - * @see docs for /db/_temp_view - * @param {Function} mapFun Map function - * @param {Function} reduceFun Reduce function - * @param {Function} language Language the map / reduce funs are - * implemented in - * @param {ajaxSettings} options jQuery ajax settings - */ - query: function(mapFun, reduceFun, language, options) { - language = language || "javascript"; - if (typeof(mapFun) !== "string") { - mapFun = mapFun.toSource ? mapFun.toSource() - : "(" + mapFun.toString() + ")"; - } - var body = {language: language, map: mapFun}; - if (reduceFun != null) { - if (typeof(reduceFun) !== "string") - reduceFun = reduceFun.toSource ? reduceFun.toSource() - : "(" + reduceFun.toString() + ")"; - body.reduce = reduceFun; - } - ajax({ - type: "POST", - url: this.uri + "_temp_view" + encodeOptions(options), - contentType: "application/json", data: toJSON(body) - }, - options, - "An error occurred querying the database" - ); - }, + /** + * Fetch a _list view output, you can specify a list of + * keys in the options object to recieve only those keys. + * @see + * docs for /db/_design/design-doc/_list/l1/v1 + * @param {String} list Listname in the form of ddoc/listname + * @param {String} view View to run list against + * @param {options} CouchDB View Options + * @param {ajaxSettings} options jQuery ajax settings + */ + list: function(list, view, options, ajaxOptions) { + var list = list.split('/'); + var options = options || {}; + var type = 'GET'; + var data = null; + if (options['keys']) { + type = 'POST'; + var keys = options['keys']; + delete options['keys']; + data = toJSON({'keys': keys }); + } + ajax({ + type: type, + data: data, + url: this.uri + '_design/' + list[0] + + '/_list/' + list[1] + '/' + view + encodeOptions(options) + }, + ajaxOptions, 'An error occured accessing the list' + ); + }, - /** - * Fetch a _list view output, you can specify a list of - * keys in the options object to recieve only those keys. - * @see - * docs for /db/_design/design-doc/_list/l1/v1 - * @param {String} list Listname in the form of ddoc/listname - * @param {String} view View to run list against - * @param {options} CouchDB View Options - * @param {ajaxSettings} options jQuery ajax settings - */ - list: function(list, view, options, ajaxOptions) { - var list = list.split('/'); - var options = options || {}; - var type = 'GET'; - var data = null; - if (options['keys']) { - type = 'POST'; - var keys = options['keys']; - delete options['keys']; - data = toJSON({'keys': keys }); - } - ajax({ - type: type, - data: data, - url: this.uri + '_design/' + list[0] + - '/_list/' + list[1] + '/' + view + encodeOptions(options) + /** + * Executes the specified view-name from the specified design-doc + * design document, you can specify a list of keys + * in the options object to recieve only those keys. + * @see docs for /db/ + * _design/design-doc/_list/l1/v1 + * @param {String} name View to run list against (string should have + * the design-doc name followed by a slash and the view name) + * @param {ajaxSettings} options jQuery ajax settings + */ + view: function(name, options) { + var name = name.split('/'); + var options = options || {}; + var type = "GET"; + var data= null; + if (options["keys"]) { + type = "POST"; + var keys = options["keys"]; + delete options["keys"]; + data = toJSON({ "keys": keys }); + } + ajax({ + type: type, + data: data, + url: this.uri + "_design/" + name[0] + + "/_view/" + name[1] + encodeOptions(options) }, - ajaxOptions, 'An error occured accessing the list' - ); - }, + options, "An error occurred accessing the view" + ); + }, - /** - * Executes the specified view-name from the specified design-doc - * design document, you can specify a list of keys - * in the options object to recieve only those keys. - * @see docs for /db/ - * _design/design-doc/_list/l1/v1 - * @param {String} name View to run list against (string should have - * the design-doc name followed by a slash and the view name) - * @param {ajaxSettings} options jQuery ajax settings - */ - view: function(name, options) { - var name = name.split('/'); - var options = options || {}; - var type = "GET"; - var data= null; - if (options["keys"]) { - type = "POST"; - var keys = options["keys"]; - delete options["keys"]; - data = toJSON({ "keys": keys }); - } - ajax({ - type: type, - data: data, - url: this.uri + "_design/" + name[0] + - "/_view/" + name[1] + encodeOptions(options) + /** + * Fetch an arbitrary CouchDB database property + * @see docs for /db/_prop + * @param {String} propName Propery name to fetch + * @param {ajaxSettings} options jQuery ajax settings + * @param {ajaxSettings} ajaxOptions jQuery ajax settings + */ + getDbProperty: function(propName, options, ajaxOptions) { + ajax({url: this.uri + propName + encodeOptions(options)}, + options, + "The property could not be retrieved", + ajaxOptions + ); + }, + + /** + * Set an arbitrary CouchDB database property + * @see docs for /db/_prop + * @param {String} propName Propery name to fetch + * @param {String} propValue Propery value to set + * @param {ajaxSettings} options jQuery ajax settings + * @param {ajaxSettings} ajaxOptions jQuery ajax settings + */ + setDbProperty: function(propName, propValue, options, ajaxOptions) { + ajax({ + type: "PUT", + url: this.uri + propName + encodeOptions(options), + data : JSON.stringify(propValue) }, - options, "An error occurred accessing the view" - ); - }, + options, + "The property could not be updated", + ajaxOptions + ); + } + }; + }, - /** - * Fetch an arbitrary CouchDB database property - * @see docs for /db/_prop - * @param {String} propName Propery name to fetch - * @param {ajaxSettings} options jQuery ajax settings - * @param {ajaxSettings} ajaxOptions jQuery ajax settings - */ - getDbProperty: function(propName, options, ajaxOptions) { - ajax({url: this.uri + propName + encodeOptions(options)}, - options, - "The property could not be retrieved", - ajaxOptions - ); - }, + encodeDocId: encodeDocId, - /** - * Set an arbitrary CouchDB database property - * @see docs for /db/_prop - * @param {String} propName Propery name to fetch - * @param {String} propValue Propery value to set - * @param {ajaxSettings} options jQuery ajax settings - * @param {ajaxSettings} ajaxOptions jQuery ajax settings - */ - setDbProperty: function(propName, propValue, options, ajaxOptions) { - ajax({ - type: "PUT", - url: this.uri + propName + encodeOptions(options), - data : JSON.stringify(propValue) + /** + * Accessing the root of a CouchDB instance returns meta information about + * the instance. The response is a JSON structure containing information + * about the server, including a welcome message and the version of the + * server. + * @see + * docs for GET / + * @param {ajaxSettings} options jQuery ajax settings + */ + info: function(options) { + ajax( + {url: this.urlPrefix + "/"}, + options, + "Server information could not be retrieved" + ); + }, + + /** + * Request, configure, or stop, a replication operation. + * @see docs for POST /_replicate + * @param {String} source Path or url to source database + * @param {String} target Path or url to target database + * @param {ajaxSettings} ajaxOptions jQuery ajax settings + * @param {Object} repOpts Additional replication options + */ + replicate: function(source, target, ajaxOptions, repOpts) { + repOpts = $.extend({source: source, target: target}, repOpts); + if (repOpts.continuous && !repOpts.cancel) { + ajaxOptions.successStatus = 202; + } + ajax({ + type: "POST", url: this.urlPrefix + "/_replicate", + data: JSON.stringify(repOpts), + contentType: "application/json" }, - options, - "The property could not be updated", - ajaxOptions + ajaxOptions, + "Replication failed" + ); + }, + + /** + * Fetch a new UUID + * @see docs for /_uuids + * @param {Int} cacheNum Number of uuids to keep cached for future use + */ + newUUID: function(cacheNum) { + if (cacheNum === undefined) { + cacheNum = 1; + } + if (!uuidCache.length) { + ajax({url: this.urlPrefix + "/_uuids", data: {count: cacheNum}, async: + false}, { + success: function(resp) { + uuidCache = resp.uuids; + } + }, + "Failed to retrieve UUID batch." ); } - }; - }, - - encodeDocId: encodeDocId, + return uuidCache.shift(); + } + }); /** - * Accessing the root of a CouchDB instance returns meta information about - * the instance. The response is a JSON structure containing information - * about the server, including a welcome message and the version of the - * server. - * @see - * docs for GET / - * @param {ajaxSettings} options jQuery ajax settings + * @private */ - info: function(options) { - ajax( - {url: this.urlPrefix + "/"}, - options, - "Server information could not be retrieved" - ); - }, + function ajax(obj, options, errorMessage, ajaxOptions) { + var timeStart; + var defaultAjaxOpts = { + contentType: "application/json", + headers:{"Accept": "application/json"} + }; - /** - * Request, configure, or stop, a replication operation. - * @see docs for POST /_replicate - * @param {String} source Path or url to source database - * @param {String} target Path or url to target database - * @param {ajaxSettings} ajaxOptions jQuery ajax settings - * @param {Object} repOpts Additional replication options - */ - replicate: function(source, target, ajaxOptions, repOpts) { - repOpts = $.extend({source: source, target: target}, repOpts); - if (repOpts.continuous && !repOpts.cancel) { - ajaxOptions.successStatus = 202; - } - ajax({ - type: "POST", url: this.urlPrefix + "/_replicate", - data: JSON.stringify(repOpts), - contentType: "application/json" + options = $.extend({successStatus: 200}, options); + ajaxOptions = $.extend(defaultAjaxOpts, ajaxOptions); + errorMessage = errorMessage || "Unknown error"; + timeStart = (new Date()).getTime(); + $.ajax($.extend($.extend({ + type: "GET", dataType: "json", cache : !$.browser.msie, + beforeSend: function(xhr){ + if(ajaxOptions && ajaxOptions.headers){ + for (var header in ajaxOptions.headers){ + xhr.setRequestHeader(header, ajaxOptions.headers[header]); + } + } }, - ajaxOptions, - "Replication failed" - ); - }, + complete: function(req) { + var reqDuration = (new Date()).getTime() - timeStart; + try { + var resp = $.parseJSON(req.responseText); + } catch(e) { + if (options.error) { + options.error(req.status, req, e); + } else { + throw errorMessage + ': ' + e; + } + return; + } + if (options.ajaxStart) { + options.ajaxStart(resp); + } + if (req.status == options.successStatus) { + if (options.beforeSuccess) options.beforeSuccess(req, resp, reqDuration); + if (options.success) options.success(resp, reqDuration); + } else if (options.error) { + options.error(req.status, resp && resp.error || + errorMessage, resp && resp.reason || "no response", + reqDuration); + } else { + throw errorMessage + ": " + resp.reason; + } + } + }, obj), ajaxOptions)); + } /** - * Fetch a new UUID - * @see docs for /_uuids - * @param {Int} cacheNum Number of uuids to keep cached for future use + * @private */ - newUUID: function(cacheNum) { - if (cacheNum === undefined) { - cacheNum = 1; + function fullCommit(options) { + var options = options || {}; + if (typeof options.ensure_full_commit !== "undefined") { + var commit = options.ensure_full_commit; + delete options.ensure_full_commit; + return function(xhr) { + xhr.setRequestHeader('Accept', 'application/json'); + xhr.setRequestHeader("X-Couch-Full-Commit", commit.toString()); + }; } - if (!uuidCache.length) { - ajax({url: this.urlPrefix + "/_uuids", data: {count: cacheNum}, async: - false}, { - success: function(resp) { - uuidCache = resp.uuids; - } - }, - "Failed to retrieve UUID batch." - ); - } - return uuidCache.shift(); - } - }); - - /** - * @private - */ - function ajax(obj, options, errorMessage, ajaxOptions) { - var timeStart; - var defaultAjaxOpts = { - contentType: "application/json", - headers:{"Accept": "application/json"} }; - options = $.extend({successStatus: 200}, options); - ajaxOptions = $.extend(defaultAjaxOpts, ajaxOptions); - errorMessage = errorMessage || "Unknown error"; - timeStart = (new Date()).getTime(); - $.ajax($.extend($.extend({ - type: "GET", dataType: "json", cache : !$.browser.msie, - beforeSend: function(xhr){ - if(ajaxOptions && ajaxOptions.headers){ - for (var header in ajaxOptions.headers){ - xhr.setRequestHeader(header, ajaxOptions.headers[header]); - } - } - }, - complete: function(req) { - var reqDuration = (new Date()).getTime() - timeStart; - try { - var resp = $.parseJSON(req.responseText); - } catch(e) { - if (options.error) { - options.error(req.status, req, e); - } else { - throw errorMessage + ': ' + e; + /** + * @private + */ + // Convert a options object to an url query string. + // ex: {key:'value',key2:'value2'} becomes '?key="value"&key2="value2"' + function encodeOptions(options) { + var buf = []; + if (typeof(options) === "object" && options !== null) { + for (var name in options) { + if ($.inArray(name, + ["error", "success", "beforeSuccess", "ajaxStart"]) >= 0) + continue; + var value = options[name]; + if ($.inArray(name, ["key", "startkey", "endkey"]) >= 0) { + value = toJSON(value); } - return; - } - if (options.ajaxStart) { - options.ajaxStart(resp); - } - if (req.status == options.successStatus) { - if (options.beforeSuccess) options.beforeSuccess(req, resp, reqDuration); - if (options.success) options.success(resp, reqDuration); - } else if (options.error) { - options.error(req.status, resp && resp.error || - errorMessage, resp && resp.reason || "no response", - reqDuration); - } else { - throw errorMessage + ": " + resp.reason; + buf.push(encodeURIComponent(name) + "=" + encodeURIComponent(value)); } } - }, obj), ajaxOptions)); - } - - /** - * @private - */ - function fullCommit(options) { - var options = options || {}; - if (typeof options.ensure_full_commit !== "undefined") { - var commit = options.ensure_full_commit; - delete options.ensure_full_commit; - return function(xhr) { - xhr.setRequestHeader('Accept', 'application/json'); - xhr.setRequestHeader("X-Couch-Full-Commit", commit.toString()); - }; + return buf.length ? "?" + buf.join("&") : ""; } - }; - /** - * @private - */ - // Convert a options object to an url query string. - // ex: {key:'value',key2:'value2'} becomes '?key="value"&key2="value2"' - function encodeOptions(options) { - var buf = []; - if (typeof(options) === "object" && options !== null) { - for (var name in options) { - if ($.inArray(name, - ["error", "success", "beforeSuccess", "ajaxStart"]) >= 0) - continue; - var value = options[name]; - if ($.inArray(name, ["key", "startkey", "endkey"]) >= 0) { - value = toJSON(value); - } - buf.push(encodeURIComponent(name) + "=" + encodeURIComponent(value)); - } + /** + * @private + */ + function toJSON(obj) { + return obj !== null ? JSON.stringify(obj) : null; } - return buf.length ? "?" + buf.join("&") : ""; - } - /** - * @private - */ - function toJSON(obj) { - return obj !== null ? JSON.stringify(obj) : null; - } + })(jQuery); -})(jQuery); +}); \ No newline at end of file diff --git a/assets/js/lib/jquery.mb.browser.js b/assets/js/lib/jquery.mb.browser.js index 16d2ff0..4f4552b 100755 --- a/assets/js/lib/jquery.mb.browser.js +++ b/assets/js/lib/jquery.mb.browser.js @@ -6,9 +6,9 @@ * Copyright (c) 2001-2014. Matteo Bicocchi (Pupunzi); * Open lab srl, Firenze - Italy * email: matteo@open-lab.com - * site: http://pupunzi.com - * blog: http://pupunzi.open-lab.com - * http://open-lab.com + * site: http://pupunzi.com + * blog: http://pupunzi.open-lab.com + * http://open-lab.com * * Licences: MIT, GPL * http://www.opensource.org/licenses/mit-license.php @@ -18,4 +18,14 @@ * ***************************************************************************** */ +/** + * Modified in SourceJS to use custom `define` namespace and local jquery + */ + +sourcejs.amd.define([ + 'jquery' +], function(jQuery) { + var nAgt=navigator.userAgent;if(!jQuery.browser){jQuery.browser={},jQuery.browser.mozilla=!1,jQuery.browser.webkit=!1,jQuery.browser.opera=!1,jQuery.browser.safari=!1,jQuery.browser.chrome=!1,jQuery.browser.msie=!1,jQuery.browser.ua=nAgt,jQuery.browser.name=navigator.appName,jQuery.browser.fullVersion=""+parseFloat(navigator.appVersion),jQuery.browser.majorVersion=parseInt(navigator.appVersion,10);var nameOffset,verOffset,ix;if(-1!=(verOffset=nAgt.indexOf("Opera")))jQuery.browser.opera=!0,jQuery.browser.name="Opera",jQuery.browser.fullVersion=nAgt.substring(verOffset+6),-1!=(verOffset=nAgt.indexOf("Version"))&&(jQuery.browser.fullVersion=nAgt.substring(verOffset+8));else if(-1!=(verOffset=nAgt.indexOf("OPR")))jQuery.browser.opera=!0,jQuery.browser.name="Opera",jQuery.browser.fullVersion=nAgt.substring(verOffset+4);else if(-1!=(verOffset=nAgt.indexOf("MSIE")))jQuery.browser.msie=!0,jQuery.browser.name="Microsoft Internet Explorer",jQuery.browser.fullVersion=nAgt.substring(verOffset+5);else if(-1!=nAgt.indexOf("Trident")){jQuery.browser.msie=!0,jQuery.browser.name="Microsoft Internet Explorer";var start=nAgt.indexOf("rv:")+3,end=start+4;jQuery.browser.fullVersion=nAgt.substring(start,end)}else-1!=(verOffset=nAgt.indexOf("Chrome"))?(jQuery.browser.webkit=!0,jQuery.browser.chrome=!0,jQuery.browser.name="Chrome",jQuery.browser.fullVersion=nAgt.substring(verOffset+7)):-1!=(verOffset=nAgt.indexOf("Safari"))?(jQuery.browser.webkit=!0,jQuery.browser.safari=!0,jQuery.browser.name="Safari",jQuery.browser.fullVersion=nAgt.substring(verOffset+7),-1!=(verOffset=nAgt.indexOf("Version"))&&(jQuery.browser.fullVersion=nAgt.substring(verOffset+8))):-1!=(verOffset=nAgt.indexOf("AppleWebkit"))?(jQuery.browser.webkit=!0,jQuery.browser.name="Safari",jQuery.browser.fullVersion=nAgt.substring(verOffset+7),-1!=(verOffset=nAgt.indexOf("Version"))&&(jQuery.browser.fullVersion=nAgt.substring(verOffset+8))):-1!=(verOffset=nAgt.indexOf("Firefox"))?(jQuery.browser.mozilla=!0,jQuery.browser.name="Firefox",jQuery.browser.fullVersion=nAgt.substring(verOffset+8)):(nameOffset=nAgt.lastIndexOf(" ")+1)<(verOffset=nAgt.lastIndexOf("/"))&&(jQuery.browser.name=nAgt.substring(nameOffset,verOffset),jQuery.browser.fullVersion=nAgt.substring(verOffset+1),jQuery.browser.name.toLowerCase()==jQuery.browser.name.toUpperCase()&&(jQuery.browser.name=navigator.appName));-1!=(ix=jQuery.browser.fullVersion.indexOf(";"))&&(jQuery.browser.fullVersion=jQuery.browser.fullVersion.substring(0,ix)),-1!=(ix=jQuery.browser.fullVersion.indexOf(" "))&&(jQuery.browser.fullVersion=jQuery.browser.fullVersion.substring(0,ix)),jQuery.browser.majorVersion=parseInt(""+jQuery.browser.fullVersion,10),isNaN(jQuery.browser.majorVersion)&&(jQuery.browser.fullVersion=""+parseFloat(navigator.appVersion),jQuery.browser.majorVersion=parseInt(navigator.appVersion,10)),jQuery.browser.version=jQuery.browser.majorVersion}jQuery.browser.android=/Android/i.test(nAgt),jQuery.browser.blackberry=/BlackBerry|BB|PlayBook/i.test(nAgt),jQuery.browser.ios=/iPhone|iPad|iPod|webOS/i.test(nAgt),jQuery.browser.operaMobile=/Opera Mini/i.test(nAgt),jQuery.browser.windowsMobile=/IEMobile|Windows Phone/i.test(nAgt),jQuery.browser.kindle=/Kindle|Silk/i.test(nAgt),jQuery.browser.mobile=jQuery.browser.android||jQuery.browser.blackberry||jQuery.browser.ios||jQuery.browser.windowsMobile||jQuery.browser.operaMobile||jQuery.browser.kindle,jQuery.isMobile=jQuery.browser.mobile,jQuery.isTablet=jQuery.browser.mobile&&jQuery(window).width()>765,jQuery.isAndroidDefault=jQuery.browser.android&&!/chrome/i.test(nAgt); + +}); diff --git a/assets/js/lib/lodash-private.js b/assets/js/lib/lodash-private.js new file mode 100644 index 0000000..15a730c --- /dev/null +++ b/assets/js/lib/lodash-private.js @@ -0,0 +1,3 @@ +sourcejs.amd.define(['lodash'], function (lodash) { + return lodash.noConflict(true); +}); \ No newline at end of file diff --git a/assets/js/lib/modalbox.js b/assets/js/lib/modalbox.js index 913ee55..91ed610 100644 --- a/assets/js/lib/modalbox.js +++ b/assets/js/lib/modalbox.js @@ -1,105 +1,106 @@ -"use strict"; -define([ +sourcejs.amd.define([ 'jquery', 'sourceModules/module', 'sourceLib/lodash' ], function($, module, _) { -var context; // instance of box - -var ModalBox = function(config, data) { - var isNewInstance = !context; - context = context || this; - context.data = data ? data : initialBlocksData; - - if (!isNewInstance) { - context.render(); - return context; - } - - var modulesOptions = context.options.modulesOptions; - modulesOptions.modalBox = $.extend(true, { - "classes": { - "box": [context.options.mainClass, context.options.colMain, "source_modal_box"].join(' '), - "title": "source_modal_title", - "body": "source_modal_body", - "close": "source_modal_close" - }, - "labels": { - "close": "Close extended search results" - }, - "appendTo": ".source_main" - }, modulesOptions.modalBox, config); - - context.init(); -}; - -ModalBox.prototype = module.createInstance(); -ModalBox.prototype.constructor = ModalBox; - -ModalBox.prototype.init = function() { - this.render(); - this.initCloseHandler(); -}; - -ModalBox.prototype.templates = { - box: _.template('
'), - title: _.template('
'), - close: _.template('
'), - body: _.template('
') -}; - -ModalBox.prototype.renderers = {}; - -ModalBox.prototype.renderers.box = function(element) { - $(this.options.modulesOptions.modalBox.appendTo).after(element); -}; - -ModalBox.prototype.renderers.close = function(element) { - $(element).html(this.data.close ? this.data.close : ""); - $(this.box).append(element); -}; - -ModalBox.prototype.renderers.title = function(element) { - $(element).html(this.data.title ? this.data.title : ""); - $(this.box).append(element); -}; - -ModalBox.prototype.renderers.body = function(element) { - $(element).html(this.data.body ? this.data.body : ""); - $(this.box).append(element); -}; - -ModalBox.prototype.render = function() { - var config = this.options.modulesOptions.modalBox; - $.each(context.renderers, function(name, callback) { - var element = context[name] = context[name] - ? context[name] - : $(context.templates[name].call(context, config)); - - callback.call(context, element); - }); -}; - -ModalBox.prototype.initCloseHandler = function() { - $(this.close).on("click", function(e) { - context.hide(); - }); -}; - -ModalBox.prototype.show = function() { - var config = this.options.modulesOptions.modalBox; - $(config.appendTo).hide(); - $(this.box).show(); - return this; -}; - -ModalBox.prototype.hide = function() { - var config = this.options.modulesOptions.modalBox; - $(config.appendTo).show(); - $(this.box).hide(); - return this; -}; - -return ModalBox; -}); \ No newline at end of file + "use strict"; + + var context; // instance of box + + var ModalBox = function(config, data) { + var isNewInstance = !context; + context = context || this; + context.data = data ? data : initialBlocksData; + + if (!isNewInstance) { + context.render(); + return context; + } + + var modulesOptions = context.options.modulesOptions; + modulesOptions.modalBox = $.extend(true, { + "classes": { + "box": [context.options.mainClass, context.options.colMain, "source_modal_box"].join(' '), + "title": "source_modal_title", + "body": "source_modal_body", + "close": "source_modal_close" + }, + "labels": { + "close": "Close extended search results" + }, + "appendTo": ".source_main" + }, modulesOptions.modalBox, config); + + context.init(); + }; + + ModalBox.prototype = module.createInstance(); + ModalBox.prototype.constructor = ModalBox; + + ModalBox.prototype.init = function() { + this.render(); + this.initCloseHandler(); + }; + + ModalBox.prototype.templates = { + box: _.template('
'), + title: _.template('
'), + close: _.template('
'), + body: _.template('
') + }; + + ModalBox.prototype.renderers = {}; + + ModalBox.prototype.renderers.box = function(element) { + $(this.options.modulesOptions.modalBox.appendTo).after(element); + }; + + ModalBox.prototype.renderers.close = function(element) { + $(element).html(this.data.close ? this.data.close : ""); + $(this.box).append(element); + }; + + ModalBox.prototype.renderers.title = function(element) { + $(element).html(this.data.title ? this.data.title : ""); + $(this.box).append(element); + }; + + ModalBox.prototype.renderers.body = function(element) { + $(element).html(this.data.body ? this.data.body : ""); + $(this.box).append(element); + }; + + ModalBox.prototype.render = function() { + var config = this.options.modulesOptions.modalBox; + $.each(context.renderers, function(name, callback) { + var element = context[name] = context[name] + ? context[name] + : $(context.templates[name].call(context, config)); + + callback.call(context, element); + }); + }; + + ModalBox.prototype.initCloseHandler = function() { + $(this.close).on("click", function(e) { + context.hide(); + }); + }; + + ModalBox.prototype.show = function() { + var config = this.options.modulesOptions.modalBox; + $(config.appendTo).hide(); + $(this.box).show(); + return this; + }; + + ModalBox.prototype.hide = function() { + var config = this.options.modulesOptions.modalBox; + $(config.appendTo).show(); + $(this.box).hide(); + return this; + }; + + return ModalBox; +}); diff --git a/assets/js/lib/prism/prism.css b/assets/js/lib/prism/prism.css index 1310e16..9503b2e 100644 --- a/assets/js/lib/prism/prism.css +++ b/assets/js/lib/prism/prism.css @@ -53,8 +53,8 @@ pre[class*="src-"] { pre[class*="src-"] { background: #f1f2f3; border:1px solid #dfe2e4; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } /* Inline code */ diff --git a/assets/js/lib/prism/prism.js b/assets/js/lib/prism/prism.js index 4a1bbe8..8d98a24 100644 --- a/assets/js/lib/prism/prism.js +++ b/assets/js/lib/prism/prism.js @@ -4,501 +4,510 @@ * @author Lea Verou http://lea.verou.me */ -(function(){ +/** + * Modified in SourceJS to use custom `define` namespace and localize Prism global + */ -// Private helper vars - var lang = /\bsrc?-(?!\*)(\w+)\b/i; +sourcejs.amd.define([], function(){ + var Prism; - var _ = self.Prism = { - util: { - type: function (o) { - return Object.prototype.toString.call(o).match(/\[object (\w+)\]/)[1]; - }, + (function(){ - // Deep clone a language definition (e.g. to extend it) - clone: function (o) { - var type = _.util.type(o); + // Private helper vars + var lang = /\bsrc?-(?!\*)(\w+)\b/i; + var _ = Prism = { + util: { + type: function (o) { + return Object.prototype.toString.call(o).match(/\[object (\w+)\]/)[1]; + }, + + // Deep clone a language definition (e.g. to extend it) + clone: function (o) { + var type = _.util.type(o); - switch (type) { - case 'Object': - var clone = {}; + switch (type) { + case 'Object': + var clone = {}; - for (var key in o) { - if (o.hasOwnProperty(key)) { - clone[key] = _.util.clone(o[key]); + for (var key in o) { + if (o.hasOwnProperty(key)) { + clone[key] = _.util.clone(o[key]); + } } - } - return clone; + return clone; - case 'Array': - return o.slice(); - } + case 'Array': + return o.slice(); + } - return o; - } - }, + return o; + } + }, - languages: { - extend: function (id, redef) { - var lang = _.util.clone(_.languages[id]); + languages: { + extend: function (id, redef) { + var lang = _.util.clone(_.languages[id]); - for (var key in redef) { - lang[key] = redef[key]; - } + for (var key in redef) { + lang[key] = redef[key]; + } - return lang; - }, + return lang; + }, - // Insert a token before another token in a language literal - insertBefore: function (inside, before, insert, root) { - root = root || _.languages; - var grammar = root[inside]; - var ret = {}; + // Insert a token before another token in a language literal + insertBefore: function (inside, before, insert, root) { + root = root || _.languages; + var grammar = root[inside]; + var ret = {}; - for (var token in grammar) { + for (var token in grammar) { - if (grammar.hasOwnProperty(token)) { + if (grammar.hasOwnProperty(token)) { - if (token == before) { + if (token == before) { - for (var newToken in insert) { + for (var newToken in insert) { - if (insert.hasOwnProperty(newToken)) { - ret[newToken] = insert[newToken]; + if (insert.hasOwnProperty(newToken)) { + ret[newToken] = insert[newToken]; + } } } + + ret[token] = grammar[token]; } + } + + return root[inside] = ret; + }, + + // Traverse a language definition with Depth First Search + DFS: function(o, callback) { + for (var i in o) { + callback.call(o, i, o[i]); - ret[token] = grammar[token]; + if (_.util.type(o) === 'Object') { + _.languages.DFS(o[i], callback); + } } } + }, + + highlightAll: function(async, callback) { + // var elements = document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'); + var elements = document.querySelectorAll('pre[class*="src"] code'); - return root[inside] = ret; + for (var i=0, element; element = elements[i++];) { + _.highlightElement(element, async === true, callback); + } }, - // Traverse a language definition with Depth First Search - DFS: function(o, callback) { - for (var i in o) { - callback.call(o, i, o[i]); + highlightElement: function(element, async, callback) { + // Find language + var language, grammar, parent = element; - if (_.util.type(o) === 'Object') { - _.languages.DFS(o[i], callback); - } + while (parent && !lang.test(parent.className)) { + parent = parent.parentNode; } - } - }, - highlightAll: function(async, callback) { -// var elements = document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'); - var elements = document.querySelectorAll('pre[class*="src"] code'); + if (parent) { + language = (parent.className.match(lang) || [,''])[1]; + grammar = _.languages[language]; + } - for (var i=0, element; element = elements[i++];) { - _.highlightElement(element, async === true, callback); - } - }, + if (!grammar) { + return; + } - highlightElement: function(element, async, callback) { - // Find language - var language, grammar, parent = element; + // Set language on the element, if not present + // element.className = element.className.replace(lang, '').replace(/\s+/g, ' ') + 'lang-' + language; - while (parent && !lang.test(parent.className)) { - parent = parent.parentNode; - } + // Set language on the parent, for styling + parent = element.parentNode; - if (parent) { - language = (parent.className.match(lang) || [,''])[1]; - grammar = _.languages[language]; - } + if (/pre/i.test(parent.nodeName)) { + parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' src-' + language; + } - if (!grammar) { - return; - } + var code = element.textContent; - // Set language on the element, if not present -// element.className = element.className.replace(lang, '').replace(/\s+/g, ' ') + 'lang-' + language; + if(!code) { + return; + } - // Set language on the parent, for styling - parent = element.parentNode; + code = code.replace(/&/g, '&').replace(/ text.length) { + // Something went terribly wrong, ABORT, ABORT! + break tokenloop; + } - var pattern = grammar[token], - inside = pattern.inside, - lookbehind = !!pattern.lookbehind, - lookbehindLength = 0; + if (str instanceof Token) { + continue; + } - pattern = pattern.pattern || pattern; + pattern.lastIndex = 0; - for (var i=0; i text.length) { - // Something went terribly wrong, ABORT, ABORT! - break tokenloop; - } + var from = match.index - 1 + lookbehindLength, + match = match[0].slice(lookbehindLength), + len = match.length, + to = from + len, + before = str.slice(0, from + 1), + after = str.slice(to + 1); - if (str instanceof Token) { - continue; - } + var args = [i, 1]; + + if (before) { + args.push(before); + } + + var wrapped = new Token(token, inside? _.tokenize(match, inside) : match); - pattern.lastIndex = 0; + args.push(wrapped); - var match = pattern.exec(str); + if (after) { + args.push(after); + } - if (match) { - if(lookbehind) { - lookbehindLength = match[1].length; + Array.prototype.splice.apply(strarr, args); } + } + } - var from = match.index - 1 + lookbehindLength, - match = match[0].slice(lookbehindLength), - len = match.length, - to = from + len, - before = str.slice(0, from + 1), - after = str.slice(to + 1); + return strarr; + }, - var args = [i, 1]; + hooks: { + all: {}, - if (before) { - args.push(before); - } + add: function (name, callback) { + var hooks = _.hooks.all; - var wrapped = new Token(token, inside? _.tokenize(match, inside) : match); + hooks[name] = hooks[name] || []; - args.push(wrapped); + hooks[name].push(callback); + }, - if (after) { - args.push(after); - } + run: function (name, env) { + var callbacks = _.hooks.all[name]; - Array.prototype.splice.apply(strarr, args); + if (!callbacks || !callbacks.length) { + return; + } + + for (var i=0, callback; callback = callbacks[i++];) { + callback(env); } } } + }; - return strarr; - }, + var Token = _.Token = function(type, content) { + this.type = type; + this.content = content; + }; - hooks: { - all: {}, + Token.stringify = function(o, language, parent) { + if (typeof o == 'string') { + return o; + } - add: function (name, callback) { - var hooks = _.hooks.all; + if (Object.prototype.toString.call(o) == '[object Array]') { + return o.map(function(element) { + return Token.stringify(element, language, o); + }).join(''); + } - hooks[name] = hooks[name] || []; + var env = { + type: o.type, + content: Token.stringify(o.content, language, parent), + prism_tag: 'span', + classes: ['token', o.type], + attributes: {}, + language: language, + parent: parent + }; - hooks[name].push(callback); - }, + if (env.type == 'comment') { + env.attributes['spellcheck'] = 'true'; + } - run: function (name, env) { - var callbacks = _.hooks.all[name]; + _.hooks.run('wrap', env); - if (!callbacks || !callbacks.length) { - return; - } + var attributes = ''; - for (var i=0, callback; callback = callbacks[i++];) { - callback(env); - } + for (var name in env.attributes) { + attributes += name + '="' + (env.attributes[name] || '') + '"'; } - } - }; - - var Token = _.Token = function(type, content) { - this.type = type; - this.content = content; - }; - Token.stringify = function(o, language, parent) { - if (typeof o == 'string') { - return o; - } + return '<' + env.prism_tag + ' class="' + env.classes.join(' ') + '" ' + attributes + '>' + env.content + ''; - if (Object.prototype.toString.call(o) == '[object Array]') { - return o.map(function(element) { - return Token.stringify(element, language, o); - }).join(''); - } - - var env = { - type: o.type, - content: Token.stringify(o.content, language, parent), - prism_tag: 'span', - classes: ['token', o.type], - attributes: {}, - language: language, - parent: parent }; - if (env.type == 'comment') { - env.attributes['spellcheck'] = 'true'; - } - - _.hooks.run('wrap', env); + if (!self.document) { + // In worker + self.addEventListener('message', function(evt) { + var message = JSON.parse(evt.data), + lang = message.language, + code = message.code; - var attributes = ''; + self.postMessage(JSON.stringify(_.tokenize(code, _.languages[lang]))); + self.close(); + }, false); - for (var name in env.attributes) { - attributes += name + '="' + (env.attributes[name] || '') + '"'; + return; } - return '<' + env.prism_tag + ' class="' + env.classes.join(' ') + '" ' + attributes + '>' + env.content + ''; + // Get current script and highlight + var script = document.getElementsByTagName('script'); - }; + script = script[script.length - 1]; - if (!self.document) { - // In worker - self.addEventListener('message', function(evt) { - var message = JSON.parse(evt.data), - lang = message.language, - code = message.code; + if (script) { + _.filename = script.src; - self.postMessage(JSON.stringify(_.tokenize(code, _.languages[lang]))); - self.close(); - }, false); + if (document.addEventListener && !script.hasAttribute('data-manual')) { + document.addEventListener('DOMContentLoaded', _.highlightAll); + } + } - return; - } + })(); -// Get current script and highlight - var script = document.getElementsByTagName('script'); + Prism.languages.html = { + 'comment': /<!--[\w\W]*?-->/g, + 'prolog': /<\?.+?\?>/, + 'doctype': /<!DOCTYPE.+?>/, + 'cdata': /<!\[CDATA\[[\w\W]*?]]>/i, + 'prism_tag': { + pattern: /<\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|\w+))?\s*)*\/?>/gi, + inside: { + 'prism_tag': { + pattern: /^<\/?[\w:-]+/i, + inside: { + 'punctuation': /^<\/?/, + 'namespace': /^[\w-]+?:/ + } + }, + 'attr-value': { + pattern: /=(?:('|")[\w\W]*?(\1)|[^\s>]+)/gi, + inside: { + 'punctuation': /=|>|"/g + } + }, + 'punctuation': /\/?>/g, + 'attr-name': { + pattern: /[\w:-]+/g, + inside: { + 'namespace': /^[\w-]+?:/ + } + } - script = script[script.length - 1]; + } + }, + 'entity': /&#?[\da-z]{1,8};/gi + }; - if (script) { - _.filename = script.src; + // Plugin to make entity title show the real entity, idea by Roman Komarov + Prism.hooks.add('wrap', function(env) { - if (document.addEventListener && !script.hasAttribute('data-manual')) { - document.addEventListener('DOMContentLoaded', _.highlightAll); + if (env.type === 'entity') { + env.attributes['title'] = env.content.replace(/&/, '&'); } - } + });; + Prism.languages.css = { + 'comment': /\/\*[\w\W]*?\*\//g, + 'atrule': { + pattern: /@[\w-]+?.*?(;|(?=\s*{))/gi, + inside: { + 'punctuation': /[;:]/g + } + }, + 'url': /url\((["']?).*?\1\)/gi, + 'selector': /[^\{\}\s][^\{\};]*(?=\s*\{)/g, + 'property': /(\b|\B)[\w-]+(?=\s*:)/ig, + 'string': /("|')(\\?.)*?\1/g, + 'important': /\B!important\b/gi, + 'ignore': /&(lt|gt|amp);/gi, + 'punctuation': /[\{\};:]/g + }; -})(); - -Prism.languages.html = { - 'comment': /<!--[\w\W]*?-->/g, - 'prolog': /<\?.+?\?>/, - 'doctype': /<!DOCTYPE.+?>/, - 'cdata': /<!\[CDATA\[[\w\W]*?]]>/i, - 'prism_tag': { - pattern: /<\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|\w+))?\s*)*\/?>/gi, - inside: { - 'prism_tag': { - pattern: /^<\/?[\w:-]+/i, + if (Prism.languages.html) { + Prism.languages.insertBefore('html', 'prism_tag', { + 'style': { + pattern: /(<|<)style[\w\W]*?(>|>)[\w\W]*?(<|<)\/style(>|>)/ig, inside: { - 'punctuation': /^<\/?/, - 'namespace': /^[\w-]+?:/ - } - }, - 'attr-value': { - pattern: /=(?:('|")[\w\W]*?(\1)|[^\s>]+)/gi, - inside: { - 'punctuation': /=|>|"/g - } - }, - 'punctuation': /\/?>/g, - 'attr-name': { - pattern: /[\w:-]+/g, - inside: { - 'namespace': /^[\w-]+?:/ + 'prism_tag': { + pattern: /(<|<)style[\w\W]*?(>|>)|(<|<)\/style(>|>)/ig, + inside: Prism.languages.html.prism_tag.inside + }, + rest: Prism.languages.css } } - - } - }, - 'entity': /&#?[\da-z]{1,8};/gi -}; - -// Plugin to make entity title show the real entity, idea by Roman Komarov -Prism.hooks.add('wrap', function(env) { - - if (env.type === 'entity') { - env.attributes['title'] = env.content.replace(/&/, '&'); - } -});; -Prism.languages.css = { - 'comment': /\/\*[\w\W]*?\*\//g, - 'atrule': { - pattern: /@[\w-]+?.*?(;|(?=\s*{))/gi, - inside: { - 'punctuation': /[;:]/g - } - }, - 'url': /url\((["']?).*?\1\)/gi, - 'selector': /[^\{\}\s][^\{\};]*(?=\s*\{)/g, - 'property': /(\b|\B)[\w-]+(?=\s*:)/ig, - 'string': /("|')(\\?.)*?\1/g, - 'important': /\B!important\b/gi, - 'ignore': /&(lt|gt|amp);/gi, - 'punctuation': /[\{\};:]/g -}; - -if (Prism.languages.html) { - Prism.languages.insertBefore('html', 'prism_tag', { - 'style': { - pattern: /(<|<)style[\w\W]*?(>|>)[\w\W]*?(<|<)\/style(>|>)/ig, + }); + }; + Prism.languages.clike = { + 'comment': { + pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g, + lookbehind: true + }, + 'string': /("|')(\\?.)*?\1/g, + 'class-name': { + pattern: /((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/ig, + lookbehind: true, inside: { - 'prism_tag': { - pattern: /(<|<)style[\w\W]*?(>|>)|(<|<)\/style(>|>)/ig, - inside: Prism.languages.html.prism_tag.inside - }, - rest: Prism.languages.css + punctuation: /(\.|\\)/ } - } + }, + 'keyword': /\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g, + 'boolean': /\b(true|false)\b/g, + 'function': { + pattern: /[a-z0-9_]+\(/ig, + inside: { + punctuation: /\(/ + } + }, + 'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g, + 'operator': /[-+]{1,2}|!|<=?|>=?|={1,3}|(&){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g, + 'ignore': /&(lt|gt|amp);/gi, + 'punctuation': /[{}[\];(),.:]/g + }; + ; + Prism.languages.js = Prism.languages.extend('clike', { + 'keyword': /\b(var|let|if|else|while|do|for|return|in|instanceof|function|new|with|typeof|try|throw|catch|finally|null|break|continue)\b/g, + 'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g }); -}; -Prism.languages.clike = { - 'comment': { - pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g, - lookbehind: true - }, - 'string': /("|')(\\?.)*?\1/g, - 'class-name': { - pattern: /((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/ig, - lookbehind: true, - inside: { - punctuation: /(\.|\\)/ - } - }, - 'keyword': /\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g, - 'boolean': /\b(true|false)\b/g, - 'function': { - pattern: /[a-z0-9_]+\(/ig, - inside: { - punctuation: /\(/ + + Prism.languages.insertBefore('js', 'keyword', { + 'regex': { + pattern: /(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g, + lookbehind: true } - }, - 'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g, - 'operator': /[-+]{1,2}|!|<=?|>=?|={1,3}|(&){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g, - 'ignore': /&(lt|gt|amp);/gi, - 'punctuation': /[{}[\];(),.:]/g -}; -; -Prism.languages.js = Prism.languages.extend('clike', { - 'keyword': /\b(var|let|if|else|while|do|for|return|in|instanceof|function|new|with|typeof|try|throw|catch|finally|null|break|continue)\b/g, - 'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g -}); + }); -Prism.languages.insertBefore('js', 'keyword', { - 'regex': { - pattern: /(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g, - lookbehind: true + if (Prism.languages.html) { + Prism.languages.insertBefore('html', 'prism_tag', { + 'script': { + pattern: /(<|<)script[\w\W]*?(>|>)[\w\W]*?(<|<)\/script(>|>)/ig, + inside: { + 'prism_tag': { + pattern: /(<|<)script[\w\W]*?(>|>)|(<|<)\/script(>|>)/ig, + inside: Prism.languages.html.prism_tag.inside + }, + rest: Prism.languages.js + } + } + }); } -}); - -if (Prism.languages.html) { - Prism.languages.insertBefore('html', 'prism_tag', { - 'script': { - pattern: /(<|<)script[\w\W]*?(>|>)[\w\W]*?(<|<)\/script(>|>)/ig, + ; + Prism.languages.bash = Prism.languages.extend('clike', { + 'comment': { + pattern: /(^|[^"{\\])(#.*?(\r?\n|$))/g, + lookbehind: true + }, + 'string': { + //allow multiline string + pattern: /("|')(\\?[\s\S])*?\1/g, inside: { - 'prism_tag': { - pattern: /(<|<)script[\w\W]*?(>|>)|(<|<)\/script(>|>)/ig, - inside: Prism.languages.html.prism_tag.inside - }, - rest: Prism.languages.js + //'property' class reused for bash variables + 'property': /\$([a-zA-Z0-9_#\?\-\*!@]+|\{[^\}]+\})/g } - } + }, + 'keyword': /\b(if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)\b/g + }); + + Prism.languages.insertBefore('bash', 'keyword', { + //'property' class reused for bash variables + 'property': /\$([a-zA-Z0-9_#\?\-\*!@]+|\{[^}]+\})/g + }); + Prism.languages.insertBefore('bash', 'comment', { + //shebang must be before comment, 'important' class from css reused + 'important': /(^#!\s*\/bin\/bash)|(^#!\s*\/bin\/sh)/g }); -} -; -Prism.languages.bash = Prism.languages.extend('clike', { - 'comment': { - pattern: /(^|[^"{\\])(#.*?(\r?\n|$))/g, - lookbehind: true - }, - 'string': { - //allow multiline string - pattern: /("|')(\\?[\s\S])*?\1/g, - inside: { - //'property' class reused for bash variables - 'property': /\$([a-zA-Z0-9_#\?\-\*!@]+|\{[^\}]+\})/g - } - }, - 'keyword': /\b(if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)\b/g -}); -Prism.languages.insertBefore('bash', 'keyword', { - //'property' class reused for bash variables - 'property': /\$([a-zA-Z0-9_#\?\-\*!@]+|\{[^}]+\})/g + return Prism; }); -Prism.languages.insertBefore('bash', 'comment', { - //shebang must be before comment, 'important' class from css reused - 'important': /(^#!\s*\/bin\/bash)|(^#!\s*\/bin\/sh)/g -}); \ No newline at end of file diff --git a/assets/js/lib/require.js b/assets/js/lib/require.js index 8a4e6e1..72b08ca 100644 --- a/assets/js/lib/require.js +++ b/assets/js/lib/require.js @@ -3,2074 +3,2090 @@ * Available via the MIT or new BSD license. * see: http://github.com/jrburke/requirejs for details */ + +/** + * Modified in SourceJS to use custom `define/require/requirejs` namespace + */ + //Not using strict: uneven strict support in browsers, #392, and causes //problems with requirejs.exec()/transpiler plugins that may not be strict. /*jslint regexp: true, nomen: true, sloppy: true */ /*global window, navigator, document, importScripts, setTimeout, opera */ -var requirejs, require, define; -(function (global) { - var req, s, head, baseElement, dataMain, src, - interactiveScript, currentlyAddingScript, mainScript, subPath, - version = '2.1.14', - commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg, - cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, - jsSuffixRegExp = /\.js$/, - currDirRegExp = /^\.\//, - op = Object.prototype, - ostring = op.toString, - hasOwn = op.hasOwnProperty, - ap = Array.prototype, - apsp = ap.splice, - isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document), - isWebWorker = !isBrowser && typeof importScripts !== 'undefined', - //PS3 indicates loaded and complete, but need to wait for complete - //specifically. Sequence is 'loading', 'loaded', execution, - // then 'complete'. The UA check is unfortunate, but not sure how - //to feature test w/o causing perf issues. - readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ? - /^complete$/ : /^(complete|loaded)$/, - defContextName = '_', - //Oh the tragedy, detecting opera. See the usage of isOpera for reason. - isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]', - contexts = {}, - cfg = {}, - globalDefQueue = [], - useInteractive = false; - - function isFunction(it) { - return ostring.call(it) === '[object Function]'; - } - - function isArray(it) { - return ostring.call(it) === '[object Array]'; - } - - /** - * Helper function for iterating over an array. If the func returns - * a true value, it will break out of the loop. - */ - function each(ary, func) { - if (ary) { - var i; - for (i = 0; i < ary.length; i += 1) { - if (ary[i] && func(ary[i], i, ary)) { - break; - } - } +window.sourcejs = window.sourcejs || {}; + +window.sourcejs.amd = (function () { + var requirejs, require, define; + + (function (global) { + var req, s, head, baseElement, dataMain, src, + interactiveScript, currentlyAddingScript, mainScript, subPath, + version = '2.1.14', + commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg, + cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, + jsSuffixRegExp = /\.js$/, + currDirRegExp = /^\.\//, + op = Object.prototype, + ostring = op.toString, + hasOwn = op.hasOwnProperty, + ap = Array.prototype, + apsp = ap.splice, + isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document), + isWebWorker = !isBrowser && typeof importScripts !== 'undefined', + //PS3 indicates loaded and complete, but need to wait for complete + //specifically. Sequence is 'loading', 'loaded', execution, + // then 'complete'. The UA check is unfortunate, but not sure how + //to feature test w/o causing perf issues. + readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ? + /^complete$/ : /^(complete|loaded)$/, + defContextName = '_', + //Oh the tragedy, detecting opera. See the usage of isOpera for reason. + isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]', + contexts = {}, + cfg = {}, + globalDefQueue = [], + useInteractive = false; + + function isFunction(it) { + return ostring.call(it) === '[object Function]'; } - } - - /** - * Helper function for iterating over an array backwards. If the func - * returns a true value, it will break out of the loop. - */ - function eachReverse(ary, func) { - if (ary) { - var i; - for (i = ary.length - 1; i > -1; i -= 1) { - if (ary[i] && func(ary[i], i, ary)) { - break; - } - } + + function isArray(it) { + return ostring.call(it) === '[object Array]'; } - } - - function hasProp(obj, prop) { - return hasOwn.call(obj, prop); - } - - function getOwn(obj, prop) { - return hasProp(obj, prop) && obj[prop]; - } - - /** - * Cycles over properties in an object and calls a function for each - * property value. If the function returns a truthy value, then the - * iteration is stopped. - */ - function eachProp(obj, func) { - var prop; - for (prop in obj) { - if (hasProp(obj, prop)) { - if (func(obj[prop], prop)) { - break; + + /** + * Helper function for iterating over an array. If the func returns + * a true value, it will break out of the loop. + */ + function each(ary, func) { + if (ary) { + var i; + for (i = 0; i < ary.length; i += 1) { + if (ary[i] && func(ary[i], i, ary)) { + break; + } } } } - } - - /** - * Simple function to mix in properties from source into target, - * but only if target does not already have a property of the same name. - */ - function mixin(target, source, force, deepStringMixin) { - if (source) { - eachProp(source, function (value, prop) { - if (force || !hasProp(target, prop)) { - if (deepStringMixin && typeof value === 'object' && value && - !isArray(value) && !isFunction(value) && - !(value instanceof RegExp)) { - - if (!target[prop]) { - target[prop] = {}; - } - mixin(target[prop], value, force, deepStringMixin); - } else { - target[prop] = value; + + /** + * Helper function for iterating over an array backwards. If the func + * returns a true value, it will break out of the loop. + */ + function eachReverse(ary, func) { + if (ary) { + var i; + for (i = ary.length - 1; i > -1; i -= 1) { + if (ary[i] && func(ary[i], i, ary)) { + break; } } - }); + } } - return target; - } - - //Similar to Function.prototype.bind, but the 'this' object is specified - //first, since it is easier to read/figure out what 'this' will be. - function bind(obj, fn) { - return function () { - return fn.apply(obj, arguments); - }; - } - function scripts() { - return document.getElementsByTagName('script'); - } - - function defaultOnError(err) { - throw err; - } - - //Allow getting a global that is expressed in - //dot notation, like 'a.b.c'. - function getGlobal(value) { - if (!value) { - return value; - } - var g = global; - each(value.split('.'), function (part) { - g = g[part]; - }); - return g; - } - - /** - * Constructs an error with a pointer to an URL with more information. - * @param {String} id the error ID that maps to an ID on a web page. - * @param {String} message human readable error. - * @param {Error} [err] the original error, if there is one. - * - * @returns {Error} - */ - function makeError(id, msg, err, requireModules) { - var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id); - e.requireType = id; - e.requireModules = requireModules; - if (err) { - e.originalError = err; + function hasProp(obj, prop) { + return hasOwn.call(obj, prop); } - return e; - } - - if (typeof define !== 'undefined') { - //If a define is already in play via another AMD loader, - //do not overwrite. - return; - } - - if (typeof requirejs !== 'undefined') { - if (isFunction(requirejs)) { - //Do not overwrite an existing requirejs instance. - return; + + function getOwn(obj, prop) { + return hasProp(obj, prop) && obj[prop]; } - cfg = requirejs; - requirejs = undefined; - } - - //Allow for a require config object - if (typeof require !== 'undefined' && !isFunction(require)) { - //assume it is a config object. - cfg = require; - require = undefined; - } - - function newContext(contextName) { - var inCheckLoaded, Module, context, handlers, - checkLoadedTimeoutId, - config = { - //Defaults. Do not set a default for map - //config to speed up normalize(), which - //will run faster if there is no default. - waitSeconds: 7, - baseUrl: './', - paths: {}, - bundles: {}, - pkgs: {}, - shim: {}, - config: {} - }, - registry = {}, - //registry of just enabled modules, to speed - //cycle breaking code when lots of modules - //are registered, but not activated. - enabledRegistry = {}, - undefEvents = {}, - defQueue = [], - defined = {}, - urlFetched = {}, - bundlesMap = {}, - requireCounter = 1, - unnormalizedCounter = 1; /** - * Trims the . and .. from an array of path segments. - * It will keep a leading path segment if a .. will become - * the first path segment, to help with module name lookups, - * which act like paths, but can be remapped. But the end result, - * all paths that use this function should look normalized. - * NOTE: this method MODIFIES the input array. - * @param {Array} ary the array of path segments. + * Cycles over properties in an object and calls a function for each + * property value. If the function returns a truthy value, then the + * iteration is stopped. */ - function trimDots(ary) { - var i, part; - for (i = 0; i < ary.length; i++) { - part = ary[i]; - if (part === '.') { - ary.splice(i, 1); - i -= 1; - } else if (part === '..') { - // If at the start, or previous value is still .., - // keep them so that when converted to a path it may - // still work when converted to a path, even though - // as an ID it is less than ideal. In larger point - // releases, may be better to just kick out an error. - if (i === 0 || (i == 1 && ary[2] === '..') || ary[i - 1] === '..') { - continue; - } else if (i > 0) { - ary.splice(i - 1, 2); - i -= 2; + function eachProp(obj, func) { + var prop; + for (prop in obj) { + if (hasProp(obj, prop)) { + if (func(obj[prop], prop)) { + break; } } } } /** - * Given a relative module name, like ./something, normalize it to - * a real name that can be mapped to a path. - * @param {String} name the relative name - * @param {String} baseName a real name that the name arg is relative - * to. - * @param {Boolean} applyMap apply the map config to the value. Should - * only be done if this normalization is for a dependency ID. - * @returns {String} normalized name + * Simple function to mix in properties from source into target, + * but only if target does not already have a property of the same name. */ - function normalize(name, baseName, applyMap) { - var pkgMain, mapValue, nameParts, i, j, nameSegment, lastIndex, - foundMap, foundI, foundStarMap, starI, normalizedBaseParts, - baseParts = (baseName && baseName.split('/')), - map = config.map, - starMap = map && map['*']; - - //Adjust any relative paths. - if (name) { - name = name.split('/'); - lastIndex = name.length - 1; - - // If wanting node ID compatibility, strip .js from end - // of IDs. Have to do this here, and not in nameToUrl - // because node allows either .js or non .js to map - // to same file. - if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) { - name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); - } - - // Starts with a '.' so need the baseName - if (name[0].charAt(0) === '.' && baseParts) { - //Convert baseName to array, and lop off the last part, - //so that . matches that 'directory' and not name of the baseName's - //module. For instance, baseName of 'one/two/three', maps to - //'one/two/three.js', but we want the directory, 'one/two' for - //this normalization. - normalizedBaseParts = baseParts.slice(0, baseParts.length - 1); - name = normalizedBaseParts.concat(name); - } - - trimDots(name); - name = name.join('/'); - } - - //Apply map config if available. - if (applyMap && map && (baseParts || starMap)) { - nameParts = name.split('/'); - - outerLoop: for (i = nameParts.length; i > 0; i -= 1) { - nameSegment = nameParts.slice(0, i).join('/'); - - if (baseParts) { - //Find the longest baseName segment match in the config. - //So, do joins on the biggest to smallest lengths of baseParts. - for (j = baseParts.length; j > 0; j -= 1) { - mapValue = getOwn(map, baseParts.slice(0, j).join('/')); - - //baseName segment has config, find if it has one for - //this name. - if (mapValue) { - mapValue = getOwn(mapValue, nameSegment); - if (mapValue) { - //Match, update name to the new value. - foundMap = mapValue; - foundI = i; - break outerLoop; - } + function mixin(target, source, force, deepStringMixin) { + if (source) { + eachProp(source, function (value, prop) { + if (force || !hasProp(target, prop)) { + if (deepStringMixin && typeof value === 'object' && value && + !isArray(value) && !isFunction(value) && + !(value instanceof RegExp)) { + + if (!target[prop]) { + target[prop] = {}; } + mixin(target[prop], value, force, deepStringMixin); + } else { + target[prop] = value; } } - - //Check for a star map match, but just hold on to it, - //if there is a shorter segment match later in a matching - //config, then favor over this star map. - if (!foundStarMap && starMap && getOwn(starMap, nameSegment)) { - foundStarMap = getOwn(starMap, nameSegment); - starI = i; - } - } - - if (!foundMap && foundStarMap) { - foundMap = foundStarMap; - foundI = starI; - } - - if (foundMap) { - nameParts.splice(0, foundI, foundMap); - name = nameParts.join('/'); - } + }); } + return target; + } - // If the name points to a package's name, use - // the package main instead. - pkgMain = getOwn(config.pkgs, name); - - return pkgMain ? pkgMain : name; + //Similar to Function.prototype.bind, but the 'this' object is specified + //first, since it is easier to read/figure out what 'this' will be. + function bind(obj, fn) { + return function () { + return fn.apply(obj, arguments); + }; } - function removeScript(name) { - if (isBrowser) { - each(scripts(), function (scriptNode) { - if (scriptNode.getAttribute('data-requiremodule') === name && - scriptNode.getAttribute('data-requirecontext') === context.contextName) { - scriptNode.parentNode.removeChild(scriptNode); - return true; - } - }); - } + function scripts() { + return document.getElementsByTagName('script'); } - function hasPathFallback(id) { - var pathConfig = getOwn(config.paths, id); - if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) { - //Pop off the first array value, since it failed, and - //retry - pathConfig.shift(); - context.require.undef(id); - - //Custom require that does not do map translation, since - //ID is "absolute", already mapped/resolved. - context.makeRequire(null, { - skipMap: true - })([id]); - - return true; - } + function defaultOnError(err) { + throw err; } - //Turns a plugin!resource to [plugin, resource] - //with the plugin being undefined if the name - //did not have a plugin prefix. - function splitPrefix(name) { - var prefix, - index = name ? name.indexOf('!') : -1; - if (index > -1) { - prefix = name.substring(0, index); - name = name.substring(index + 1, name.length); + //Allow getting a global that is expressed in + //dot notation, like 'a.b.c'. + function getGlobal(value) { + if (!value) { + return value; } - return [prefix, name]; + var g = global; + each(value.split('.'), function (part) { + g = g[part]; + }); + return g; } /** - * Creates a module mapping that includes plugin prefix, module - * name, and path. If parentModuleMap is provided it will - * also normalize the name via require.normalize() - * - * @param {String} name the module name - * @param {String} [parentModuleMap] parent module map - * for the module name, used to resolve relative names. - * @param {Boolean} isNormalized: is the ID already normalized. - * This is true if this call is done for a define() module ID. - * @param {Boolean} applyMap: apply the map config to the ID. - * Should only be true if this map is for a dependency. + * Constructs an error with a pointer to an URL with more information. + * @param {String} id the error ID that maps to an ID on a web page. + * @param {String} message human readable error. + * @param {Error} [err] the original error, if there is one. * - * @returns {Object} + * @returns {Error} */ - function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) { - var url, pluginModule, suffix, nameParts, - prefix = null, - parentName = parentModuleMap ? parentModuleMap.name : null, - originalName = name, - isDefine = true, - normalizedName = ''; - - //If no name, then it means it is a require call, generate an - //internal name. - if (!name) { - isDefine = false; - name = '_@r' + (requireCounter += 1); + function makeError(id, msg, err, requireModules) { + var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id); + e.requireType = id; + e.requireModules = requireModules; + if (err) { + e.originalError = err; } + return e; + } - nameParts = splitPrefix(name); - prefix = nameParts[0]; - name = nameParts[1]; + if (typeof define !== 'undefined') { + //If a define is already in play via another AMD loader, + //do not overwrite. + return; + } - if (prefix) { - prefix = normalize(prefix, parentName, applyMap); - pluginModule = getOwn(defined, prefix); + if (typeof requirejs !== 'undefined') { + if (isFunction(requirejs)) { + //Do not overwrite an existing requirejs instance. + return; } + cfg = requirejs; + requirejs = undefined; + } - //Account for relative paths if there is a base name. - if (name) { - if (prefix) { - if (pluginModule && pluginModule.normalize) { - //Plugin is loaded, use its normalize method. - normalizedName = pluginModule.normalize(name, function (name) { - return normalize(name, parentName, applyMap); - }); - } else { - // If nested plugin references, then do not try to - // normalize, as it will not normalize correctly. This - // places a restriction on resourceIds, and the longer - // term solution is not to normalize until plugins are - // loaded and all normalizations to allow for async - // loading of a loader plugin. But for now, fixes the - // common uses. Details in #1131 - normalizedName = name.indexOf('!') === -1 ? - normalize(name, parentName, applyMap) : - name; + //Allow for a require config object + if (typeof require !== 'undefined' && !isFunction(require)) { + //assume it is a config object. + cfg = require; + require = undefined; + } + + function newContext(contextName) { + var inCheckLoaded, Module, context, handlers, + checkLoadedTimeoutId, + config = { + //Defaults. Do not set a default for map + //config to speed up normalize(), which + //will run faster if there is no default. + waitSeconds: 7, + baseUrl: './', + paths: {}, + bundles: {}, + pkgs: {}, + shim: {}, + config: {} + }, + registry = {}, + //registry of just enabled modules, to speed + //cycle breaking code when lots of modules + //are registered, but not activated. + enabledRegistry = {}, + undefEvents = {}, + defQueue = [], + defined = {}, + urlFetched = {}, + bundlesMap = {}, + requireCounter = 1, + unnormalizedCounter = 1; + + /** + * Trims the . and .. from an array of path segments. + * It will keep a leading path segment if a .. will become + * the first path segment, to help with module name lookups, + * which act like paths, but can be remapped. But the end result, + * all paths that use this function should look normalized. + * NOTE: this method MODIFIES the input array. + * @param {Array} ary the array of path segments. + */ + function trimDots(ary) { + var i, part; + for (i = 0; i < ary.length; i++) { + part = ary[i]; + if (part === '.') { + ary.splice(i, 1); + i -= 1; + } else if (part === '..') { + // If at the start, or previous value is still .., + // keep them so that when converted to a path it may + // still work when converted to a path, even though + // as an ID it is less than ideal. In larger point + // releases, may be better to just kick out an error. + if (i === 0 || (i == 1 && ary[2] === '..') || ary[i - 1] === '..') { + continue; + } else if (i > 0) { + ary.splice(i - 1, 2); + i -= 2; + } } - } else { - //A regular module. - normalizedName = normalize(name, parentName, applyMap); - - //Normalized name may be a plugin ID due to map config - //application in normalize. The map config values must - //already be normalized, so do not need to redo that part. - nameParts = splitPrefix(normalizedName); - prefix = nameParts[0]; - normalizedName = nameParts[1]; - isNormalized = true; - - url = context.nameToUrl(normalizedName); } } - //If the id is a plugin id that cannot be determined if it needs - //normalization, stamp it with a unique ID so two matching relative - //ids that may conflict can be separate. - suffix = prefix && !pluginModule && !isNormalized ? - '_unnormalized' + (unnormalizedCounter += 1) : - ''; - - return { - prefix: prefix, - name: normalizedName, - parentMap: parentModuleMap, - unnormalized: !!suffix, - url: url, - originalName: originalName, - isDefine: isDefine, - id: (prefix ? - prefix + '!' + normalizedName : - normalizedName) + suffix - }; - } + /** + * Given a relative module name, like ./something, normalize it to + * a real name that can be mapped to a path. + * @param {String} name the relative name + * @param {String} baseName a real name that the name arg is relative + * to. + * @param {Boolean} applyMap apply the map config to the value. Should + * only be done if this normalization is for a dependency ID. + * @returns {String} normalized name + */ + function normalize(name, baseName, applyMap) { + var pkgMain, mapValue, nameParts, i, j, nameSegment, lastIndex, + foundMap, foundI, foundStarMap, starI, normalizedBaseParts, + baseParts = (baseName && baseName.split('/')), + map = config.map, + starMap = map && map['*']; + + //Adjust any relative paths. + if (name) { + name = name.split('/'); + lastIndex = name.length - 1; + + // If wanting node ID compatibility, strip .js from end + // of IDs. Have to do this here, and not in nameToUrl + // because node allows either .js or non .js to map + // to same file. + if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) { + name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); + } - function getModule(depMap) { - var id = depMap.id, - mod = getOwn(registry, id); + // Starts with a '.' so need the baseName + if (name[0].charAt(0) === '.' && baseParts) { + //Convert baseName to array, and lop off the last part, + //so that . matches that 'directory' and not name of the baseName's + //module. For instance, baseName of 'one/two/three', maps to + //'one/two/three.js', but we want the directory, 'one/two' for + //this normalization. + normalizedBaseParts = baseParts.slice(0, baseParts.length - 1); + name = normalizedBaseParts.concat(name); + } - if (!mod) { - mod = registry[id] = new context.Module(depMap); - } + trimDots(name); + name = name.join('/'); + } - return mod; - } + //Apply map config if available. + if (applyMap && map && (baseParts || starMap)) { + nameParts = name.split('/'); - function on(depMap, name, fn) { - var id = depMap.id, - mod = getOwn(registry, id); + outerLoop: for (i = nameParts.length; i > 0; i -= 1) { + nameSegment = nameParts.slice(0, i).join('/'); - if (hasProp(defined, id) && - (!mod || mod.defineEmitComplete)) { - if (name === 'defined') { - fn(defined[id]); - } - } else { - mod = getModule(depMap); - if (mod.error && name === 'error') { - fn(mod.error); - } else { - mod.on(name, fn); - } - } - } + if (baseParts) { + //Find the longest baseName segment match in the config. + //So, do joins on the biggest to smallest lengths of baseParts. + for (j = baseParts.length; j > 0; j -= 1) { + mapValue = getOwn(map, baseParts.slice(0, j).join('/')); - function onError(err, errback) { - var ids = err.requireModules, - notified = false; + //baseName segment has config, find if it has one for + //this name. + if (mapValue) { + mapValue = getOwn(mapValue, nameSegment); + if (mapValue) { + //Match, update name to the new value. + foundMap = mapValue; + foundI = i; + break outerLoop; + } + } + } + } - if (errback) { - errback(err); - } else { - each(ids, function (id) { - var mod = getOwn(registry, id); - if (mod) { - //Set error on module, so it skips timeout checks. - mod.error = err; - if (mod.events.error) { - notified = true; - mod.emit('error', err); + //Check for a star map match, but just hold on to it, + //if there is a shorter segment match later in a matching + //config, then favor over this star map. + if (!foundStarMap && starMap && getOwn(starMap, nameSegment)) { + foundStarMap = getOwn(starMap, nameSegment); + starI = i; } } - }); - if (!notified) { - req.onError(err); + if (!foundMap && foundStarMap) { + foundMap = foundStarMap; + foundI = starI; + } + + if (foundMap) { + nameParts.splice(0, foundI, foundMap); + name = nameParts.join('/'); + } } - } - } - /** - * Internal method to transfer globalQueue items to this context's - * defQueue. - */ - function takeGlobalQueue() { - //Push all the globalDefQueue items into the context's defQueue - if (globalDefQueue.length) { - //Array splice in the values since the context code has a - //local var ref to defQueue, so cannot just reassign the one - //on context. - apsp.apply(defQueue, - [defQueue.length, 0].concat(globalDefQueue)); - globalDefQueue = []; + // If the name points to a package's name, use + // the package main instead. + pkgMain = getOwn(config.pkgs, name); + + return pkgMain ? pkgMain : name; } - } - handlers = { - 'require': function (mod) { - if (mod.require) { - return mod.require; - } else { - return (mod.require = context.makeRequire(mod.map)); - } - }, - 'exports': function (mod) { - mod.usingExports = true; - if (mod.map.isDefine) { - if (mod.exports) { - return (defined[mod.map.id] = mod.exports); - } else { - return (mod.exports = defined[mod.map.id] = {}); - } - } - }, - 'module': function (mod) { - if (mod.module) { - return mod.module; - } else { - return (mod.module = { - id: mod.map.id, - uri: mod.map.url, - config: function () { - return getOwn(config.config, mod.map.id) || {}; - }, - exports: mod.exports || (mod.exports = {}) + function removeScript(name) { + if (isBrowser) { + each(scripts(), function (scriptNode) { + if (scriptNode.getAttribute('data-requiremodule') === name && + scriptNode.getAttribute('data-requirecontext') === context.contextName) { + scriptNode.parentNode.removeChild(scriptNode); + return true; + } }); } } - }; - - function cleanRegistry(id) { - //Clean up machinery used for waiting modules. - delete registry[id]; - delete enabledRegistry[id]; - } - function breakCycle(mod, traced, processed) { - var id = mod.map.id; - - if (mod.error) { - mod.emit('error', mod.error); - } else { - traced[id] = true; - each(mod.depMaps, function (depMap, i) { - var depId = depMap.id, - dep = getOwn(registry, depId); - - //Only force things that have not completed - //being defined, so still in the registry, - //and only if it has not been matched up - //in the module already. - if (dep && !mod.depMatched[i] && !processed[depId]) { - if (getOwn(traced, depId)) { - mod.defineDep(i, defined[depId]); - mod.check(); //pass false? - } else { - breakCycle(dep, traced, processed); - } - } - }); - processed[id] = true; + function hasPathFallback(id) { + var pathConfig = getOwn(config.paths, id); + if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) { + //Pop off the first array value, since it failed, and + //retry + pathConfig.shift(); + context.require.undef(id); + + //Custom require that does not do map translation, since + //ID is "absolute", already mapped/resolved. + context.makeRequire(null, { + skipMap: true + })([id]); + + return true; + } } - } - function checkLoaded() { - var err, usingPathFallback, - waitInterval = config.waitSeconds * 1000, - //It is possible to disable the wait interval by using waitSeconds of 0. - expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(), - noLoads = [], - reqCalls = [], - stillLoading = false, - needCycleCheck = true; - - //Do not bother if this call was a result of a cycle break. - if (inCheckLoaded) { - return; + //Turns a plugin!resource to [plugin, resource] + //with the plugin being undefined if the name + //did not have a plugin prefix. + function splitPrefix(name) { + var prefix, + index = name ? name.indexOf('!') : -1; + if (index > -1) { + prefix = name.substring(0, index); + name = name.substring(index + 1, name.length); + } + return [prefix, name]; } - inCheckLoaded = true; - - //Figure out the state of all the modules. - eachProp(enabledRegistry, function (mod) { - var map = mod.map, - modId = map.id; - - //Skip things that are not enabled or in error state. - if (!mod.enabled) { - return; + /** + * Creates a module mapping that includes plugin prefix, module + * name, and path. If parentModuleMap is provided it will + * also normalize the name via require.normalize() + * + * @param {String} name the module name + * @param {String} [parentModuleMap] parent module map + * for the module name, used to resolve relative names. + * @param {Boolean} isNormalized: is the ID already normalized. + * This is true if this call is done for a define() module ID. + * @param {Boolean} applyMap: apply the map config to the ID. + * Should only be true if this map is for a dependency. + * + * @returns {Object} + */ + function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) { + var url, pluginModule, suffix, nameParts, + prefix = null, + parentName = parentModuleMap ? parentModuleMap.name : null, + originalName = name, + isDefine = true, + normalizedName = ''; + + //If no name, then it means it is a require call, generate an + //internal name. + if (!name) { + isDefine = false; + name = '_@r' + (requireCounter += 1); } - if (!map.isDefine) { - reqCalls.push(mod); + nameParts = splitPrefix(name); + prefix = nameParts[0]; + name = nameParts[1]; + + if (prefix) { + prefix = normalize(prefix, parentName, applyMap); + pluginModule = getOwn(defined, prefix); } - if (!mod.error) { - //If the module should be executed, and it has not - //been inited and time is up, remember it. - if (!mod.inited && expired) { - if (hasPathFallback(modId)) { - usingPathFallback = true; - stillLoading = true; + //Account for relative paths if there is a base name. + if (name) { + if (prefix) { + if (pluginModule && pluginModule.normalize) { + //Plugin is loaded, use its normalize method. + normalizedName = pluginModule.normalize(name, function (name) { + return normalize(name, parentName, applyMap); + }); } else { - noLoads.push(modId); - removeScript(modId); - } - } else if (!mod.inited && mod.fetched && map.isDefine) { - stillLoading = true; - if (!map.prefix) { - //No reason to keep looking for unfinished - //loading. If the only stillLoading is a - //plugin resource though, keep going, - //because it may be that a plugin resource - //is waiting on a non-plugin cycle. - return (needCycleCheck = false); + // If nested plugin references, then do not try to + // normalize, as it will not normalize correctly. This + // places a restriction on resourceIds, and the longer + // term solution is not to normalize until plugins are + // loaded and all normalizations to allow for async + // loading of a loader plugin. But for now, fixes the + // common uses. Details in #1131 + normalizedName = name.indexOf('!') === -1 ? + normalize(name, parentName, applyMap) : + name; } + } else { + //A regular module. + normalizedName = normalize(name, parentName, applyMap); + + //Normalized name may be a plugin ID due to map config + //application in normalize. The map config values must + //already be normalized, so do not need to redo that part. + nameParts = splitPrefix(normalizedName); + prefix = nameParts[0]; + normalizedName = nameParts[1]; + isNormalized = true; + + url = context.nameToUrl(normalizedName); } } - }); - if (expired && noLoads.length) { - //If wait time expired, throw error of unloaded modules. - err = makeError('timeout', 'Load timeout for modules: ' + noLoads, null, noLoads); - err.contextName = context.contextName; - return onError(err); + //If the id is a plugin id that cannot be determined if it needs + //normalization, stamp it with a unique ID so two matching relative + //ids that may conflict can be separate. + suffix = prefix && !pluginModule && !isNormalized ? + '_unnormalized' + (unnormalizedCounter += 1) : + ''; + + return { + prefix: prefix, + name: normalizedName, + parentMap: parentModuleMap, + unnormalized: !!suffix, + url: url, + originalName: originalName, + isDefine: isDefine, + id: (prefix ? + prefix + '!' + normalizedName : + normalizedName) + suffix + }; } - //Not expired, check for a cycle. - if (needCycleCheck) { - each(reqCalls, function (mod) { - breakCycle(mod, {}, {}); - }); - } + function getModule(depMap) { + var id = depMap.id, + mod = getOwn(registry, id); - //If still waiting on loads, and the waiting load is something - //other than a plugin resource, or there are still outstanding - //scripts, then just try back later. - if ((!expired || usingPathFallback) && stillLoading) { - //Something is still waiting to load. Wait for it, but only - //if a timeout is not already in effect. - if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) { - checkLoadedTimeoutId = setTimeout(function () { - checkLoadedTimeoutId = 0; - checkLoaded(); - }, 50); + if (!mod) { + mod = registry[id] = new context.Module(depMap); } - } - inCheckLoaded = false; - } - - Module = function (map) { - this.events = getOwn(undefEvents, map.id) || {}; - this.map = map; - this.shim = getOwn(config.shim, map.id); - this.depExports = []; - this.depMaps = []; - this.depMatched = []; - this.pluginMaps = {}; - this.depCount = 0; - - /* this.exports this.factory - this.depMaps = [], - this.enabled, this.fetched - */ - }; + return mod; + } - Module.prototype = { - init: function (depMaps, factory, errback, options) { - options = options || {}; + function on(depMap, name, fn) { + var id = depMap.id, + mod = getOwn(registry, id); - //Do not do more inits if already done. Can happen if there - //are multiple define calls for the same module. That is not - //a normal, common case, but it is also not unexpected. - if (this.inited) { - return; + if (hasProp(defined, id) && + (!mod || mod.defineEmitComplete)) { + if (name === 'defined') { + fn(defined[id]); + } + } else { + mod = getModule(depMap); + if (mod.error && name === 'error') { + fn(mod.error); + } else { + mod.on(name, fn); + } } + } - this.factory = factory; + function onError(err, errback) { + var ids = err.requireModules, + notified = false; if (errback) { - //Register for errors on this module. - this.on('error', errback); - } else if (this.events.error) { - //If no errback already, but there are error listeners - //on this module, set up an errback to pass to the deps. - errback = bind(this, function (err) { - this.emit('error', err); + errback(err); + } else { + each(ids, function (id) { + var mod = getOwn(registry, id); + if (mod) { + //Set error on module, so it skips timeout checks. + mod.error = err; + if (mod.events.error) { + notified = true; + mod.emit('error', err); + } + } }); + + if (!notified) { + req.onError(err); + } } + } - //Do a copy of the dependency array, so that - //source inputs are not modified. For example - //"shim" deps are passed in here directly, and - //doing a direct modification of the depMaps array - //would affect that config. - this.depMaps = depMaps && depMaps.slice(0); + /** + * Internal method to transfer globalQueue items to this context's + * defQueue. + */ + function takeGlobalQueue() { + //Push all the globalDefQueue items into the context's defQueue + if (globalDefQueue.length) { + //Array splice in the values since the context code has a + //local var ref to defQueue, so cannot just reassign the one + //on context. + apsp.apply(defQueue, + [defQueue.length, 0].concat(globalDefQueue)); + globalDefQueue = []; + } + } - this.errback = errback; + handlers = { + 'require': function (mod) { + if (mod.require) { + return mod.require; + } else { + return (mod.require = context.makeRequire(mod.map)); + } + }, + 'exports': function (mod) { + mod.usingExports = true; + if (mod.map.isDefine) { + if (mod.exports) { + return (defined[mod.map.id] = mod.exports); + } else { + return (mod.exports = defined[mod.map.id] = {}); + } + } + }, + 'module': function (mod) { + if (mod.module) { + return mod.module; + } else { + return (mod.module = { + id: mod.map.id, + uri: mod.map.url, + config: function () { + return getOwn(config.config, mod.map.id) || {}; + }, + exports: mod.exports || (mod.exports = {}) + }); + } + } + }; - //Indicate this module has be initialized - this.inited = true; + function cleanRegistry(id) { + //Clean up machinery used for waiting modules. + delete registry[id]; + delete enabledRegistry[id]; + } - this.ignore = options.ignore; + function breakCycle(mod, traced, processed) { + var id = mod.map.id; - //Could have option to init this module in enabled mode, - //or could have been previously marked as enabled. However, - //the dependencies are not known until init is called. So - //if enabled previously, now trigger dependencies as enabled. - if (options.enabled || this.enabled) { - //Enable this module and dependencies. - //Will call this.check() - this.enable(); + if (mod.error) { + mod.emit('error', mod.error); } else { - this.check(); - } - }, - - defineDep: function (i, depExports) { - //Because of cycles, defined callback for a given - //export can be called more than once. - if (!this.depMatched[i]) { - this.depMatched[i] = true; - this.depCount -= 1; - this.depExports[i] = depExports; + traced[id] = true; + each(mod.depMaps, function (depMap, i) { + var depId = depMap.id, + dep = getOwn(registry, depId); + + //Only force things that have not completed + //being defined, so still in the registry, + //and only if it has not been matched up + //in the module already. + if (dep && !mod.depMatched[i] && !processed[depId]) { + if (getOwn(traced, depId)) { + mod.defineDep(i, defined[depId]); + mod.check(); //pass false? + } else { + breakCycle(dep, traced, processed); + } + } + }); + processed[id] = true; } - }, + } - fetch: function () { - if (this.fetched) { + function checkLoaded() { + var err, usingPathFallback, + waitInterval = config.waitSeconds * 1000, + //It is possible to disable the wait interval by using waitSeconds of 0. + expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(), + noLoads = [], + reqCalls = [], + stillLoading = false, + needCycleCheck = true; + + //Do not bother if this call was a result of a cycle break. + if (inCheckLoaded) { return; } - this.fetched = true; - - context.startTime = (new Date()).getTime(); - var map = this.map; + inCheckLoaded = true; - //If the manager is for a plugin managed resource, - //ask the plugin to load it now. - if (this.shim) { - context.makeRequire(this.map, { - enableBuildCallback: true - })(this.shim.deps || [], bind(this, function () { - return map.prefix ? this.callPlugin() : this.load(); - })); - } else { - //Regular dependency. - return map.prefix ? this.callPlugin() : this.load(); - } - }, - - load: function () { - var url = this.map.url; + //Figure out the state of all the modules. + eachProp(enabledRegistry, function (mod) { + var map = mod.map, + modId = map.id; - //Regular dependency. - if (!urlFetched[url]) { - urlFetched[url] = true; - context.load(this.map.id, url); - } - }, + //Skip things that are not enabled or in error state. + if (!mod.enabled) { + return; + } - /** - * Checks if the module is ready to define itself, and if so, - * define it. - */ - check: function () { - if (!this.enabled || this.enabling) { - return; - } + if (!map.isDefine) { + reqCalls.push(mod); + } - var err, cjsModule, - id = this.map.id, - depExports = this.depExports, - exports = this.exports, - factory = this.factory; - - if (!this.inited) { - this.fetch(); - } else if (this.error) { - this.emit('error', this.error); - } else if (!this.defining) { - //The factory could trigger another require call - //that would result in checking this module to - //define itself again. If already in the process - //of doing that, skip this work. - this.defining = true; - - if (this.depCount < 1 && !this.defined) { - if (isFunction(factory)) { - //If there is an error listener, favor passing - //to that instead of throwing an error. However, - //only do it for define()'d modules. require - //errbacks should not be called for failures in - //their callbacks (#699). However if a global - //onError is set, use that. - if ((this.events.error && this.map.isDefine) || - req.onError !== defaultOnError) { - try { - exports = context.execCb(id, factory, depExports, exports); - } catch (e) { - err = e; - } + if (!mod.error) { + //If the module should be executed, and it has not + //been inited and time is up, remember it. + if (!mod.inited && expired) { + if (hasPathFallback(modId)) { + usingPathFallback = true; + stillLoading = true; } else { - exports = context.execCb(id, factory, depExports, exports); + noLoads.push(modId); + removeScript(modId); } - - // Favor return value over exports. If node/cjs in play, - // then will not have a return value anyway. Favor - // module.exports assignment over exports object. - if (this.map.isDefine && exports === undefined) { - cjsModule = this.module; - if (cjsModule) { - exports = cjsModule.exports; - } else if (this.usingExports) { - //exports already set the defined value. - exports = this.exports; - } + } else if (!mod.inited && mod.fetched && map.isDefine) { + stillLoading = true; + if (!map.prefix) { + //No reason to keep looking for unfinished + //loading. If the only stillLoading is a + //plugin resource though, keep going, + //because it may be that a plugin resource + //is waiting on a non-plugin cycle. + return (needCycleCheck = false); } + } + } + }); - if (err) { - err.requireMap = this.map; - err.requireModules = this.map.isDefine ? [this.map.id] : null; - err.requireType = this.map.isDefine ? 'define' : 'require'; - return onError((this.error = err)); - } + if (expired && noLoads.length) { + //If wait time expired, throw error of unloaded modules. + err = makeError('timeout', 'Load timeout for modules: ' + noLoads, null, noLoads); + err.contextName = context.contextName; + return onError(err); + } - } else { - //Just a literal value - exports = factory; - } + //Not expired, check for a cycle. + if (needCycleCheck) { + each(reqCalls, function (mod) { + breakCycle(mod, {}, {}); + }); + } - this.exports = exports; + //If still waiting on loads, and the waiting load is something + //other than a plugin resource, or there are still outstanding + //scripts, then just try back later. + if ((!expired || usingPathFallback) && stillLoading) { + //Something is still waiting to load. Wait for it, but only + //if a timeout is not already in effect. + if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) { + checkLoadedTimeoutId = setTimeout(function () { + checkLoadedTimeoutId = 0; + checkLoaded(); + }, 50); + } + } - if (this.map.isDefine && !this.ignore) { - defined[id] = exports; + inCheckLoaded = false; + } - if (req.onResourceLoad) { - req.onResourceLoad(context, this.map, this.depMaps); - } - } + Module = function (map) { + this.events = getOwn(undefEvents, map.id) || {}; + this.map = map; + this.shim = getOwn(config.shim, map.id); + this.depExports = []; + this.depMaps = []; + this.depMatched = []; + this.pluginMaps = {}; + this.depCount = 0; + + /* this.exports this.factory + this.depMaps = [], + this.enabled, this.fetched + */ + }; - //Clean up - cleanRegistry(id); + Module.prototype = { + init: function (depMaps, factory, errback, options) { + options = options || {}; - this.defined = true; + //Do not do more inits if already done. Can happen if there + //are multiple define calls for the same module. That is not + //a normal, common case, but it is also not unexpected. + if (this.inited) { + return; } - //Finished the define stage. Allow calling check again - //to allow define notifications below in the case of a - //cycle. - this.defining = false; + this.factory = factory; - if (this.defined && !this.defineEmitted) { - this.defineEmitted = true; - this.emit('defined', this.exports); - this.defineEmitComplete = true; + if (errback) { + //Register for errors on this module. + this.on('error', errback); + } else if (this.events.error) { + //If no errback already, but there are error listeners + //on this module, set up an errback to pass to the deps. + errback = bind(this, function (err) { + this.emit('error', err); + }); } - } - }, - - callPlugin: function () { - var map = this.map, - id = map.id, - //Map already normalized the prefix. - pluginMap = makeModuleMap(map.prefix); - - //Mark this as a dependency for this plugin, so it - //can be traced for cycles. - this.depMaps.push(pluginMap); - - on(pluginMap, 'defined', bind(this, function (plugin) { - var load, normalizedMap, normalizedMod, - bundleId = getOwn(bundlesMap, this.map.id), - name = this.map.name, - parentName = this.map.parentMap ? this.map.parentMap.name : null, - localRequire = context.makeRequire(map.parentMap, { - enableBuildCallback: true - }); + //Do a copy of the dependency array, so that + //source inputs are not modified. For example + //"shim" deps are passed in here directly, and + //doing a direct modification of the depMaps array + //would affect that config. + this.depMaps = depMaps && depMaps.slice(0); - //If current map is not normalized, wait for that - //normalized name to load instead of continuing. - if (this.map.unnormalized) { - //Normalize the ID if the plugin allows it. - if (plugin.normalize) { - name = plugin.normalize(name, function (name) { - return normalize(name, parentName, true); - }) || ''; - } + this.errback = errback; - //prefix and name should already be normalized, no need - //for applying map config again either. - normalizedMap = makeModuleMap(map.prefix + '!' + name, - this.map.parentMap); - on(normalizedMap, - 'defined', bind(this, function (value) { - this.init([], function () { return value; }, null, { - enabled: true, - ignore: true - }); - })); + //Indicate this module has be initialized + this.inited = true; - normalizedMod = getOwn(registry, normalizedMap.id); - if (normalizedMod) { - //Mark this as a dependency for this plugin, so it - //can be traced for cycles. - this.depMaps.push(normalizedMap); + this.ignore = options.ignore; - if (this.events.error) { - normalizedMod.on('error', bind(this, function (err) { - this.emit('error', err); - })); - } - normalizedMod.enable(); - } + //Could have option to init this module in enabled mode, + //or could have been previously marked as enabled. However, + //the dependencies are not known until init is called. So + //if enabled previously, now trigger dependencies as enabled. + if (options.enabled || this.enabled) { + //Enable this module and dependencies. + //Will call this.check() + this.enable(); + } else { + this.check(); + } + }, + + defineDep: function (i, depExports) { + //Because of cycles, defined callback for a given + //export can be called more than once. + if (!this.depMatched[i]) { + this.depMatched[i] = true; + this.depCount -= 1; + this.depExports[i] = depExports; + } + }, + fetch: function () { + if (this.fetched) { return; } + this.fetched = true; - //If a paths config, then just load that file instead to - //resolve the plugin, as it is built into that paths layer. - if (bundleId) { - this.map.url = context.nameToUrl(bundleId); - this.load(); + context.startTime = (new Date()).getTime(); + + var map = this.map; + + //If the manager is for a plugin managed resource, + //ask the plugin to load it now. + if (this.shim) { + context.makeRequire(this.map, { + enableBuildCallback: true + })(this.shim.deps || [], bind(this, function () { + return map.prefix ? this.callPlugin() : this.load(); + })); + } else { + //Regular dependency. + return map.prefix ? this.callPlugin() : this.load(); + } + }, + + load: function () { + var url = this.map.url; + + //Regular dependency. + if (!urlFetched[url]) { + urlFetched[url] = true; + context.load(this.map.id, url); + } + }, + + /** + * Checks if the module is ready to define itself, and if so, + * define it. + */ + check: function () { + if (!this.enabled || this.enabling) { return; } - load = bind(this, function (value) { - this.init([], function () { return value; }, null, { - enabled: true - }); - }); + var err, cjsModule, + id = this.map.id, + depExports = this.depExports, + exports = this.exports, + factory = this.factory; + + if (!this.inited) { + this.fetch(); + } else if (this.error) { + this.emit('error', this.error); + } else if (!this.defining) { + //The factory could trigger another require call + //that would result in checking this module to + //define itself again. If already in the process + //of doing that, skip this work. + this.defining = true; + + if (this.depCount < 1 && !this.defined) { + if (isFunction(factory)) { + //If there is an error listener, favor passing + //to that instead of throwing an error. However, + //only do it for define()'d modules. require + //errbacks should not be called for failures in + //their callbacks (#699). However if a global + //onError is set, use that. + if ((this.events.error && this.map.isDefine) || + req.onError !== defaultOnError) { + try { + exports = context.execCb(id, factory, depExports, exports); + } catch (e) { + err = e; + } + } else { + exports = context.execCb(id, factory, depExports, exports); + } + + // Favor return value over exports. If node/cjs in play, + // then will not have a return value anyway. Favor + // module.exports assignment over exports object. + if (this.map.isDefine && exports === undefined) { + cjsModule = this.module; + if (cjsModule) { + exports = cjsModule.exports; + } else if (this.usingExports) { + //exports already set the defined value. + exports = this.exports; + } + } - load.error = bind(this, function (err) { - this.inited = true; - this.error = err; - err.requireModules = [id]; + if (err) { + err.requireMap = this.map; + err.requireModules = this.map.isDefine ? [this.map.id] : null; + err.requireType = this.map.isDefine ? 'define' : 'require'; + return onError((this.error = err)); + } - //Remove temp unnormalized modules for this module, - //since they will never be resolved otherwise now. - eachProp(registry, function (mod) { - if (mod.map.id.indexOf(id + '_unnormalized') === 0) { - cleanRegistry(mod.map.id); + } else { + //Just a literal value + exports = factory; } - }); - onError(err); - }); + this.exports = exports; - //Allow plugins to load other code without having to know the - //context or how to 'complete' the load. - load.fromText = bind(this, function (text, textAlt) { - /*jslint evil: true */ - var moduleName = map.name, - moduleMap = makeModuleMap(moduleName), - hasInteractive = useInteractive; - - //As of 2.1.0, support just passing the text, to reinforce - //fromText only being called once per resource. Still - //support old style of passing moduleName but discard - //that moduleName in favor of the internal ref. - if (textAlt) { - text = textAlt; - } + if (this.map.isDefine && !this.ignore) { + defined[id] = exports; - //Turn off interactive script matching for IE for any define - //calls in the text, then turn it back on at the end. - if (hasInteractive) { - useInteractive = false; - } + if (req.onResourceLoad) { + req.onResourceLoad(context, this.map, this.depMaps); + } + } - //Prime the system by creating a module instance for - //it. - getModule(moduleMap); + //Clean up + cleanRegistry(id); - //Transfer any config to this other module. - if (hasProp(config.config, id)) { - config.config[moduleName] = config.config[id]; + this.defined = true; } - try { - req.exec(text); - } catch (e) { - return onError(makeError('fromtexteval', - 'fromText eval for ' + id + - ' failed: ' + e, - e, - [id])); - } + //Finished the define stage. Allow calling check again + //to allow define notifications below in the case of a + //cycle. + this.defining = false; - if (hasInteractive) { - useInteractive = true; + if (this.defined && !this.defineEmitted) { + this.defineEmitted = true; + this.emit('defined', this.exports); + this.defineEmitComplete = true; } - //Mark this as a dependency for the plugin - //resource - this.depMaps.push(moduleMap); + } + }, + + callPlugin: function () { + var map = this.map, + id = map.id, + //Map already normalized the prefix. + pluginMap = makeModuleMap(map.prefix); + + //Mark this as a dependency for this plugin, so it + //can be traced for cycles. + this.depMaps.push(pluginMap); + + on(pluginMap, 'defined', bind(this, function (plugin) { + var load, normalizedMap, normalizedMod, + bundleId = getOwn(bundlesMap, this.map.id), + name = this.map.name, + parentName = this.map.parentMap ? this.map.parentMap.name : null, + localRequire = context.makeRequire(map.parentMap, { + enableBuildCallback: true + }); + + //If current map is not normalized, wait for that + //normalized name to load instead of continuing. + if (this.map.unnormalized) { + //Normalize the ID if the plugin allows it. + if (plugin.normalize) { + name = plugin.normalize(name, function (name) { + return normalize(name, parentName, true); + }) || ''; + } - //Support anonymous modules. - context.completeLoad(moduleName); + //prefix and name should already be normalized, no need + //for applying map config again either. + normalizedMap = makeModuleMap(map.prefix + '!' + name, + this.map.parentMap); + on(normalizedMap, + 'defined', bind(this, function (value) { + this.init([], function () { return value; }, null, { + enabled: true, + ignore: true + }); + })); - //Bind the value of that module to the value for this - //resource ID. - localRequire([moduleName], load); - }); + normalizedMod = getOwn(registry, normalizedMap.id); + if (normalizedMod) { + //Mark this as a dependency for this plugin, so it + //can be traced for cycles. + this.depMaps.push(normalizedMap); - //Use parentName here since the plugin's name is not reliable, - //could be some weird string with no path that actually wants to - //reference the parentName's path. - plugin.load(map.name, localRequire, load, config); - })); - - context.enable(pluginMap, this); - this.pluginMaps[pluginMap.id] = pluginMap; - }, - - enable: function () { - enabledRegistry[this.map.id] = this; - this.enabled = true; - - //Set flag mentioning that the module is enabling, - //so that immediate calls to the defined callbacks - //for dependencies do not trigger inadvertent load - //with the depCount still being zero. - this.enabling = true; - - //Enable each dependency - each(this.depMaps, bind(this, function (depMap, i) { - var id, mod, handler; - - if (typeof depMap === 'string') { - //Dependency needs to be converted to a depMap - //and wired up to this module. - depMap = makeModuleMap(depMap, - (this.map.isDefine ? this.map : this.map.parentMap), - false, - !this.skipMap); - this.depMaps[i] = depMap; - - handler = getOwn(handlers, depMap.id); - - if (handler) { - this.depExports[i] = handler(this); - return; + if (this.events.error) { + normalizedMod.on('error', bind(this, function (err) { + this.emit('error', err); + })); + } + normalizedMod.enable(); + } + + return; } - this.depCount += 1; + //If a paths config, then just load that file instead to + //resolve the plugin, as it is built into that paths layer. + if (bundleId) { + this.map.url = context.nameToUrl(bundleId); + this.load(); + return; + } - on(depMap, 'defined', bind(this, function (depExports) { - this.defineDep(i, depExports); - this.check(); - })); + load = bind(this, function (value) { + this.init([], function () { return value; }, null, { + enabled: true + }); + }); - if (this.errback) { - on(depMap, 'error', bind(this, this.errback)); - } - } + load.error = bind(this, function (err) { + this.inited = true; + this.error = err; + err.requireModules = [id]; - id = depMap.id; - mod = registry[id]; + //Remove temp unnormalized modules for this module, + //since they will never be resolved otherwise now. + eachProp(registry, function (mod) { + if (mod.map.id.indexOf(id + '_unnormalized') === 0) { + cleanRegistry(mod.map.id); + } + }); - //Skip special modules like 'require', 'exports', 'module' - //Also, don't call enable if it is already enabled, - //important in circular dependency cases. - if (!hasProp(handlers, id) && mod && !mod.enabled) { - context.enable(depMap, this); - } - })); - - //Enable each plugin that is used in - //a dependency - eachProp(this.pluginMaps, bind(this, function (pluginMap) { - var mod = getOwn(registry, pluginMap.id); - if (mod && !mod.enabled) { - context.enable(pluginMap, this); - } - })); + onError(err); + }); - this.enabling = false; + //Allow plugins to load other code without having to know the + //context or how to 'complete' the load. + load.fromText = bind(this, function (text, textAlt) { + /*jslint evil: true */ + var moduleName = map.name, + moduleMap = makeModuleMap(moduleName), + hasInteractive = useInteractive; + + //As of 2.1.0, support just passing the text, to reinforce + //fromText only being called once per resource. Still + //support old style of passing moduleName but discard + //that moduleName in favor of the internal ref. + if (textAlt) { + text = textAlt; + } - this.check(); - }, + //Turn off interactive script matching for IE for any define + //calls in the text, then turn it back on at the end. + if (hasInteractive) { + useInteractive = false; + } - on: function (name, cb) { - var cbs = this.events[name]; - if (!cbs) { - cbs = this.events[name] = []; - } - cbs.push(cb); - }, + //Prime the system by creating a module instance for + //it. + getModule(moduleMap); - emit: function (name, evt) { - each(this.events[name], function (cb) { - cb(evt); - }); - if (name === 'error') { - //Now that the error handler was triggered, remove - //the listeners, since this broken Module instance - //can stay around for a while in the registry. - delete this.events[name]; - } - } - }; + //Transfer any config to this other module. + if (hasProp(config.config, id)) { + config.config[moduleName] = config.config[id]; + } - function callGetModule(args) { - //Skip modules already defined. - if (!hasProp(defined, args[0])) { - getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]); - } - } + try { + req.exec(text); + } catch (e) { + return onError(makeError('fromtexteval', + 'fromText eval for ' + id + + ' failed: ' + e, + e, + [id])); + } - function removeListener(node, func, name, ieName) { - //Favor detachEvent because of IE9 - //issue, see attachEvent/addEventListener comment elsewhere - //in this file. - if (node.detachEvent && !isOpera) { - //Probably IE. If not it will throw an error, which will be - //useful to know. - if (ieName) { - node.detachEvent(ieName, func); - } - } else { - node.removeEventListener(name, func, false); - } - } + if (hasInteractive) { + useInteractive = true; + } - /** - * Given an event from a script node, get the requirejs info from it, - * and then removes the event listeners on the node. - * @param {Event} evt - * @returns {Object} - */ - function getScriptData(evt) { - //Using currentTarget instead of target for Firefox 2.0's sake. Not - //all old browsers will be supported, but this one was easy enough - //to support and still makes sense. - var node = evt.currentTarget || evt.srcElement; - - //Remove the listeners once here. - removeListener(node, context.onScriptLoad, 'load', 'onreadystatechange'); - removeListener(node, context.onScriptError, 'error'); - - return { - node: node, - id: node && node.getAttribute('data-requiremodule') - }; - } + //Mark this as a dependency for the plugin + //resource + this.depMaps.push(moduleMap); - function intakeDefines() { - var args; + //Support anonymous modules. + context.completeLoad(moduleName); - //Any defined modules in the global queue, intake them now. - takeGlobalQueue(); + //Bind the value of that module to the value for this + //resource ID. + localRequire([moduleName], load); + }); - //Make sure any remaining defQueue items get properly processed. - while (defQueue.length) { - args = defQueue.shift(); - if (args[0] === null) { - return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1])); - } else { - //args are id, deps, factory. Should be normalized by the - //define() function. - callGetModule(args); - } - } - } + //Use parentName here since the plugin's name is not reliable, + //could be some weird string with no path that actually wants to + //reference the parentName's path. + plugin.load(map.name, localRequire, load, config); + })); - context = { - config: config, - contextName: contextName, - registry: registry, - defined: defined, - urlFetched: urlFetched, - defQueue: defQueue, - Module: Module, - makeModuleMap: makeModuleMap, - nextTick: req.nextTick, - onError: onError, + context.enable(pluginMap, this); + this.pluginMaps[pluginMap.id] = pluginMap; + }, + + enable: function () { + enabledRegistry[this.map.id] = this; + this.enabled = true; + + //Set flag mentioning that the module is enabling, + //so that immediate calls to the defined callbacks + //for dependencies do not trigger inadvertent load + //with the depCount still being zero. + this.enabling = true; + + //Enable each dependency + each(this.depMaps, bind(this, function (depMap, i) { + var id, mod, handler; + + if (typeof depMap === 'string') { + //Dependency needs to be converted to a depMap + //and wired up to this module. + depMap = makeModuleMap(depMap, + (this.map.isDefine ? this.map : this.map.parentMap), + false, + !this.skipMap); + this.depMaps[i] = depMap; + + handler = getOwn(handlers, depMap.id); + + if (handler) { + this.depExports[i] = handler(this); + return; + } - /** - * Set a configuration for the context. - * @param {Object} cfg config object to integrate. - */ - configure: function (cfg) { - //Make sure the baseUrl ends in a slash. - if (cfg.baseUrl) { - if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') { - cfg.baseUrl += '/'; - } - } + this.depCount += 1; - //Save off the paths since they require special processing, - //they are additive. - var shim = config.shim, - objs = { - paths: true, - bundles: true, - config: true, - map: true - }; - - eachProp(cfg, function (value, prop) { - if (objs[prop]) { - if (!config[prop]) { - config[prop] = {}; - } - mixin(config[prop], value, true, true); - } else { - config[prop] = value; - } - }); + on(depMap, 'defined', bind(this, function (depExports) { + this.defineDep(i, depExports); + this.check(); + })); - //Reverse map the bundles - if (cfg.bundles) { - eachProp(cfg.bundles, function (value, prop) { - each(value, function (v) { - if (v !== prop) { - bundlesMap[v] = prop; + if (this.errback) { + on(depMap, 'error', bind(this, this.errback)); } - }); - }); - } + } - //Merge shim - if (cfg.shim) { - eachProp(cfg.shim, function (value, id) { - //Normalize the structure - if (isArray(value)) { - value = { - deps: value - }; + id = depMap.id; + mod = registry[id]; + + //Skip special modules like 'require', 'exports', 'module' + //Also, don't call enable if it is already enabled, + //important in circular dependency cases. + if (!hasProp(handlers, id) && mod && !mod.enabled) { + context.enable(depMap, this); } - if ((value.exports || value.init) && !value.exportsFn) { - value.exportsFn = context.makeShimExports(value); + })); + + //Enable each plugin that is used in + //a dependency + eachProp(this.pluginMaps, bind(this, function (pluginMap) { + var mod = getOwn(registry, pluginMap.id); + if (mod && !mod.enabled) { + context.enable(pluginMap, this); } - shim[id] = value; - }); - config.shim = shim; - } + })); - //Adjust packages if necessary. - if (cfg.packages) { - each(cfg.packages, function (pkgObj) { - var location, name; + this.enabling = false; - pkgObj = typeof pkgObj === 'string' ? { name: pkgObj } : pkgObj; + this.check(); + }, - name = pkgObj.name; - location = pkgObj.location; - if (location) { - config.paths[name] = pkgObj.location; - } + on: function (name, cb) { + var cbs = this.events[name]; + if (!cbs) { + cbs = this.events[name] = []; + } + cbs.push(cb); + }, - //Save pointer to main module ID for pkg name. - //Remove leading dot in main, so main paths are normalized, - //and remove any trailing .js, since different package - //envs have different conventions: some use a module name, - //some use a file name. - config.pkgs[name] = pkgObj.name + '/' + (pkgObj.main || 'main') - .replace(currDirRegExp, '') - .replace(jsSuffixRegExp, ''); + emit: function (name, evt) { + each(this.events[name], function (cb) { + cb(evt); }); - } - - //If there are any "waiting to execute" modules in the registry, - //update the maps for them, since their info, like URLs to load, - //may have changed. - eachProp(registry, function (mod, id) { - //If module already has init called, since it is too - //late to modify them, and ignore unnormalized ones - //since they are transient. - if (!mod.inited && !mod.map.unnormalized) { - mod.map = makeModuleMap(id); + if (name === 'error') { + //Now that the error handler was triggered, remove + //the listeners, since this broken Module instance + //can stay around for a while in the registry. + delete this.events[name]; } - }); + } + }; - //If a deps array or a config callback is specified, then call - //require with those args. This is useful when require is defined as a - //config object before require.js is loaded. - if (cfg.deps || cfg.callback) { - context.require(cfg.deps || [], cfg.callback); + function callGetModule(args) { + //Skip modules already defined. + if (!hasProp(defined, args[0])) { + getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]); } - }, + } - makeShimExports: function (value) { - function fn() { - var ret; - if (value.init) { - ret = value.init.apply(global, arguments); + function removeListener(node, func, name, ieName) { + //Favor detachEvent because of IE9 + //issue, see attachEvent/addEventListener comment elsewhere + //in this file. + if (node.detachEvent && !isOpera) { + //Probably IE. If not it will throw an error, which will be + //useful to know. + if (ieName) { + node.detachEvent(ieName, func); } - return ret || (value.exports && getGlobal(value.exports)); + } else { + node.removeEventListener(name, func, false); } - return fn; - }, + } - makeRequire: function (relMap, options) { - options = options || {}; + /** + * Given an event from a script node, get the requirejs info from it, + * and then removes the event listeners on the node. + * @param {Event} evt + * @returns {Object} + */ + function getScriptData(evt) { + //Using currentTarget instead of target for Firefox 2.0's sake. Not + //all old browsers will be supported, but this one was easy enough + //to support and still makes sense. + var node = evt.currentTarget || evt.srcElement; - function localRequire(deps, callback, errback) { - var id, map, requireMod; + //Remove the listeners once here. + removeListener(node, context.onScriptLoad, 'load', 'onreadystatechange'); + removeListener(node, context.onScriptError, 'error'); - if (options.enableBuildCallback && callback && isFunction(callback)) { - callback.__requireJsBuild = true; - } + return { + node: node, + id: node && node.getAttribute('data-requiremodule') + }; + } - if (typeof deps === 'string') { - if (isFunction(callback)) { - //Invalid call - return onError(makeError('requireargs', 'Invalid require call'), errback); - } + function intakeDefines() { + var args; - //If require|exports|module are requested, get the - //value for them from the special handlers. Caveat: - //this only works while module is being defined. - if (relMap && hasProp(handlers, deps)) { - return handlers[deps](registry[relMap.id]); - } + //Any defined modules in the global queue, intake them now. + takeGlobalQueue(); - //Synchronous access to one module. If require.get is - //available (as in the Node adapter), prefer that. - if (req.get) { - return req.get(context, deps, relMap, localRequire); - } + //Make sure any remaining defQueue items get properly processed. + while (defQueue.length) { + args = defQueue.shift(); + if (args[0] === null) { + return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1])); + } else { + //args are id, deps, factory. Should be normalized by the + //define() function. + callGetModule(args); + } + } + } - //Normalize module name, if it contains . or .. - map = makeModuleMap(deps, relMap, false, true); - id = map.id; + context = { + config: config, + contextName: contextName, + registry: registry, + defined: defined, + urlFetched: urlFetched, + defQueue: defQueue, + Module: Module, + makeModuleMap: makeModuleMap, + nextTick: req.nextTick, + onError: onError, + + /** + * Set a configuration for the context. + * @param {Object} cfg config object to integrate. + */ + configure: function (cfg) { + //Make sure the baseUrl ends in a slash. + if (cfg.baseUrl) { + if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') { + cfg.baseUrl += '/'; + } + } - if (!hasProp(defined, id)) { - return onError(makeError('notloaded', 'Module name "' + - id + - '" has not been loaded yet for context: ' + - contextName + - (relMap ? '' : '. Use require([])'))); + //Save off the paths since they require special processing, + //they are additive. + var shim = config.shim, + objs = { + paths: true, + bundles: true, + config: true, + map: true + }; + + eachProp(cfg, function (value, prop) { + if (objs[prop]) { + if (!config[prop]) { + config[prop] = {}; + } + mixin(config[prop], value, true, true); + } else { + config[prop] = value; } - return defined[id]; + }); + + //Reverse map the bundles + if (cfg.bundles) { + eachProp(cfg.bundles, function (value, prop) { + each(value, function (v) { + if (v !== prop) { + bundlesMap[v] = prop; + } + }); + }); } - //Grab defines waiting in the global queue. - intakeDefines(); + //Merge shim + if (cfg.shim) { + eachProp(cfg.shim, function (value, id) { + //Normalize the structure + if (isArray(value)) { + value = { + deps: value + }; + } + if ((value.exports || value.init) && !value.exportsFn) { + value.exportsFn = context.makeShimExports(value); + } + shim[id] = value; + }); + config.shim = shim; + } - //Mark all the dependencies as needing to be loaded. - context.nextTick(function () { - //Some defines could have been added since the - //require call, collect them. - intakeDefines(); + //Adjust packages if necessary. + if (cfg.packages) { + each(cfg.packages, function (pkgObj) { + var location, name; - requireMod = getModule(makeModuleMap(null, relMap)); + pkgObj = typeof pkgObj === 'string' ? { name: pkgObj } : pkgObj; - //Store if map config should be applied to this require - //call for dependencies. - requireMod.skipMap = options.skipMap; + name = pkgObj.name; + location = pkgObj.location; + if (location) { + config.paths[name] = pkgObj.location; + } - requireMod.init(deps, callback, errback, { - enabled: true + //Save pointer to main module ID for pkg name. + //Remove leading dot in main, so main paths are normalized, + //and remove any trailing .js, since different package + //envs have different conventions: some use a module name, + //some use a file name. + config.pkgs[name] = pkgObj.name + '/' + (pkgObj.main || 'main') + .replace(currDirRegExp, '') + .replace(jsSuffixRegExp, ''); }); + } - checkLoaded(); + //If there are any "waiting to execute" modules in the registry, + //update the maps for them, since their info, like URLs to load, + //may have changed. + eachProp(registry, function (mod, id) { + //If module already has init called, since it is too + //late to modify them, and ignore unnormalized ones + //since they are transient. + if (!mod.inited && !mod.map.unnormalized) { + mod.map = makeModuleMap(id); + } }); - return localRequire; - } + //If a deps array or a config callback is specified, then call + //require with those args. This is useful when require is defined as a + //config object before require.js is loaded. + if (cfg.deps || cfg.callback) { + context.require(cfg.deps || [], cfg.callback); + } + }, - mixin(localRequire, { - isBrowser: isBrowser, - - /** - * Converts a module name + .extension into an URL path. - * *Requires* the use of a module name. It does not support using - * plain URLs like nameToUrl. - */ - toUrl: function (moduleNamePlusExt) { - var ext, - index = moduleNamePlusExt.lastIndexOf('.'), - segment = moduleNamePlusExt.split('/')[0], - isRelative = segment === '.' || segment === '..'; - - //Have a file extension alias, and it is not the - //dots from a relative path. - if (index !== -1 && (!isRelative || index > 1)) { - ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length); - moduleNamePlusExt = moduleNamePlusExt.substring(0, index); + makeShimExports: function (value) { + function fn() { + var ret; + if (value.init) { + ret = value.init.apply(global, arguments); } - - return context.nameToUrl(normalize(moduleNamePlusExt, - relMap && relMap.id, true), ext, true); - }, - - defined: function (id) { - return hasProp(defined, makeModuleMap(id, relMap, false, true).id); - }, - - specified: function (id) { - id = makeModuleMap(id, relMap, false, true).id; - return hasProp(defined, id) || hasProp(registry, id); + return ret || (value.exports && getGlobal(value.exports)); } - }); + return fn; + }, - //Only allow undef on top level require calls - if (!relMap) { - localRequire.undef = function (id) { - //Bind any waiting define() calls to this context, - //fix for #408 - takeGlobalQueue(); + makeRequire: function (relMap, options) { + options = options || {}; - var map = makeModuleMap(id, relMap, true), - mod = getOwn(registry, id); + function localRequire(deps, callback, errback) { + var id, map, requireMod; - removeScript(id); + if (options.enableBuildCallback && callback && isFunction(callback)) { + callback.__requireJsBuild = true; + } - delete defined[id]; - delete urlFetched[map.url]; - delete undefEvents[id]; + if (typeof deps === 'string') { + if (isFunction(callback)) { + //Invalid call + return onError(makeError('requireargs', 'Invalid require call'), errback); + } - //Clean queued defines too. Go backwards - //in array so that the splices do not - //mess up the iteration. - eachReverse(defQueue, function(args, i) { - if(args[0] === id) { - defQueue.splice(i, 1); + //If require|exports|module are requested, get the + //value for them from the special handlers. Caveat: + //this only works while module is being defined. + if (relMap && hasProp(handlers, deps)) { + return handlers[deps](registry[relMap.id]); } - }); - if (mod) { - //Hold on to listeners in case the - //module will be attempted to be reloaded - //using a different config. - if (mod.events.defined) { - undefEvents[id] = mod.events; + //Synchronous access to one module. If require.get is + //available (as in the Node adapter), prefer that. + if (req.get) { + return req.get(context, deps, relMap, localRequire); } - cleanRegistry(id); + //Normalize module name, if it contains . or .. + map = makeModuleMap(deps, relMap, false, true); + id = map.id; + + if (!hasProp(defined, id)) { + return onError(makeError('notloaded', 'Module name "' + + id + + '" has not been loaded yet for context: ' + + contextName + + (relMap ? '' : '. Use require([])'))); + } + return defined[id]; } - }; - } - return localRequire; - }, + //Grab defines waiting in the global queue. + intakeDefines(); - /** - * Called to enable a module if it is still in the registry - * awaiting enablement. A second arg, parent, the parent module, - * is passed in for context, when this method is overridden by - * the optimizer. Not shown here to keep code compact. - */ - enable: function (depMap) { - var mod = getOwn(registry, depMap.id); - if (mod) { - getModule(depMap).enable(); - } - }, + //Mark all the dependencies as needing to be loaded. + context.nextTick(function () { + //Some defines could have been added since the + //require call, collect them. + intakeDefines(); - /** - * Internal method used by environment adapters to complete a load event. - * A load event could be a script load or just a load pass from a synchronous - * load call. - * @param {String} moduleName the name of the module to potentially complete. - */ - completeLoad: function (moduleName) { - var found, args, mod, - shim = getOwn(config.shim, moduleName) || {}, - shExports = shim.exports; + requireMod = getModule(makeModuleMap(null, relMap)); - takeGlobalQueue(); + //Store if map config should be applied to this require + //call for dependencies. + requireMod.skipMap = options.skipMap; - while (defQueue.length) { - args = defQueue.shift(); - if (args[0] === null) { - args[0] = moduleName; - //If already found an anonymous module and bound it - //to this name, then this is some other anon module - //waiting for its completeLoad to fire. - if (found) { - break; - } - found = true; - } else if (args[0] === moduleName) { - //Found matching define call for this script! - found = true; + requireMod.init(deps, callback, errback, { + enabled: true + }); + + checkLoaded(); + }); + + return localRequire; } - callGetModule(args); - } + mixin(localRequire, { + isBrowser: isBrowser, + + /** + * Converts a module name + .extension into an URL path. + * *Requires* the use of a module name. It does not support using + * plain URLs like nameToUrl. + */ + toUrl: function (moduleNamePlusExt) { + var ext, + index = moduleNamePlusExt.lastIndexOf('.'), + segment = moduleNamePlusExt.split('/')[0], + isRelative = segment === '.' || segment === '..'; + + //Have a file extension alias, and it is not the + //dots from a relative path. + if (index !== -1 && (!isRelative || index > 1)) { + ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length); + moduleNamePlusExt = moduleNamePlusExt.substring(0, index); + } + + return context.nameToUrl(normalize(moduleNamePlusExt, + relMap && relMap.id, true), ext, true); + }, - //Do this after the cycle of callGetModule in case the result - //of those calls/init calls changes the registry. - mod = getOwn(registry, moduleName); + defined: function (id) { + return hasProp(defined, makeModuleMap(id, relMap, false, true).id); + }, - if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) { - if (config.enforceDefine && (!shExports || !getGlobal(shExports))) { - if (hasPathFallback(moduleName)) { - return; - } else { - return onError(makeError('nodefine', - 'No define call for ' + moduleName, - null, - [moduleName])); + specified: function (id) { + id = makeModuleMap(id, relMap, false, true).id; + return hasProp(defined, id) || hasProp(registry, id); } - } else { - //A script that does not call define(), so just simulate - //the call for it. - callGetModule([moduleName, (shim.deps || []), shim.exportsFn]); - } - } + }); - checkLoaded(); - }, + //Only allow undef on top level require calls + if (!relMap) { + localRequire.undef = function (id) { + //Bind any waiting define() calls to this context, + //fix for #408 + takeGlobalQueue(); - /** - * Converts a module name to a file path. Supports cases where - * moduleName may actually be just an URL. - * Note that it **does not** call normalize on the moduleName, - * it is assumed to have already been normalized. This is an - * internal API, not a public one. Use toUrl for the public API. - */ - nameToUrl: function (moduleName, ext, skipExt) { - var paths, syms, i, parentModule, url, - parentPath, bundleId, - pkgMain = getOwn(config.pkgs, moduleName); + var map = makeModuleMap(id, relMap, true), + mod = getOwn(registry, id); - if (pkgMain) { - moduleName = pkgMain; - } + removeScript(id); - bundleId = getOwn(bundlesMap, moduleName); + delete defined[id]; + delete urlFetched[map.url]; + delete undefEvents[id]; - if (bundleId) { - return context.nameToUrl(bundleId, ext, skipExt); - } + //Clean queued defines too. Go backwards + //in array so that the splices do not + //mess up the iteration. + eachReverse(defQueue, function(args, i) { + if(args[0] === id) { + defQueue.splice(i, 1); + } + }); + + if (mod) { + //Hold on to listeners in case the + //module will be attempted to be reloaded + //using a different config. + if (mod.events.defined) { + undefEvents[id] = mod.events; + } - //If a colon is in the URL, it indicates a protocol is used and it is just - //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?) - //or ends with .js, then assume the user meant to use an url and not a module id. - //The slash is important for protocol-less URLs as well as full paths. - if (req.jsExtRegExp.test(moduleName)) { - //Just a plain path, not module name lookup, so just return it. - //Add extension if it is included. This is a bit wonky, only non-.js things pass - //an extension, this method probably needs to be reworked. - url = moduleName + (ext || ''); - } else { - //A module that needs to be converted to a path. - paths = config.paths; - - syms = moduleName.split('/'); - //For each module name segment, see if there is a path - //registered for it. Start with most specific name - //and work up from it. - for (i = syms.length; i > 0; i -= 1) { - parentModule = syms.slice(0, i).join('/'); - - parentPath = getOwn(paths, parentModule); - if (parentPath) { - //If an array, it means there are a few choices, - //Choose the one that is desired - if (isArray(parentPath)) { - parentPath = parentPath[0]; + cleanRegistry(id); + } + }; + } + + return localRequire; + }, + + /** + * Called to enable a module if it is still in the registry + * awaiting enablement. A second arg, parent, the parent module, + * is passed in for context, when this method is overridden by + * the optimizer. Not shown here to keep code compact. + */ + enable: function (depMap) { + var mod = getOwn(registry, depMap.id); + if (mod) { + getModule(depMap).enable(); + } + }, + + /** + * Internal method used by environment adapters to complete a load event. + * A load event could be a script load or just a load pass from a synchronous + * load call. + * @param {String} moduleName the name of the module to potentially complete. + */ + completeLoad: function (moduleName) { + var found, args, mod, + shim = getOwn(config.shim, moduleName) || {}, + shExports = shim.exports; + + takeGlobalQueue(); + + while (defQueue.length) { + args = defQueue.shift(); + if (args[0] === null) { + args[0] = moduleName; + //If already found an anonymous module and bound it + //to this name, then this is some other anon module + //waiting for its completeLoad to fire. + if (found) { + break; } - syms.splice(0, i, parentPath); - break; + found = true; + } else if (args[0] === moduleName) { + //Found matching define call for this script! + found = true; } + + callGetModule(args); } - //Join the path parts together, then figure out if baseUrl is needed. - url = syms.join('/'); - url += (ext || (/^data\:|\?/.test(url) || skipExt ? '' : '.js')); - url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url; - } + //Do this after the cycle of callGetModule in case the result + //of those calls/init calls changes the registry. + mod = getOwn(registry, moduleName); + + if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) { + if (config.enforceDefine && (!shExports || !getGlobal(shExports))) { + if (hasPathFallback(moduleName)) { + return; + } else { + return onError(makeError('nodefine', + 'No define call for ' + moduleName, + null, + [moduleName])); + } + } else { + //A script that does not call define(), so just simulate + //the call for it. + callGetModule([moduleName, (shim.deps || []), shim.exportsFn]); + } + } - return config.urlArgs ? url + - ((url.indexOf('?') === -1 ? '?' : '&') + - config.urlArgs) : url; - }, + checkLoaded(); + }, + + /** + * Converts a module name to a file path. Supports cases where + * moduleName may actually be just an URL. + * Note that it **does not** call normalize on the moduleName, + * it is assumed to have already been normalized. This is an + * internal API, not a public one. Use toUrl for the public API. + */ + nameToUrl: function (moduleName, ext, skipExt) { + var paths, syms, i, parentModule, url, + parentPath, bundleId, + pkgMain = getOwn(config.pkgs, moduleName); + + if (pkgMain) { + moduleName = pkgMain; + } - //Delegates to req.load. Broken out as a separate function to - //allow overriding in the optimizer. - load: function (id, url) { - req.load(context, id, url); - }, + bundleId = getOwn(bundlesMap, moduleName); - /** - * Executes a module callback function. Broken out as a separate function - * solely to allow the build system to sequence the files in the built - * layer in the right sequence. - * - * @private - */ - execCb: function (name, callback, args, exports) { - return callback.apply(exports, args); - }, + if (bundleId) { + return context.nameToUrl(bundleId, ext, skipExt); + } - /** - * callback for script loads, used to check status of loading. - * - * @param {Event} evt the event from the browser for the script - * that was loaded. - */ - onScriptLoad: function (evt) { - //Using currentTarget instead of target for Firefox 2.0's sake. Not - //all old browsers will be supported, but this one was easy enough - //to support and still makes sense. - if (evt.type === 'load' || - (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) { - //Reset interactive script so a script node is not held onto for - //to long. - interactiveScript = null; + //If a colon is in the URL, it indicates a protocol is used and it is just + //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?) + //or ends with .js, then assume the user meant to use an url and not a module id. + //The slash is important for protocol-less URLs as well as full paths. + if (req.jsExtRegExp.test(moduleName)) { + //Just a plain path, not module name lookup, so just return it. + //Add extension if it is included. This is a bit wonky, only non-.js things pass + //an extension, this method probably needs to be reworked. + url = moduleName + (ext || ''); + } else { + //A module that needs to be converted to a path. + paths = config.paths; + + syms = moduleName.split('/'); + //For each module name segment, see if there is a path + //registered for it. Start with most specific name + //and work up from it. + for (i = syms.length; i > 0; i -= 1) { + parentModule = syms.slice(0, i).join('/'); + + parentPath = getOwn(paths, parentModule); + if (parentPath) { + //If an array, it means there are a few choices, + //Choose the one that is desired + if (isArray(parentPath)) { + parentPath = parentPath[0]; + } + syms.splice(0, i, parentPath); + break; + } + } - //Pull out the name of the module and the context. + //Join the path parts together, then figure out if baseUrl is needed. + url = syms.join('/'); + url += (ext || (/^data\:|\?/.test(url) || skipExt ? '' : '.js')); + url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url; + } + + return config.urlArgs ? url + + ((url.indexOf('?') === -1 ? '?' : '&') + + config.urlArgs) : url; + }, + + //Delegates to req.load. Broken out as a separate function to + //allow overriding in the optimizer. + load: function (id, url) { + req.load(context, id, url); + }, + + /** + * Executes a module callback function. Broken out as a separate function + * solely to allow the build system to sequence the files in the built + * layer in the right sequence. + * + * @private + */ + execCb: function (name, callback, args, exports) { + return callback.apply(exports, args); + }, + + /** + * callback for script loads, used to check status of loading. + * + * @param {Event} evt the event from the browser for the script + * that was loaded. + */ + onScriptLoad: function (evt) { + //Using currentTarget instead of target for Firefox 2.0's sake. Not + //all old browsers will be supported, but this one was easy enough + //to support and still makes sense. + if (evt.type === 'load' || + (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) { + //Reset interactive script so a script node is not held onto for + //to long. + interactiveScript = null; + + //Pull out the name of the module and the context. + var data = getScriptData(evt); + context.completeLoad(data.id); + } + }, + + /** + * Callback for script errors. + */ + onScriptError: function (evt) { var data = getScriptData(evt); - context.completeLoad(data.id); + if (!hasPathFallback(data.id)) { + return onError(makeError('scripterror', 'Script error for: ' + data.id, evt, [data.id])); + } } - }, + }; - /** - * Callback for script errors. - */ - onScriptError: function (evt) { - var data = getScriptData(evt); - if (!hasPathFallback(data.id)) { - return onError(makeError('scripterror', 'Script error for: ' + data.id, evt, [data.id])); + context.require = context.makeRequire(); + return context; + } + + /** + * Main entry point. + * + * If the only argument to require is a string, then the module that + * is represented by that string is fetched for the appropriate context. + * + * If the first argument is an array, then it will be treated as an array + * of dependency string names to fetch. An optional function callback can + * be specified to execute when all of those dependencies are available. + * + * Make a local req variable to help Caja compliance (it assumes things + * on a require that are not standardized), and to give a short + * name for minification/local scope use. + */ + req = requirejs = function (deps, callback, errback, optional) { + + //Find the right context, use default + var context, config, + contextName = defContextName; + + // Determine if have config object in the call. + if (!isArray(deps) && typeof deps !== 'string') { + // deps is a config object + config = deps; + if (isArray(callback)) { + // Adjust args if there are dependencies + deps = callback; + callback = errback; + errback = optional; + } else { + deps = []; } } - }; - context.require = context.makeRequire(); - return context; - } - - /** - * Main entry point. - * - * If the only argument to require is a string, then the module that - * is represented by that string is fetched for the appropriate context. - * - * If the first argument is an array, then it will be treated as an array - * of dependency string names to fetch. An optional function callback can - * be specified to execute when all of those dependencies are available. - * - * Make a local req variable to help Caja compliance (it assumes things - * on a require that are not standardized), and to give a short - * name for minification/local scope use. - */ - req = requirejs = function (deps, callback, errback, optional) { - - //Find the right context, use default - var context, config, - contextName = defContextName; - - // Determine if have config object in the call. - if (!isArray(deps) && typeof deps !== 'string') { - // deps is a config object - config = deps; - if (isArray(callback)) { - // Adjust args if there are dependencies - deps = callback; - callback = errback; - errback = optional; - } else { - deps = []; + if (config && config.context) { + contextName = config.context; } - } - if (config && config.context) { - contextName = config.context; - } + context = getOwn(contexts, contextName); + if (!context) { + context = contexts[contextName] = req.s.newContext(contextName); + } - context = getOwn(contexts, contextName); - if (!context) { - context = contexts[contextName] = req.s.newContext(contextName); - } + if (config) { + context.configure(config); + } - if (config) { - context.configure(config); - } + return context.require(deps, callback, errback); + }; - return context.require(deps, callback, errback); - }; + /** + * Support require.config() to make it easier to cooperate with other + * AMD loaders on globally agreed names. + */ + req.config = function (config) { + return req(config); + }; - /** - * Support require.config() to make it easier to cooperate with other - * AMD loaders on globally agreed names. - */ - req.config = function (config) { - return req(config); - }; + /** + * Execute something after the current tick + * of the event loop. Override for other envs + * that have a better solution than setTimeout. + * @param {Function} fn function to execute later. + */ + req.nextTick = typeof setTimeout !== 'undefined' ? function (fn) { + setTimeout(fn, 4); + } : function (fn) { fn(); }; - /** - * Execute something after the current tick - * of the event loop. Override for other envs - * that have a better solution than setTimeout. - * @param {Function} fn function to execute later. - */ - req.nextTick = typeof setTimeout !== 'undefined' ? function (fn) { - setTimeout(fn, 4); - } : function (fn) { fn(); }; - - /** - * Export require as a global, but only if it does not already exist. - */ - if (!require) { - require = req; - } - - req.version = version; - - //Used to filter out dependencies that are already paths. - req.jsExtRegExp = /^\/|:|\?|\.js$/; - req.isBrowser = isBrowser; - s = req.s = { - contexts: contexts, - newContext: newContext - }; + /** + * Export require as a global, but only if it does not already exist. + */ + if (!require) { + require = req; + } - //Create default context. - req({}); - - //Exports some context-sensitive methods on global require. - each([ - 'toUrl', - 'undef', - 'defined', - 'specified' - ], function (prop) { - //Reference from contexts instead of early binding to default context, - //so that during builds, the latest instance of the default context - //with its config gets used. - req[prop] = function () { - var ctx = contexts[defContextName]; - return ctx.require[prop].apply(ctx, arguments); + req.version = version; + + //Used to filter out dependencies that are already paths. + req.jsExtRegExp = /^\/|:|\?|\.js$/; + req.isBrowser = isBrowser; + s = req.s = { + contexts: contexts, + newContext: newContext }; - }); - - if (isBrowser) { - head = s.head = document.getElementsByTagName('head')[0]; - //If BASE tag is in play, using appendChild is a problem for IE6. - //When that browser dies, this can be removed. Details in this jQuery bug: - //http://dev.jquery.com/ticket/2709 - baseElement = document.getElementsByTagName('base')[0]; - if (baseElement) { - head = s.head = baseElement.parentNode; - } - } - - /** - * Any errors that require explicitly generates will be passed to this - * function. Intercept/override it if you want custom error handling. - * @param {Error} err the error object. - */ - req.onError = defaultOnError; - - /** - * Creates the node for the load command. Only used in browser envs. - */ - req.createNode = function (config, moduleName, url) { - var node = config.xhtml ? - document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') : - document.createElement('script'); - node.type = config.scriptType || 'text/javascript'; - node.charset = 'utf-8'; - node.async = true; - return node; - }; - /** - * Does the request to load a module for the browser case. - * Make this a separate function to allow other environments - * to override it. - * - * @param {Object} context the require context to find state. - * @param {String} moduleName the name of the module. - * @param {Object} url the URL to the module. - */ - req.load = function (context, moduleName, url) { - var config = (context && context.config) || {}, - node; - if (isBrowser) { - //In the browser so use a script tag - node = req.createNode(config, moduleName, url); - - node.setAttribute('data-requirecontext', context.contextName); - node.setAttribute('data-requiremodule', moduleName); - - //Set up load listener. Test attachEvent first because IE9 has - //a subtle issue in its addEventListener and script onload firings - //that do not match the behavior of all other browsers with - //addEventListener support, which fire the onload event for a - //script right after the script execution. See: - //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution - //UNFORTUNATELY Opera implements attachEvent but does not follow the script - //script execution mode. - if (node.attachEvent && - //Check if node.attachEvent is artificially added by custom script or - //natively supported by browser - //read https://github.com/jrburke/requirejs/issues/187 - //if we can NOT find [native code] then it must NOT natively supported. - //in IE8, node.attachEvent does not have toString() - //Note the test for "[native code" with no closing brace, see: - //https://github.com/jrburke/requirejs/issues/273 - !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) && - !isOpera) { - //Probably IE. IE (at least 6-8) do not fire - //script onload right after executing the script, so - //we cannot tie the anonymous define call to a name. - //However, IE reports the script as being in 'interactive' - //readyState at the time of the define call. - useInteractive = true; - - node.attachEvent('onreadystatechange', context.onScriptLoad); - //It would be great to add an error handler here to catch - //404s in IE9+. However, onreadystatechange will fire before - //the error handler, so that does not help. If addEventListener - //is used, then IE will fire error before load, but we cannot - //use that pathway given the connect.microsoft.com issue - //mentioned above about not doing the 'script execute, - //then fire the script load event listener before execute - //next script' that other browsers do. - //Best hope: IE10 fixes the issues, - //and then destroys all installs of IE 6-9. - //node.attachEvent('onerror', context.onScriptError); - } else { - node.addEventListener('load', context.onScriptLoad, false); - node.addEventListener('error', context.onScriptError, false); - } - node.src = url; + //Create default context. + req({}); + + //Exports some context-sensitive methods on global require. + each([ + 'toUrl', + 'undef', + 'defined', + 'specified' + ], function (prop) { + //Reference from contexts instead of early binding to default context, + //so that during builds, the latest instance of the default context + //with its config gets used. + req[prop] = function () { + var ctx = contexts[defContextName]; + return ctx.require[prop].apply(ctx, arguments); + }; + }); - //For some cache cases in IE 6-8, the script executes before the end - //of the appendChild execution, so to tie an anonymous define - //call to the module name (which is stored on the node), hold on - //to a reference to this node, but clear after the DOM insertion. - currentlyAddingScript = node; + if (isBrowser) { + head = s.head = document.getElementsByTagName('head')[0]; + //If BASE tag is in play, using appendChild is a problem for IE6. + //When that browser dies, this can be removed. Details in this jQuery bug: + //http://dev.jquery.com/ticket/2709 + baseElement = document.getElementsByTagName('base')[0]; if (baseElement) { - head.insertBefore(node, baseElement); - } else { - head.appendChild(node); - } - currentlyAddingScript = null; - - return node; - } else if (isWebWorker) { - try { - //In a web worker, use importScripts. This is not a very - //efficient use of importScripts, importScripts will block until - //its script is downloaded and evaluated. However, if web workers - //are in play, the expectation that a build has been done so that - //only one script needs to be loaded anyway. This may need to be - //reevaluated if other use cases become common. - importScripts(url); - - //Account for anonymous modules - context.completeLoad(moduleName); - } catch (e) { - context.onError(makeError('importscripts', - 'importScripts failed for ' + - moduleName + ' at ' + url, - e, - [moduleName])); + head = s.head = baseElement.parentNode; } } - }; - function getInteractiveScript() { - if (interactiveScript && interactiveScript.readyState === 'interactive') { - return interactiveScript; - } + /** + * Any errors that require explicitly generates will be passed to this + * function. Intercept/override it if you want custom error handling. + * @param {Error} err the error object. + */ + req.onError = defaultOnError; + + /** + * Creates the node for the load command. Only used in browser envs. + */ + req.createNode = function (config, moduleName, url) { + var node = config.xhtml ? + document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') : + document.createElement('script'); + node.type = config.scriptType || 'text/javascript'; + node.charset = 'utf-8'; + node.async = true; + return node; + }; - eachReverse(scripts(), function (script) { - if (script.readyState === 'interactive') { - return (interactiveScript = script); + /** + * Does the request to load a module for the browser case. + * Make this a separate function to allow other environments + * to override it. + * + * @param {Object} context the require context to find state. + * @param {String} moduleName the name of the module. + * @param {Object} url the URL to the module. + */ + req.load = function (context, moduleName, url) { + var config = (context && context.config) || {}, + node; + if (isBrowser) { + //In the browser so use a script tag + node = req.createNode(config, moduleName, url); + + node.setAttribute('data-requirecontext', context.contextName); + node.setAttribute('data-requiremodule', moduleName); + + //Set up load listener. Test attachEvent first because IE9 has + //a subtle issue in its addEventListener and script onload firings + //that do not match the behavior of all other browsers with + //addEventListener support, which fire the onload event for a + //script right after the script execution. See: + //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution + //UNFORTUNATELY Opera implements attachEvent but does not follow the script + //script execution mode. + if (node.attachEvent && + //Check if node.attachEvent is artificially added by custom script or + //natively supported by browser + //read https://github.com/jrburke/requirejs/issues/187 + //if we can NOT find [native code] then it must NOT natively supported. + //in IE8, node.attachEvent does not have toString() + //Note the test for "[native code" with no closing brace, see: + //https://github.com/jrburke/requirejs/issues/273 + !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) && + !isOpera) { + //Probably IE. IE (at least 6-8) do not fire + //script onload right after executing the script, so + //we cannot tie the anonymous define call to a name. + //However, IE reports the script as being in 'interactive' + //readyState at the time of the define call. + useInteractive = true; + + node.attachEvent('onreadystatechange', context.onScriptLoad); + //It would be great to add an error handler here to catch + //404s in IE9+. However, onreadystatechange will fire before + //the error handler, so that does not help. If addEventListener + //is used, then IE will fire error before load, but we cannot + //use that pathway given the connect.microsoft.com issue + //mentioned above about not doing the 'script execute, + //then fire the script load event listener before execute + //next script' that other browsers do. + //Best hope: IE10 fixes the issues, + //and then destroys all installs of IE 6-9. + //node.attachEvent('onerror', context.onScriptError); + } else { + node.addEventListener('load', context.onScriptLoad, false); + node.addEventListener('error', context.onScriptError, false); + } + node.src = url; + + //For some cache cases in IE 6-8, the script executes before the end + //of the appendChild execution, so to tie an anonymous define + //call to the module name (which is stored on the node), hold on + //to a reference to this node, but clear after the DOM insertion. + currentlyAddingScript = node; + if (baseElement) { + head.insertBefore(node, baseElement); + } else { + head.appendChild(node); + } + currentlyAddingScript = null; + + return node; + } else if (isWebWorker) { + try { + //In a web worker, use importScripts. This is not a very + //efficient use of importScripts, importScripts will block until + //its script is downloaded and evaluated. However, if web workers + //are in play, the expectation that a build has been done so that + //only one script needs to be loaded anyway. This may need to be + //reevaluated if other use cases become common. + importScripts(url); + + //Account for anonymous modules + context.completeLoad(moduleName); + } catch (e) { + context.onError(makeError('importscripts', + 'importScripts failed for ' + + moduleName + ' at ' + url, + e, + [moduleName])); + } } - }); - return interactiveScript; - } - - //Look for a data-main script attribute, which could also adjust the baseUrl. - if (isBrowser && !cfg.skipDataMain) { - //Figure out baseUrl. Get it from the script tag with require.js in it. - eachReverse(scripts(), function (script) { - //Set the 'head' where we can append children by - //using the script's parent. - if (!head) { - head = script.parentNode; + }; + + function getInteractiveScript() { + if (interactiveScript && interactiveScript.readyState === 'interactive') { + return interactiveScript; } - //Look for a data-main attribute to set main script for the page - //to load. If it is there, the path to data main becomes the - //baseUrl, if it is not already set. - dataMain = script.getAttribute('data-main'); - if (dataMain) { - //Preserve dataMain in case it is a path (i.e. contains '?') - mainScript = dataMain; - - //Set final baseUrl if there is not already an explicit one. - if (!cfg.baseUrl) { - //Pull off the directory of data-main for use as the - //baseUrl. - src = mainScript.split('/'); - mainScript = src.pop(); - subPath = src.length ? src.join('/') + '/' : './'; - - cfg.baseUrl = subPath; + eachReverse(scripts(), function (script) { + if (script.readyState === 'interactive') { + return (interactiveScript = script); } + }); + return interactiveScript; + } - //Strip off any trailing .js since mainScript is now - //like a module name. - mainScript = mainScript.replace(jsSuffixRegExp, ''); + //Look for a data-main script attribute, which could also adjust the baseUrl. + if (isBrowser && !cfg.skipDataMain) { + //Figure out baseUrl. Get it from the script tag with require.js in it. + eachReverse(scripts(), function (script) { + //Set the 'head' where we can append children by + //using the script's parent. + if (!head) { + head = script.parentNode; + } - //If mainScript is still a path, fall back to dataMain - if (req.jsExtRegExp.test(mainScript)) { + //Look for a data-main attribute to set main script for the page + //to load. If it is there, the path to data main becomes the + //baseUrl, if it is not already set. + dataMain = script.getAttribute('data-main'); + if (dataMain) { + //Preserve dataMain in case it is a path (i.e. contains '?') mainScript = dataMain; - } - //Put the data-main script in the files to load. - cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript]; + //Set final baseUrl if there is not already an explicit one. + if (!cfg.baseUrl) { + //Pull off the directory of data-main for use as the + //baseUrl. + src = mainScript.split('/'); + mainScript = src.pop(); + subPath = src.length ? src.join('/') + '/' : './'; - return true; - } - }); - } - - /** - * The function that handles definitions of modules. Differs from - * require() in that a string for the module should be the first argument, - * and the function to execute after dependencies are loaded should - * return a value to define the module corresponding to the first argument's - * name. - */ - define = function (name, deps, callback) { - var node, context; - - //Allow for anonymous modules - if (typeof name !== 'string') { - //Adjust args appropriately - callback = deps; - deps = name; - name = null; - } + cfg.baseUrl = subPath; + } + + //Strip off any trailing .js since mainScript is now + //like a module name. + mainScript = mainScript.replace(jsSuffixRegExp, ''); + + //If mainScript is still a path, fall back to dataMain + if (req.jsExtRegExp.test(mainScript)) { + mainScript = dataMain; + } - //This module may not have dependencies - if (!isArray(deps)) { - callback = deps; - deps = null; + //Put the data-main script in the files to load. + cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript]; + + return true; + } + }); } - //If no name, and callback is a function, then figure out if it a - //CommonJS thing with dependencies. - if (!deps && isFunction(callback)) { - deps = []; - //Remove comments from the callback string, - //look for require calls, and pull them into the dependencies, - //but only if there are function args. - if (callback.length) { - callback - .toString() - .replace(commentRegExp, '') - .replace(cjsRequireRegExp, function (match, dep) { - deps.push(dep); - }); + /** + * The function that handles definitions of modules. Differs from + * require() in that a string for the module should be the first argument, + * and the function to execute after dependencies are loaded should + * return a value to define the module corresponding to the first argument's + * name. + */ + define = function (name, deps, callback) { + var node, context; + + //Allow for anonymous modules + if (typeof name !== 'string') { + //Adjust args appropriately + callback = deps; + deps = name; + name = null; + } - //May be a CommonJS thing even without require calls, but still - //could use exports, and module. Avoid doing exports and module - //work though if it just needs require. - //REQUIRES the function to expect the CommonJS variables in the - //order listed below. - deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps); + //This module may not have dependencies + if (!isArray(deps)) { + callback = deps; + deps = null; } - } - //If in IE 6-8 and hit an anonymous define() call, do the interactive - //work. - if (useInteractive) { - node = currentlyAddingScript || getInteractiveScript(); - if (node) { - if (!name) { - name = node.getAttribute('data-requiremodule'); + //If no name, and callback is a function, then figure out if it a + //CommonJS thing with dependencies. + if (!deps && isFunction(callback)) { + deps = []; + //Remove comments from the callback string, + //look for require calls, and pull them into the dependencies, + //but only if there are function args. + if (callback.length) { + callback + .toString() + .replace(commentRegExp, '') + .replace(cjsRequireRegExp, function (match, dep) { + deps.push(dep); + }); + + //May be a CommonJS thing even without require calls, but still + //could use exports, and module. Avoid doing exports and module + //work though if it just needs require. + //REQUIRES the function to expect the CommonJS variables in the + //order listed below. + deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps); } - context = contexts[node.getAttribute('data-requirecontext')]; } - } - //Always save off evaluating the def call until the script onload handler. - //This allows multiple modules to be in a file without prematurely - //tracing dependencies, and allows for anonymous module support, - //where the module name is not known until the script onload event - //occurs. If no context, use the global queue, and get it processed - //in the onscript load callback. - (context ? context.defQueue : globalDefQueue).push([name, deps, callback]); - }; + //If in IE 6-8 and hit an anonymous define() call, do the interactive + //work. + if (useInteractive) { + node = currentlyAddingScript || getInteractiveScript(); + if (node) { + if (!name) { + name = node.getAttribute('data-requiremodule'); + } + context = contexts[node.getAttribute('data-requirecontext')]; + } + } - define.amd = { - jQuery: true - }; + //Always save off evaluating the def call until the script onload handler. + //This allows multiple modules to be in a file without prematurely + //tracing dependencies, and allows for anonymous module support, + //where the module name is not known until the script onload event + //occurs. If no context, use the global queue, and get it processed + //in the onscript load callback. + (context ? context.defQueue : globalDefQueue).push([name, deps, callback]); + }; + define.amd = { + jQuery: true + }; - /** - * Executes the text. Normally just uses eval, but can be modified - * to use a better, environment-specific call. Only used for transpiling - * loader plugins, not for plain JS modules. - * @param {String} text the text to execute/evaluate. - */ - req.exec = function (text) { - /*jslint evil: true */ - return eval(text); - }; - //Set up with config info. - req(cfg); -}(this)); \ No newline at end of file + /** + * Executes the text. Normally just uses eval, but can be modified + * to use a better, environment-specific call. Only used for transpiling + * loader plugins, not for plain JS modules. + * @param {String} text the text to execute/evaluate. + */ + req.exec = function (text) { + /*jslint evil: true */ + return eval(text); + }; + + //Set up with config info. + req(cfg); + }(this)); + + return { + requirejs: requirejs, + require: require, + define: define + }; +}()); diff --git a/assets/js/load-options.js b/assets/js/load-options.js index 668cd59..e1f8bde 100644 --- a/assets/js/load-options.js +++ b/assets/js/load-options.js @@ -4,7 +4,7 @@ * * */ -define([ +sourcejs.amd.define([ 'jquery', 'text!/api/options', 'sourceModules/inlineOptions' @@ -17,4 +17,4 @@ define([ $.extend(true, sourceOptions, inlineOptions); return sourceOptions; -}); \ No newline at end of file +}); diff --git a/assets/js/modules/auth.js b/assets/js/modules/auth.js index dd5a117..e4ed95b 100644 --- a/assets/js/modules/auth.js +++ b/assets/js/modules/auth.js @@ -1,8 +1,8 @@ -define([ +sourcejs.amd.define([ 'jquery', 'sourceModules/module' ], function($, Module) { - + 'use strict'; /** @@ -152,4 +152,4 @@ define([ }; return Auth; -}); \ No newline at end of file +}); diff --git a/assets/js/modules/browser.js b/assets/js/modules/browser.js index 19f4afb..b46f367 100644 --- a/assets/js/modules/browser.js +++ b/assets/js/modules/browser.js @@ -1,6 +1,9 @@ -"use strict"; +'use strict'; -define(["sourceLib/jquery.mb.browser"], function() { +sourcejs.amd.define([ + 'jquery', + 'sourceLib/jquery.mb.browser' +], function($) { //Browser context classes var browserClasses = { msie: "ie", @@ -30,4 +33,4 @@ define(["sourceLib/jquery.mb.browser"], function() { $('html').addClass(classString); return $.browser; -}); \ No newline at end of file +}); diff --git a/assets/js/modules/clarifyInSpec.js b/assets/js/modules/clarifyInSpec.js index cda8d6a..5e3401d 100644 --- a/assets/js/modules/clarifyInSpec.js +++ b/assets/js/modules/clarifyInSpec.js @@ -8,7 +8,7 @@ 'use strict'; -define([ +sourcejs.amd.define([ 'jquery', 'sourceModules/module', 'sourceModules/sections', @@ -73,4 +73,4 @@ define([ }; return new ClarifyInSpec(); -}); \ No newline at end of file +}); diff --git a/assets/js/modules/codeSource.js b/assets/js/modules/codeSource.js index 931e7ea..ceeb04f 100644 --- a/assets/js/modules/codeSource.js +++ b/assets/js/modules/codeSource.js @@ -4,7 +4,7 @@ * * */ -define([ +sourcejs.amd.define([ "jquery", "source/load-options", "sourceModules/utils", @@ -13,7 +13,7 @@ define([ "sourceLib/codeFormat", "sourceModules/innerNavigation", "sourceLib/prism/prism" -], function($, options, utils, Css, browser, codeFormat, innerNavigation) { +], function($, options, utils, Css, browser, codeFormat, innerNavigation, Prism) { 'use strict'; if (!(browser.msie && parseInt(browser.version, 10) < 9)) { // and if not ie < 9 @@ -170,7 +170,9 @@ define([ }; var afterActivation = function() { - var sources = $('.' + SourceCode); + var sources = $('.' + SourceCode).filter(function() { + return !$(this).next().hasClass('source_ignore'); + }); sources.addClass(SourceCodeShow); //Scroll to section @@ -192,7 +194,9 @@ define([ if (!prepared) { fillCodeContainers(); prepareCodeBlocks(); - $('pre').removeAttr('style'); + $('pre').filter(function() { + return !$(this).closest('.source_source-code').next().hasClass('source_ignore'); + }).removeAttr('style'); prepared = true; } afterActivation(); @@ -228,4 +232,4 @@ define([ showStaticCode(); }); } -}); \ No newline at end of file +}); diff --git a/assets/js/modules/couch.js b/assets/js/modules/couch.js index cde812f..2559e02 100644 --- a/assets/js/modules/couch.js +++ b/assets/js/modules/couch.js @@ -7,7 +7,7 @@ * * */ -define([ +sourcejs.amd.define([ 'jquery', 'sourceModules/module', 'sourceModules/utils', @@ -133,4 +133,4 @@ define([ return new Couch(); -}); \ No newline at end of file +}); diff --git a/assets/js/modules/css.js b/assets/js/modules/css.js index c854bd2..d3587e1 100644 --- a/assets/js/modules/css.js +++ b/assets/js/modules/css.js @@ -1,6 +1,6 @@ 'use strict'; -define(["source/load-options"], function(options) { +sourcejs.amd.define(["source/load-options"], function(options) { function Css (url, cat) { this.url = url; this.cat = cat || 'plugin'; @@ -9,17 +9,17 @@ define(["source/load-options"], function(options) { } Css.prototype.inject = function(){ - var href = this.url; + var href = this.url; - var link = document.createElement("link"); + var link = document.createElement("link"); link.type = "text/css"; link.rel = "stylesheet"; link.dataset.source = this.cat; - link.href = href; + link.href = href; document.getElementsByTagName("head")[0].appendChild(link); }; return Css; -}); \ No newline at end of file +}); diff --git a/assets/js/modules/globalNav.js b/assets/js/modules/globalNav.js index 55f93dc..59f664c 100644 --- a/assets/js/modules/globalNav.js +++ b/assets/js/modules/globalNav.js @@ -4,7 +4,7 @@ * * */ -define([ +sourcejs.amd.define([ "jquery", "sourceModules/module", "sourceModules/utils", diff --git a/assets/js/modules/headerFooter.js b/assets/js/modules/headerFooter.js index 554adb9..699d590 100644 --- a/assets/js/modules/headerFooter.js +++ b/assets/js/modules/headerFooter.js @@ -1,97 +1,79 @@ -define(['source/load-options'], function(options) { +sourcejs.amd.define([ + 'jquery', + 'source/load-options' +], function($, options) { 'use strict'; - var $header = $(".source_header"); - var $footer = $(".source_footer"); + $(function(){ + var headerEl = document.querySelector('.source_header'); + var footerEl = document.querySelector('.source_footer'); - if(options.modulesEnabled.headerFooter) { - var headerExists = $header.length > 0; - var footerExists = $footer.length > 0; + if(options.modulesEnabled.headerFooter) { + //Header and Footer injection + var $sourceContainer = $('.source_container'); - //Header and Footer injection - var source_container = $('.source_container'); - - if (!headerExists) { - source_container.prepend($('
')); - } - - if (!footerExists) { - source_container.append($('')); - } + if (!headerEl) { + $sourceContainer.prepend($('
')); + } - if (source_container.length && !(headerExists && footerExists)) { - //some empty page - if (!source_container.contents().length) { - source_container.append($('
Welcome to Source!
')); + if (!footerEl) { + $sourceContainer.append($('')); } - var insertHeader = function(data) { - $('.source_header').replaceWith(data.responseText); - }; + if ($sourceContainer.length && !(headerEl && footerEl)) { + //some empty page + if (!$sourceContainer.contents().length) { + $sourceContainer.append($('
Welcome to Source!
')); + } + + var insertHeader = function(data) { + $('.source_header').replaceWith(data.responseText); + }; - var headerFile = 'header.inc.html'; - var footerFile = 'footer.inc.html'; + var headerFile = 'header.inc.html'; + var footerFile = 'footer.inc.html'; - $.ajax({ - url:"/assets/templates/"+headerFile, - async:true, - complete:function (data, status) { - if (status === 'success') { - insertHeader(data); - } else { - $.ajax({ - url:"/source/assets/templates/"+headerFile, - async:true, - complete:function (data) { - insertHeader(data); - } - }); + $.ajax({ + url:"/assets/templates/"+headerFile, + async:true, + complete:function (data, status) { + if (status === 'success') { + insertHeader(data); + } else { + $.ajax({ + url:"/source/assets/templates/"+headerFile, + async:true, + complete:function (data) { + insertHeader(data); + } + }); + } } - } - }); + }); - var insertFooter = function(data) { - $('.source_footer').replaceWith(data.responseText); - }; + var insertFooter = function(data) { + $('.source_footer').replaceWith(data.responseText); + }; - $.ajax({ - url:"/assets/templates/"+footerFile, - async:true, - complete:function (data, status) { - if (status === 'success') { - insertFooter(data); - } else { - $.ajax({ - url:"/source/assets/templates/"+footerFile, - async:true, - complete:function (data) { - insertFooter(data); - } - }); + $.ajax({ + url:"/assets/templates/"+footerFile, + async:true, + complete:function (data, status) { + if (status === 'success') { + insertFooter(data); + } else { + $.ajax({ + url:"/source/assets/templates/"+footerFile, + async:true, + complete:function (data) { + insertFooter(data); + } + }); + } } - } - }); - } - } - - //click on header - go up - $header.on({ - mouseover: function(e){ - if(e.target === this){ - $('.source_header').css('cursor', 'pointer'); - }else { - $('.source_header').css('cursor', 'inherit'); - } - }, - click: function(e){ - if(e.target === this){ - window.scrollTo(0, 0); + }); } - }, - mouseout : function(){ - $('.source_header').css('cursor', 'inherit'); } }); - -}); \ No newline at end of file +}); diff --git a/assets/js/modules/htmlAPISync.js b/assets/js/modules/htmlAPISync.js index e798396..8373bfe 100644 --- a/assets/js/modules/htmlAPISync.js +++ b/assets/js/modules/htmlAPISync.js @@ -1,6 +1,6 @@ 'use strict'; -define([ +sourcejs.amd.define([ "jquery", "sourceModules/module", "sourceModules/utils", @@ -70,4 +70,4 @@ define([ }; return new HtmlAPiSync(); -}); \ No newline at end of file +}); diff --git a/assets/js/modules/inlineOptions.js b/assets/js/modules/inlineOptions.js index e62eaaa..43c385b 100644 --- a/assets/js/modules/inlineOptions.js +++ b/assets/js/modules/inlineOptions.js @@ -1,4 +1,4 @@ -define(function() { +sourcejs.amd.define(function() { 'use strict'; diff --git a/assets/js/modules/innerNavigation.js b/assets/js/modules/innerNavigation.js index 82cf750..28143b6 100644 --- a/assets/js/modules/innerNavigation.js +++ b/assets/js/modules/innerNavigation.js @@ -1,6 +1,6 @@ 'use strict'; -define([ +sourcejs.amd.define([ "jquery", "sourceModules/module", "sourceModules/utils", @@ -158,26 +158,26 @@ define([ '' ].join(''); - if ( section.subHeaderElements !== undefined ) { - appendString += '
    '; + if ( section.subHeaderElements !== undefined ) { + appendString += '
      '; - for (var j = 0; j < section.subHeaderElements.length; j++) { + for (var j = 0; j < section.subHeaderElements.length; j++) { var seqNum = j+1; var subSection = section.subHeaderElements[j]; var subSectionID = sectionID + '.' + seqNum; var subHref = subSection.attr('id') || subSectionID; - appendString += [ + appendString += [ '
    • ', '', section.num + '.' + seqNum + ' ' + subSection.text(), '', '
    • ' ].join(''); - } + } appendString += '
    '; - } + } appendString += ''; } @@ -196,4 +196,4 @@ define([ return new InnerNavigation(); -}); \ No newline at end of file +}); diff --git a/assets/js/modules/loadEvents.js b/assets/js/modules/loadEvents.js index dd48b5b..f5a2afe 100644 --- a/assets/js/modules/loadEvents.js +++ b/assets/js/modules/loadEvents.js @@ -4,40 +4,40 @@ * */ -define(["sourceModules/module", "sourceModules/utils"], function(module, utils) { +sourcejs.amd.define(["sourceModules/module", "sourceModules/utils"], function(module, utils) { 'use strict'; - function LoadEvents() {} + function LoadEvents() {} - LoadEvents.prototype = module.createInstance(); - LoadEvents.prototype.constructor = LoadEvents; + LoadEvents.prototype = module.createInstance(); + LoadEvents.prototype.constructor = LoadEvents; - LoadEvents.prototype.init = function( callback ) { + LoadEvents.prototype.init = function( callback ) { - callback = callback || function () {}; - var evt; - var complete = false; - var debug = module.options.modulesEnabled.loadEvents && module.options.modulesOptions.loadEvents && module.options.modulesOptions.loadEvents.debug; + callback = callback || function () {}; + var evt; + var complete = false; + var debug = module.options.modulesEnabled.loadEvents && module.options.modulesOptions.loadEvents && module.options.modulesOptions.loadEvents.debug; - if ( (!module.options.modulesEnabled.loadEvents) || (window.CustomEvent === undefined && document.createEvent === undefined) ) { - if (debug && utils.isDevelopmentMode()) { - console.log('LoadEvents Module disabled.'); - } + if ( (!module.options.modulesEnabled.loadEvents) || (window.CustomEvent === undefined && document.createEvent === undefined) ) { + if (debug && utils.isDevelopmentMode()) { + console.log('LoadEvents Module disabled.'); + } - callback(); - return; - } else { - if (debug && utils.isDevelopmentMode()) { - console.log('LoadEvents Module enabled.'); - } - } + callback(); + return; + } else { + if (debug && utils.isDevelopmentMode()) { + console.log('LoadEvents Module enabled.'); + } + } - function checkPluginsDefinition() { - return (window.source !== undefined) - && (window.source.loadEvents !== undefined) - && (Object.keys(window.source.loadEvents).length); - } + function checkPluginsDefinition() { + return (window.source !== undefined) + && (window.source.loadEvents !== undefined) + && (Object.keys(window.source.loadEvents).length); + } function phantomHook(event) { console.log('PhantomJS hook: %s', event); @@ -47,152 +47,152 @@ define(["sourceModules/module", "sourceModules/utils"], function(module, utils) } } - function generateSuccessEvent(eventName) { - if (debug && utils.isDevelopmentMode()) { - console.log('event happens ' + eventName ); - } + function generateSuccessEvent(eventName) { + if (debug && utils.isDevelopmentMode()) { + console.log('event happens ' + eventName ); + } - if (typeof window.CustomEvent === 'function') { - evt = new CustomEvent(eventName); - } else { - evt = document.createEvent('CustomEvent'); - evt.initCustomEvent(eventName, false, false, {}); - } + if (typeof window.CustomEvent === 'function') { + evt = new CustomEvent(eventName); + } else { + evt = document.createEvent('CustomEvent'); + evt.initCustomEvent(eventName, false, false, {}); + } - document.dispatchEvent(evt); + document.dispatchEvent(evt); - if (!complete) { - complete = true; - callback(); - } - } + if (!complete) { + complete = true; + callback(); + } + } - (function checkPluginsState() { + (function checkPluginsState() { - // If there's no any render plugin, just skip checking section - if ( !checkPluginsDefinition() ) { - generateSuccessEvent('allPluginsFinish'); + // If there's no any render plugin, just skip checking section + if ( !checkPluginsDefinition() ) { + generateSuccessEvent('allPluginsFinish'); phantomHook('allPluginsFinish'); - return; - } - - var pluginsSection = window.source.loadEvents; - var defaultPluginTimeout = 700; - - function checkPlugins() { - var now = new Date().getTime(); - var pluginFinish = 0; - - var onFinishEvent = function() { - if (debug && utils.isDevelopmentMode()) { - console.log(plugin + ' drop finishEvent' ); - } - - pluginsSection[plugin].finish = true; - pluginsSection[plugin].timeExpected = now-1; - }; - - var onUpdateEvent = function() { - var tmpExpected = now + parseInt(pluginsSection[plugin].timeout || defaultPluginTimeout, 10); - - if (tmpExpected > pluginsSection[plugin].timeExpected) { - pluginsSection[plugin].timeExpected = tmpExpected; - if (debug && utils.isDevelopmentMode()) { - console.log(plugin + ' drop updateEvent and increase timeout to ' + pluginsSection[plugin].timeExpected ); - } - - } - }; - /*jshint forin: false */ - for (var plugin in pluginsSection) { - if (!pluginsSection.hasOwnProperty(plugin)) { - continue; - } - if (debug && utils.isDevelopmentMode()) { - console.log(plugin + ' checking... '); - } - - if (pluginsSection[plugin].finish) { - pluginsSection[plugin].timeExpected = now-1; - if (debug && utils.isDevelopmentMode()) { - console.log(plugin + ' marked as finished'); - } - } - - if ( !Array.isArray( pluginsSection[plugin]) ) { - // first time - - if (pluginsSection[plugin].timeExpected === undefined) { - - pluginsSection[plugin].timeExpected = now + parseInt(pluginsSection[plugin].timeout || defaultPluginTimeout, 10); - if (debug && utils.isDevelopmentMode()) { - console.log(plugin + ' was registred and set timeout ' + pluginsSection[plugin].timeExpected); - } - - // When plugin finish his work, it send "finishEvent", which differs for each plugin - pluginsSection[plugin].finishEvent && document.addEventListener(pluginsSection[plugin].finishEvent, onFinishEvent); - - // When plugin need to update work's timeout, it generate "updateEvent" - pluginsSection[plugin].updateEvent && document.addEventListener(pluginsSection[plugin].updateEvent, onUpdateEvent); - - // Plugin already was initialized - } else { - - // If timeout come, increase counter - if ( pluginsSection[plugin].timeExpected < now ) { - if (!pluginsSection[plugin].finish) { - generateSuccessEvent(plugin + ' timeout, ' + new Date().getTime()); - pluginsSection[plugin].finish = true; - } - - pluginFinish++; - } - } - - } else { - var subPluginFinish = 0; - pluginFinish++; - - if ( (pluginsSection[plugin].length) && (!pluginsSection[plugin].finish) ) { - - for (var i = 0; i < pluginsSection[plugin].length; i++ ) { - var subPlugin = pluginsSection[plugin][i]; - - if ( (pluginsSection[subPlugin] !== undefined) && (pluginsSection[subPlugin].timeExpected < now) ) { - subPluginFinish++; - } - } - - if ( pluginsSection[plugin].length === subPluginFinish) { - pluginsSection[plugin].finish = true; - generateSuccessEvent(plugin + ' GroupFinish'); - } - } - } - - } - - // if there's more than 0 plugins and all of them get timeout, continue, - // otherwise make recursive call - if ( Object.keys(pluginsSection).length !== pluginFinish ) { - setTimeout(function() { - checkPlugins(); - }, 100); - return; - } - setTimeout(function () { - generateSuccessEvent('allPluginsFinish'); + return; + } + + var pluginsSection = window.source.loadEvents; + var defaultPluginTimeout = 700; + + function checkPlugins() { + var now = new Date().getTime(); + var pluginFinish = 0; + + var onFinishEvent = function() { + if (debug && utils.isDevelopmentMode()) { + console.log(plugin + ' drop finishEvent' ); + } + + pluginsSection[plugin].finish = true; + pluginsSection[plugin].timeExpected = now-1; + }; + + var onUpdateEvent = function() { + var tmpExpected = now + parseInt(pluginsSection[plugin].timeout || defaultPluginTimeout, 10); + + if (tmpExpected > pluginsSection[plugin].timeExpected) { + pluginsSection[plugin].timeExpected = tmpExpected; + if (debug && utils.isDevelopmentMode()) { + console.log(plugin + ' drop updateEvent and increase timeout to ' + pluginsSection[plugin].timeExpected ); + } + + } + }; + /*jshint forin: false */ + for (var plugin in pluginsSection) { // jshint ignore:line + if (!pluginsSection.hasOwnProperty(plugin)) { + continue; + } + if (debug && utils.isDevelopmentMode()) { + console.log(plugin + ' checking... '); + } + + if (pluginsSection[plugin].finish) { + pluginsSection[plugin].timeExpected = now-1; + if (debug && utils.isDevelopmentMode()) { + console.log(plugin + ' marked as finished'); + } + } + + if ( !Array.isArray( pluginsSection[plugin]) ) { + // first time + + if (pluginsSection[plugin].timeExpected === undefined) { + + pluginsSection[plugin].timeExpected = now + parseInt(pluginsSection[plugin].timeout || defaultPluginTimeout, 10); + if (debug && utils.isDevelopmentMode()) { + console.log(plugin + ' was registred and set timeout ' + pluginsSection[plugin].timeExpected); + } + + // When plugin finish his work, it send "finishEvent", which differs for each plugin + pluginsSection[plugin].finishEvent && document.addEventListener(pluginsSection[plugin].finishEvent, onFinishEvent); + + // When plugin need to update work's timeout, it generate "updateEvent" + pluginsSection[plugin].updateEvent && document.addEventListener(pluginsSection[plugin].updateEvent, onUpdateEvent); + + // Plugin already was initialized + } else { + + // If timeout come, increase counter + if ( pluginsSection[plugin].timeExpected < now ) { + if (!pluginsSection[plugin].finish) { + generateSuccessEvent(plugin + ' timeout, ' + new Date().getTime()); + pluginsSection[plugin].finish = true; + } + + pluginFinish++; + } + } + + } else { + var subPluginFinish = 0; + pluginFinish++; + + if ( (pluginsSection[plugin].length) && (!pluginsSection[plugin].finish) ) { + + for (var i = 0; i < pluginsSection[plugin].length; i++ ) { + var subPlugin = pluginsSection[plugin][i]; + + if ( (pluginsSection[subPlugin] !== undefined) && (pluginsSection[subPlugin].timeExpected < now) ) { + subPluginFinish++; + } + } + + if ( pluginsSection[plugin].length === subPluginFinish) { + pluginsSection[plugin].finish = true; + generateSuccessEvent(plugin + ' GroupFinish'); + } + } + } + + } + + // if there's more than 0 plugins and all of them get timeout, continue, + // otherwise make recursive call + if ( Object.keys(pluginsSection).length !== pluginFinish ) { + setTimeout(function() { + checkPlugins(); + }, 100); + return; + } + setTimeout(function () { + generateSuccessEvent('allPluginsFinish'); phantomHook('allPluginsFinish'); - }, defaultPluginTimeout); + }, defaultPluginTimeout); - return; - } + return; + } - checkPlugins(); - })(); - }; + checkPlugins(); + })(); + }; - return new LoadEvents(); -}); \ No newline at end of file + return new LoadEvents(); +}); diff --git a/assets/js/modules/module.js b/assets/js/modules/module.js index 536f991..b13617f 100644 --- a/assets/js/modules/module.js +++ b/assets/js/modules/module.js @@ -1,4 +1,4 @@ -define(["source/load-options"], function (options) { +sourcejs.amd.define(["source/load-options"], function (options) { 'use strict'; @@ -30,4 +30,4 @@ define(["source/load-options"], function (options) { return new Module(); -}); \ No newline at end of file +}); diff --git a/assets/js/modules/moduleLoader.js b/assets/js/modules/moduleLoader.js index a21e25c..71d8e6f 100644 --- a/assets/js/modules/moduleLoader.js +++ b/assets/js/modules/moduleLoader.js @@ -1,12 +1,37 @@ -define([ - 'sourceModules/module' - ], function (module) { +sourcejs.amd.define([ + 'jquery', + 'sourceModules/module' + ], function ($, module) { 'use strict'; function ModuleLoader() { + var _this = this; + this.loadModules('modules'); this.loadModules('plugins'); + + // Extending RequireJS config with npm packages list + sourcejs.amd.requirejs.config({ + // Create shorthands routes to clint-side npm plugins + packages: (function () { + var modulesList = _this.options.npmPluginsEnabled; + + var npmPackages = []; + for (var module in modulesList) { + if (modulesList.hasOwnProperty(module)) { + npmPackages.push({ + name: module, + location: '/node_modules/' + module + '/assets', + main: 'index' + }); + } + } + + return npmPackages; + }()) + }); + this.loadModules('npmPlugins'); } @@ -46,7 +71,11 @@ define([ var targetObj = optionsBase[typeEnabled][item]; if (targetObj){ - require([path + item]); + sourcejs.amd.require([path + item]); + + if (type === 'plugins') { + console.warn('Deprecation notice: module loader will stop supporting local plugins with next breaking release, please move `' + path + item + '` plugin to NPM dependencies, following SourceJS plugin structure https://sourcejs.com/docs/api/plugins.'); + } } } } @@ -54,4 +83,4 @@ define([ }; return new ModuleLoader(); -}); \ No newline at end of file +}); diff --git a/assets/js/modules/navHighlight.js b/assets/js/modules/navHighlight.js index e056c9d..4a4be98 100644 --- a/assets/js/modules/navHighlight.js +++ b/assets/js/modules/navHighlight.js @@ -6,200 +6,201 @@ * * */ -"use strict"; -define([ +sourcejs.amd.define([ + 'jquery', 'sourceModules/module' - ], function (module) { - - function NavHighlight() { - var defaults = { - updateHash: true - }; - - this.options.modulesOptions.navHighlight = $.extend(true, defaults, this.options.modulesOptions.navHighlight); - this.conf = this.options.modulesOptions.navHighlight; - - this.init(); - } - - NavHighlight.prototype = module.createInstance(); - NavHighlight.prototype.constructor = NavHighlight; - - NavHighlight.prototype.init = function(){ - var _this = this; - - // basic utils - var utils = (function() { - - return { - offsetTop: function(elem) { - var box = elem.getBoundingClientRect(); - var clientTop = document.body.clientTop || 0; - var top = box.top + window.pageYOffset - clientTop; - - return Math.round(top); - }, - hasClass: function(elem, cls) { - if (elem !== null) { - return elem.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)')); - } else { - return false; - } - }, - addClass: function(elem, cls) { - if (!this.hasClass(elem,cls)) { - elem.className += " "+cls; - elem.className.replace(/ +/g,' '); - } - }, - removeClass: function(elem, cls) { - if (this.hasClass(elem,cls)) { - var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)'); - elem.className=elem.className.replace(reg,''); - } - }, - closest: function(elem, cls) { //console.log(elem, cls); - if (elem.tagName === 'html') return false; - - var elemParent = elem.parentNode; - if (!utils.hasClass(elem, cls)) { - return utils.closest(elemParent, cls); - } - - return elem; - } - }; - - })(); - - var sourceHeaders = []; - var navHeaders; - var currentHeader = -1; - var filename = ''; - var extension = ''; - var hashThreshold = 100; - - var fullFilename = window.location.href.split("#")[0].split('/').pop().split('.'); - - //update extension and filename only if there is one in URL - if(fullFilename.length !== 1) { - extension = /\w+/.exec(fullFilename[1]); - filename = fullFilename[0]; - } - - // watch headers position - var watchSectionTop = function () { - - var headersLength = sourceHeaders.length; - var minDistance = Number.MAX_VALUE; - var closestHeader = -1; - var fileNameInUrl = filename === '' ? '' : filename + '.' + extension; - - if ((document.body.scrollTop || document.documentElement.scrollTop) < hashThreshold) { - - if (!!window.location.hash) { - currentHeader = -1; - if (!!(window.history && history.pushState)) { - window.history.replaceState({anchor: 0}, document.title, window.location.pathname); - } - } - - return; - } - - // catch section which is closed for top window border - for (var i=0; i < headersLength; i++) { - - if ((sourceHeaders[i].tagName === 'H3') && (!utils.hasClass(utils.closest(sourceHeaders[i], 'source_section'), 'source_section__open')) ) { - continue; - } - - var currentDist = Math.abs( utils.offsetTop(sourceHeaders[i]) - 60 - window.pageYOffset ); //60 = Header heights - if (currentDist < minDistance) { - closestHeader = i; - minDistance = currentDist; - } - } - - if (closestHeader !== currentHeader) { - utils.removeClass( document.querySelector('.source_main_nav_li.__active'), '__active'); - utils.removeClass( document.querySelector('.source_main_nav_a.__active'), '__active'); - - utils.addClass(navHeaders[closestHeader], '__active'); - - var parent = utils.closest(navHeaders[closestHeader], 'source_main_nav_li'); - var hashFromLink = navHeaders[closestHeader].getAttribute('href'); - - if (!!parent && parent) { - utils.addClass(parent, '__active'); - } - - if (_this.conf.updateHash) { - // TODO: pause hash change when scrolling - append it only on stand-still - - // Modern browsers uses history API for correct back-button-browser functionality - if (!!(window.history && history.pushState)) { - window.history.replaceState({anchor: closestHeader+1}, document.title, fileNameInUrl + hashFromLink); - } else { // ie9 fallback - window.location.hash = hashFromLink; - } - } - - currentHeader = closestHeader; - } - }; - - // watch navmenu render - var checkNavInterval; - var h2Nodes; - var bodyNode = document.querySelector('body'); - var checkOnNav = function checkOnNav() { + ], function ($, module) { + 'use strict'; + + function NavHighlight() { + var defaults = { + updateHash: true + }; + + this.options.modulesOptions.navHighlight = $.extend(true, defaults, this.options.modulesOptions.navHighlight); + this.conf = this.options.modulesOptions.navHighlight; + + this.init(); + } + + NavHighlight.prototype = module.createInstance(); + NavHighlight.prototype.constructor = NavHighlight; + + NavHighlight.prototype.init = function(){ + var _this = this; + + // basic utils + var utils = (function() { + + return { + offsetTop: function(elem) { + var box = elem.getBoundingClientRect(); + var clientTop = document.body.clientTop || 0; + var top = box.top + window.pageYOffset - clientTop; + + return Math.round(top); + }, + hasClass: function(elem, cls) { + if (elem !== null) { + return elem.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)')); + } else { + return false; + } + }, + addClass: function(elem, cls) { + if (!this.hasClass(elem,cls)) { + elem.className += " "+cls; + elem.className.replace(/ +/g,' '); + } + }, + removeClass: function(elem, cls) { + if (this.hasClass(elem,cls)) { + var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)'); + elem.className=elem.className.replace(reg,''); + } + }, + closest: function(elem, cls) { //console.log(elem, cls); + if (elem.tagName === 'html') return false; + + var elemParent = elem.parentNode; + if (!utils.hasClass(elem, cls)) { + return utils.closest(elemParent, cls); + } + + return elem; + } + }; + + })(); + + var sourceHeaders = []; + var navHeaders; + var currentHeader = -1; + var filename = ''; + var extension = ''; + var hashThreshold = 100; + + var fullFilename = window.location.href.split("#")[0].split('/').pop().split('.'); + + //update extension and filename only if there is one in URL + if(fullFilename.length !== 1) { + extension = /\w+/.exec(fullFilename[1]); + filename = fullFilename[0]; + } + + // watch headers position + var watchSectionTop = function () { + + var headersLength = sourceHeaders.length; + var minDistance = Number.MAX_VALUE; + var closestHeader = -1; + var fileNameInUrl = filename === '' ? '' : filename + '.' + extension; + + if ((document.body.scrollTop || document.documentElement.scrollTop) < hashThreshold) { + + if (!!window.location.hash) { + currentHeader = -1; + if (!!(window.history && history.pushState)) { + window.history.replaceState({anchor: 0}, document.title, window.location.pathname); + } + } + + return; + } + + // catch section which is closed for top window border + for (var i=0; i < headersLength; i++) { + + if ((sourceHeaders[i].tagName === 'H3') && (!utils.hasClass(utils.closest(sourceHeaders[i], 'source_section'), 'source_section__open')) ) { + continue; + } + + var currentDist = Math.abs( utils.offsetTop(sourceHeaders[i]) - 60 - window.pageYOffset ); //60 = Header heights + if (currentDist < minDistance) { + closestHeader = i; + minDistance = currentDist; + } + } + + if (closestHeader !== currentHeader) { + utils.removeClass( document.querySelector('.source_main_nav_li.__active'), '__active'); + utils.removeClass( document.querySelector('.source_main_nav_a.__active'), '__active'); + + utils.addClass(navHeaders[closestHeader], '__active'); + + var parent = utils.closest(navHeaders[closestHeader], 'source_main_nav_li'); + var hashFromLink = navHeaders[closestHeader].getAttribute('href'); + + if (!!parent && parent) { + utils.addClass(parent, '__active'); + } + + if (_this.conf.updateHash) { + // TODO: pause hash change when scrolling - append it only on stand-still + + // Modern browsers uses history API for correct back-button-browser functionality + if (!!(window.history && history.pushState)) { + window.history.replaceState({anchor: closestHeader+1}, document.title, fileNameInUrl + hashFromLink); + } else { // ie9 fallback + window.location.hash = hashFromLink; + } + } + + currentHeader = closestHeader; + } + }; + + // watch navmenu render + var checkNavInterval; + var h2Nodes; + var bodyNode = document.querySelector('body'); + var checkOnNav = function checkOnNav() { - if ((document.querySelector('.source_section') !== null) && - (document.querySelector('.source_main_nav_a') !== null)) { + if ((document.querySelector('.source_section') !== null) && + (document.querySelector('.source_main_nav_a') !== null)) { - clearInterval(checkNavInterval); + clearInterval(checkNavInterval); - navHeaders = document.querySelectorAll('.source_main_nav_a'); - h2Nodes = document.querySelectorAll('.source_section'); + navHeaders = document.querySelectorAll('.source_main_nav_a'); + h2Nodes = document.querySelectorAll('.source_section'); - var getH3Nodes = function(childerArray){ - var h3Nodes = []; + var getH3Nodes = function(childerArray){ + var h3Nodes = []; - childerArray.forEach(function (item) { - if (item.tagName === 'H3') h3Nodes.push(item); - }); + childerArray.forEach(function (item) { + if (item.tagName === 'H3') h3Nodes.push(item); + }); - return h3Nodes; - }; + return h3Nodes; + }; - for (var h2 = 0; h2 < h2Nodes.length; h2++) { - var childerArray = [].slice.call(h2Nodes[h2].children); + for (var h2 = 0; h2 < h2Nodes.length; h2++) { + var childerArray = [].slice.call(h2Nodes[h2].children); - var h3Nodes = getH3Nodes(childerArray); + var h3Nodes = getH3Nodes(childerArray); - sourceHeaders.push( h2Nodes[h2].querySelector('h2') ); - for (var h3 = 0; h3 < h3Nodes.length; h3++) { - sourceHeaders.push( h3Nodes[h3] ); - } + sourceHeaders.push( h2Nodes[h2].querySelector('h2') ); + for (var h3 = 0; h3 < h3Nodes.length; h3++) { + sourceHeaders.push( h3Nodes[h3] ); + } - } + } - if (utils.hasClass(bodyNode, 'source__scrolled-down')) { - watchSectionTop(); - } + if (utils.hasClass(bodyNode, 'source__scrolled-down')) { + watchSectionTop(); + } - window.onscroll = function() { - watchSectionTop(); - }; + window.onscroll = function() { + watchSectionTop(); + }; - return; - } - }; + return; + } + }; - checkNavInterval = setInterval(checkOnNav, 1000); - }; + checkNavInterval = setInterval(checkOnNav, 1000); + }; - return new NavHighlight(); -}); \ No newline at end of file + return new NavHighlight(); +}); diff --git a/assets/js/modules/ntf.js b/assets/js/modules/ntf.js index 20976a7..8498809 100644 --- a/assets/js/modules/ntf.js +++ b/assets/js/modules/ntf.js @@ -1,6 +1,6 @@ 'use strict'; -define([ +sourcejs.amd.define([ 'jquery', 'sourceModules/module' ], function($, module) { @@ -30,4 +30,4 @@ define([ }; return new Notification(); -}); \ No newline at end of file +}); diff --git a/assets/js/modules/parseFileTree.js b/assets/js/modules/parseFileTree.js index 58e88ed..8178f6c 100644 --- a/assets/js/modules/parseFileTree.js +++ b/assets/js/modules/parseFileTree.js @@ -9,7 +9,7 @@ 'use strict'; -define([ +sourcejs.amd.define([ 'jquery', 'sourceModules/module', 'text!/api/specs/raw', @@ -304,4 +304,4 @@ define([ }; return new ParseFileTree(); -}); \ No newline at end of file +}); diff --git a/assets/js/modules/scrollToHash.js b/assets/js/modules/scrollToHash.js index 068390e..fc92321 100644 --- a/assets/js/modules/scrollToHash.js +++ b/assets/js/modules/scrollToHash.js @@ -1,5 +1,5 @@ //In separate module, to trace script ready state -define([ +sourcejs.amd.define([ "jquery", "sourceModules/utils", "sourceModules/loadEvents", @@ -47,4 +47,4 @@ define([ } }); }); -}); \ No newline at end of file +}); diff --git a/assets/js/modules/search.js b/assets/js/modules/search.js index 27f5f49..f60008f 100644 --- a/assets/js/modules/search.js +++ b/assets/js/modules/search.js @@ -4,7 +4,7 @@ * * */ -define([ +sourcejs.amd.define([ 'jquery', 'sourceModules/module', 'sourceLib/autocomplete', @@ -72,18 +72,18 @@ Search.prototype.prepareAutoCompleteData = function() { // Skip hidden specs if (targetPage.tag && targetPage.tag.indexOf('hidden') > -1) continue; - var keywords = targetPage.keywords; - var keywordsPageName = pagesData[page] && pagesData[page]['name'] + var tag = targetPage.tag; + var pageName = pagesData[page] && pagesData[page]['name'] ? pagesData[page]['name'] : ""; //get cat name - var prepareKeywords = ''; + var tags = ''; var autocompleteValue = targetPage.title; - if (keywords && keywords !== '') { - prepareKeywords += ', ' + keywords; + if (tag && tag.length) { + tags += ', ' + tag.join(', '); } - autocompleteValue += ' (' + keywordsPageName + prepareKeywords + ')'; + autocompleteValue += ' (' + pageName + tags + ')'; this.data[this.data.length] = new AutocomleteDataItem(autocompleteValue, targetPage.url); } } diff --git a/assets/js/modules/sectionFolding.js b/assets/js/modules/sectionFolding.js index fcd5130..919177d 100644 --- a/assets/js/modules/sectionFolding.js +++ b/assets/js/modules/sectionFolding.js @@ -6,7 +6,7 @@ * * */ -define([ +sourcejs.amd.define([ "jquery", "source/load-options", "sourceModules/utils", @@ -20,26 +20,26 @@ define([ $(function(){ //TODO: move to utils - // Bulletproof localStorage check - var storage; - var fail; - var uid; - try { - uid = new Date(); - (storage = window.localStorage).setItem(uid, uid); - fail = storage.getItem(uid) !== uid.toString(); - storage.removeItem(uid); - fail && (storage = false); - } catch (e) { - } - //TODO: /move to utils - var SECTION_CLASS = options.SECTION_CLASS; - var L_SECTION_CLASS = $('.'+SECTION_CLASS); - var OPEN_SECTION_CLASS = 'source_section__open'; - var sectionsOnPage = L_SECTION_CLASS; - var specName = utils.getSpecName(); //Определяем название спеки - var clientConfig = {}; - var RES_HIDE_SECTIONS = 'Hide all sections'; + // Bulletproof localStorage check + var storage; + var fail; + var uid; + try { + uid = new Date(); + (storage = window.localStorage).setItem(uid, uid); + fail = storage.getItem(uid) !== uid.toString(); + storage.removeItem(uid); + fail && (storage = false); + } catch (e) { + } + //TODO: /move to utils + var SECTION_CLASS = options.SECTION_CLASS; + var L_SECTION_CLASS = $('.'+SECTION_CLASS); + var OPEN_SECTION_CLASS = 'source_section__open'; + var sectionsOnPage = L_SECTION_CLASS; + var specName = utils.getSpecName(); //Определяем название спеки + var clientConfig = {}; + var RES_HIDE_SECTIONS = 'Hide all sections'; if (storage) { //Check if localstorage has required data @@ -94,40 +94,12 @@ define([ $target.addClass(OPEN_SECTION_CLASS); var sectionID = $target.attr('id'); - var isRendered = false; closedSections["section" + sectionID] = false; if (config) { //Remember options in localStorage updateConfig(); } - - // TODO: remove mustache check from core - if (options.pluginsOptions && options.pluginsOptions.mustache) { - // Need to use absolute path to get same scope with requires from inline scripts - require(['/plugins/mustache/js/mustache.js'], function(templater){ - if (typeof templater.PostponedTemplates !== 'undefined') { - - if ($target.attr('data-rendered') === 'true') { - isRendered = true; - } - - if (!isRendered) { - - for (var arr in templater.PostponedTemplates[sectionID]) { - if (templater.PostponedTemplates[sectionID].hasOwnProperty(arr)) { - var values = templater.PostponedTemplates[sectionID][arr]; - templater.insertTemplate(values[0], values[1], values[2]); - } - } - - $target.attr('data-rendered', 'true'); - } - - } - }); - } - }; var closeSpoiler = function (t, config) { @@ -245,4 +217,4 @@ define([ }); -}); \ No newline at end of file +}); diff --git a/assets/js/modules/sections.js b/assets/js/modules/sections.js index c51c48e..6ec4859 100644 --- a/assets/js/modules/sections.js +++ b/assets/js/modules/sections.js @@ -6,7 +6,7 @@ * * */ -define([ +sourcejs.amd.define([ "jquery", "sourceModules/module" ], function ($, module) { @@ -89,4 +89,4 @@ define([ }; return new Sections(); -}); \ No newline at end of file +}); diff --git a/assets/js/modules/sectionsParser.js b/assets/js/modules/sectionsParser.js index 05e65f1..a5e68c8 100644 --- a/assets/js/modules/sectionsParser.js +++ b/assets/js/modules/sectionsParser.js @@ -12,6 +12,8 @@ function SourceGetSections() { // Defining strict inside func, because PhantomJS stops evaluating this script if it's on top 'use strict'; + /*jshint latedef: false */ + var config = { // include params from opt@argument first code: 'source_example', @@ -211,7 +213,7 @@ function SourceGetSections() { /** * Filter list of HTML nodes * - * @param {Array} elementsArr - nodelist to filter + * @param {Array} elementsArr - elements array to filter * @param {Function} [customElFilter] - Additional filter for element * @param {Boolean} [skipAttrFilters] - Set to true, if expect not filtered list of resources * @@ -426,4 +428,4 @@ SourceGetSections.prototype.getSpecResources = function(scope){ output.cssStyles = this.getStyleContainersHTML(_scope); return (output.cssLinks || output.scripts || output.cssStyles) ? output : undefined; -}; \ No newline at end of file +}; diff --git a/assets/js/modules/specDecorations.js b/assets/js/modules/specDecorations.js index d4e92f9..81f9770 100644 --- a/assets/js/modules/specDecorations.js +++ b/assets/js/modules/specDecorations.js @@ -1,4 +1,4 @@ -define([ +sourcejs.amd.define([ "jquery", "source/load-options", "sourceModules/browser" @@ -28,4 +28,4 @@ define([ } }).trigger('scroll'); -}); \ No newline at end of file +}); diff --git a/assets/js/modules/trimSpaces.js b/assets/js/modules/trimSpaces.js index b30a333..5302d41 100644 --- a/assets/js/modules/trimSpaces.js +++ b/assets/js/modules/trimSpaces.js @@ -6,10 +6,11 @@ * * */ -define([ - "source/load-options", - "sourceModules/codeSource" - ], function(options) { +sourcejs.amd.define([ + 'jquery', + 'source/load-options', + 'sourceModules/codeSource' + ], function($, options) { 'use strict'; @@ -39,5 +40,4 @@ define([ }; L_EXAMPLE_CLASS.trimSpaces(); - -}); \ No newline at end of file +}); diff --git a/assets/js/modules/utils.js b/assets/js/modules/utils.js index 342161b..d0cdaa6 100644 --- a/assets/js/modules/utils.js +++ b/assets/js/modules/utils.js @@ -4,7 +4,7 @@ * * */ -define([ +sourcejs.amd.define([ 'jquery', 'sourceModules/module' ], function ($, module) { @@ -59,8 +59,8 @@ define([ var specName; var pageUrl = window.location.pathname; - var pageUrlSplit = pageUrl.split("/"); //Разбивает на массив - specName = pageUrlSplit[pageUrlSplit.length - 2]; //Берет последнюю часть урла + var pageUrlSplit = pageUrl.split("/"); + specName = pageUrlSplit[pageUrlSplit.length - 2]; return specName; }; @@ -69,7 +69,7 @@ define([ var pathToSpec = (function(){ var path; - //specUrl is used from parseFileTree, and contains only path, without file like "/docs/spec" + //specUrl is used from parseFileTree, and contains only path, without file like "/docs/spec-html" if (typeof specUrlFromFileTree === 'undefined') { path = window.location.pathname; @@ -96,17 +96,17 @@ define([ }; Utils.prototype.getCookie = function(name) { - var matches = document.cookie.match(new RegExp("(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)")); - return matches ? decodeURIComponent(matches[1]) : undefined; + var matches = document.cookie.match(new RegExp("(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)")); + return matches ? decodeURIComponent(matches[1]) : undefined; }; Utils.prototype.isDevelopmentMode = function() { - return this.getCookie('source-mode') === 'development'; + return this.getCookie('source-mode') === 'development'; }; - Utils.prototype.isArray = function(arr) { - return Object.prototype.toString.call(arr) === '[object Array]'; - }; + Utils.prototype.isArray = function(arr) { + return Object.prototype.toString.call(arr) === '[object Array]'; + }; Utils.prototype.unifySpecPath = function(url) { if (url.slice(-10) === "index.html") url = url.slice(0, -10); @@ -129,4 +129,4 @@ define([ }; return new Utils(); -}); \ No newline at end of file +}); diff --git a/assets/js/require-config.js b/assets/js/require-config.js deleted file mode 100644 index f8b64eb..0000000 --- a/assets/js/require-config.js +++ /dev/null @@ -1,19 +0,0 @@ -// Joined to require.bundle.js - -requirejs.config({ - paths: { - // /source/assets requests are routed to /assets - source: '/source/assets/js', - sourceModules: '/source/assets/js/modules', - sourceLib: '/source/assets/js/lib', - sourceTemplates: '/source/assets/templates', - - // Require.js plugins - text: '/source/assets/js/lib/text', - - // Relative to user root - js: '/assets/js', - plugins: '/plugins', - node_modules: '/node_modules' - } -}); \ No newline at end of file diff --git a/assets/templates/clarifyPanel.inc.html b/assets/templates/clarifyPanel.inc.html index 64000e2..6934adf 100644 --- a/assets/templates/clarifyPanel.inc.html +++ b/assets/templates/clarifyPanel.inc.html @@ -28,13 +28,6 @@

    Options

    <% } %> - <% if (htmlParser) { %> -
  • - -
  • - <% } %>