├── firefox
├── data
│ └── empty.txt
├── lib
│ ├── main.js
│ ├── loader.js
│ ├── storage.js
│ ├── ext.js
│ ├── target-logger.js
│ └── runtime.js
├── package.json
└── test
│ └── test-main.js
├── shared
├── fw
│ ├── modules
│ │ ├── main.js
│ │ ├── panel.js
│ │ ├── settings.js
│ │ └── checkbox.js
│ └── cui
│ │ ├── modules
│ │ ├── lib.js
│ │ ├── templates-utils.js
│ │ ├── events.js
│ │ ├── utils.js
│ │ ├── basic.js
│ │ ├── ajax.js
│ │ └── ui.js
│ │ ├── loader.debug.js
│ │ ├── loader2.js
│ │ ├── loader.js
│ │ └── modules.js
├── ext_modules
│ ├── storage.js
│ ├── ext.js
│ ├── backend.js
│ └── prefs.js
├── ui
│ ├── fonts
│ │ ├── icons.eot
│ │ ├── icons.otf
│ │ ├── icons.ttf
│ │ ├── icons.woff
│ │ ├── basic.icons.eot
│ │ ├── basic.icons.ttf
│ │ └── basic.icons.woff
│ └── images
│ │ ├── loader-large.gif
│ │ ├── loader-mini.gif
│ │ ├── loader-small.gif
│ │ ├── loader-medium.gif
│ │ ├── loader-mini-inverted.gif
│ │ ├── loader-large-inverted.gif
│ │ ├── loader-medium-inverted.gif
│ │ └── loader-small-inverted.gif
├── prefs.json
├── bootstrap.js
├── promises-panel.html
├── promises-backend.js
├── providers
│ └── es6.js
├── css
│ └── style.css
└── promises-panel.js
├── chrome
├── scripts
│ ├── main.js
│ ├── ext.js
│ ├── storage.js
│ ├── commonjs.js
│ └── runtime.js
├── devtools.html
├── manifest.json
├── promises-frontend.js
└── devtools.js
├── .gitignore
├── init.sh
├── init.bat
├── README.md
└── LICENSE.md
/firefox/data/empty.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/shared/fw/modules/main.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/chrome/scripts/main.js:
--------------------------------------------------------------------------------
1 | require('lib/runtime.js');
--------------------------------------------------------------------------------
/shared/ext_modules/storage.js:
--------------------------------------------------------------------------------
1 | module.exports = require('lib/storage');
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | firefox/data/shared
2 | chrome/shared
3 | node_modules/
4 | *.notes.txt
--------------------------------------------------------------------------------
/chrome/devtools.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/shared/ui/fonts/icons.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NekR/PromisesDebuggerExtension/HEAD/shared/ui/fonts/icons.eot
--------------------------------------------------------------------------------
/shared/ui/fonts/icons.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NekR/PromisesDebuggerExtension/HEAD/shared/ui/fonts/icons.otf
--------------------------------------------------------------------------------
/shared/ui/fonts/icons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NekR/PromisesDebuggerExtension/HEAD/shared/ui/fonts/icons.ttf
--------------------------------------------------------------------------------
/shared/ui/fonts/icons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NekR/PromisesDebuggerExtension/HEAD/shared/ui/fonts/icons.woff
--------------------------------------------------------------------------------
/firefox/lib/main.js:
--------------------------------------------------------------------------------
1 | const loader = require('loader.js');
2 | require = loader.require;
3 |
4 | require('lib/runtime.js');
--------------------------------------------------------------------------------
/shared/ui/fonts/basic.icons.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NekR/PromisesDebuggerExtension/HEAD/shared/ui/fonts/basic.icons.eot
--------------------------------------------------------------------------------
/shared/ui/fonts/basic.icons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NekR/PromisesDebuggerExtension/HEAD/shared/ui/fonts/basic.icons.ttf
--------------------------------------------------------------------------------
/shared/ui/fonts/basic.icons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NekR/PromisesDebuggerExtension/HEAD/shared/ui/fonts/basic.icons.woff
--------------------------------------------------------------------------------
/shared/ui/images/loader-large.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NekR/PromisesDebuggerExtension/HEAD/shared/ui/images/loader-large.gif
--------------------------------------------------------------------------------
/shared/ui/images/loader-mini.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NekR/PromisesDebuggerExtension/HEAD/shared/ui/images/loader-mini.gif
--------------------------------------------------------------------------------
/shared/ui/images/loader-small.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NekR/PromisesDebuggerExtension/HEAD/shared/ui/images/loader-small.gif
--------------------------------------------------------------------------------
/shared/ui/images/loader-medium.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NekR/PromisesDebuggerExtension/HEAD/shared/ui/images/loader-medium.gif
--------------------------------------------------------------------------------
/shared/ui/images/loader-mini-inverted.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NekR/PromisesDebuggerExtension/HEAD/shared/ui/images/loader-mini-inverted.gif
--------------------------------------------------------------------------------
/shared/ui/images/loader-large-inverted.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NekR/PromisesDebuggerExtension/HEAD/shared/ui/images/loader-large-inverted.gif
--------------------------------------------------------------------------------
/shared/ui/images/loader-medium-inverted.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NekR/PromisesDebuggerExtension/HEAD/shared/ui/images/loader-medium-inverted.gif
--------------------------------------------------------------------------------
/shared/ui/images/loader-small-inverted.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NekR/PromisesDebuggerExtension/HEAD/shared/ui/images/loader-small-inverted.gif
--------------------------------------------------------------------------------
/shared/fw/modules/panel.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | ['updateSetting'].forEach(function(method) {
4 | exports[method] = PromisesPanel[method].bind(PromisesPanel);
5 | });
--------------------------------------------------------------------------------
/init.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | unlink ./chrome/shared
4 | unlink ./firefox/data/shared
5 |
6 | ln -s ./shared ./chrome/shared
7 | ln -s ./shared ./firefox/data/shared
--------------------------------------------------------------------------------
/init.bat:
--------------------------------------------------------------------------------
1 | rmdir .\chrome\shared
2 | rmdir .\firefox\data\shared
3 |
4 | cd .\chrome
5 | mklink /D .\shared ..\shared
6 | cd ..
7 | cd .\firefox\data
8 | mklink /D .\shared ..\..\shared
9 | cd ..\..
--------------------------------------------------------------------------------
/firefox/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "promises-debugger-extension",
3 | "title": "Promises Debugger",
4 | "id": "jid1-2kvMqwPuHcvUDw",
5 | "description": "",
6 | "author": "",
7 | "license": "MPL 2.0",
8 | "version": "0.1"
9 | }
10 |
--------------------------------------------------------------------------------
/firefox/test/test-main.js:
--------------------------------------------------------------------------------
1 | var main = require("./main");
2 |
3 | exports["test main"] = function(assert) {
4 | assert.pass("Unit test running!");
5 | };
6 |
7 | exports["test main async"] = function(assert, done) {
8 | assert.pass("async Unit test running!");
9 | done();
10 | };
11 |
12 | require("sdk/test").run(exports);
13 |
--------------------------------------------------------------------------------
/shared/fw/cui/modules/lib.js:
--------------------------------------------------------------------------------
1 | var exports = {
2 | extend: Sync.extend,
3 | each: Sync.each,
4 | cache: Sync.cache,
5 | escape: Sync.escape,
6 | unescape: Sync.unescape,
7 | events: {
8 | add: Sync.events.addEvent,
9 | remove: Sync.events.removeEvent,
10 | clean: Sync.events.cleanEvents,
11 | removeAll: Sync.events.removeEventAll,
12 | dispatch: Sync.events.dispatchEvent
13 | }
14 | };
--------------------------------------------------------------------------------
/shared/prefs.json:
--------------------------------------------------------------------------------
1 | {
2 | // log errors in promises
3 | "log_errors": true,
4 | // show full stack means show stack from extensions,
5 | // useful for this ext. dev
6 | "show_full_stack": true,
7 | // ignore promises which are auto created by then, but not handled (yet?)
8 | "ignore_trailing_promises": true,
9 |
10 | "log_caught_rejections": true,
11 | // pause on errors in promise which has at least one catch handler
12 | "pause_on_caught_errors": false,
13 |
14 | // attach backend to target on DevTools open
15 | "start_watch_on_start": false
16 | }
--------------------------------------------------------------------------------
/shared/fw/modules/settings.js:
--------------------------------------------------------------------------------
1 | var ui = require('ui'),
2 | parser = require('parser'),
3 | checkbox = require('checkbox'),
4 | panel = require('panel');
5 |
6 | ui.define('settings', {
7 | handler: function() {
8 | var self = this;
9 |
10 | events.on(self, parser.events.parsed, function() {
11 | self.children.forEach(function(child) {
12 | events.on(child, checkbox.events.checked, function() {
13 | panel.updateSetting(child.get('string:setting'), child.get('checked'));
14 | });
15 | });
16 | });
17 | }
18 | });
--------------------------------------------------------------------------------
/firefox/lib/loader.js:
--------------------------------------------------------------------------------
1 | const self = require('sdk/self');
2 | const { Loader, Require } = require('toolkit/loader');
3 |
4 | let options = require('@loader/options');
5 |
6 | let extRoot = options.prefixURI + options.name + '/';
7 |
8 | options.paths['shared/'] = self.data.url('shared/ext_modules/');
9 | options.paths['lib/'] = options.paths['./'];
10 | options.paths['data/'] = self.data.url('');
11 |
12 | let replacemntLoader = Loader(options);
13 | let replacemntRequire = Require(replacemntLoader);
14 |
15 | exports.extRoot = extRoot;
16 | exports.require = replacemntRequire;
--------------------------------------------------------------------------------
/chrome/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 2,
3 |
4 | "name": "Promises Debugger",
5 | "description": "",
6 | "version": "1.0",
7 |
8 | "permissions": [
9 | "tabs",
10 | "storage",
11 | "activeTab",
12 | "webNavigation",
13 | "http://*/",
14 | "https://*/"
15 | ],
16 | "devtools_page": "devtools.html",
17 | "background": {
18 | "scripts": [
19 | "scripts/commonjs.js",
20 | "scripts/main.js"
21 | ],
22 | "persistent": false
23 | },
24 | "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
25 | }
--------------------------------------------------------------------------------
/shared/bootstrap.js:
--------------------------------------------------------------------------------
1 | modules.ready(function() {
2 | modules.require('parser').parse(document.body);
3 | });
4 |
5 | modules.load({
6 | version: 1,
7 | deps: [
8 | 'fw/lib/sync.js',
9 | 'fw/cui/modules/lib.js',
10 | 'fw/cui/modules/events.js',
11 | 'fw/cui/modules/utils.js',
12 | 'fw/cui/modules/ui.js',
13 | 'fw/cui/modules/parser.js',
14 |
15 | 'fw/modules/panel.js',
16 | 'fw/modules/checkbox.js',
17 | 'fw/modules/settings.js',
18 | 'fw/modules/main.js'
19 | ],
20 | url: 'fw/cui/modules.js',
21 | path: './',
22 | debug: false,
23 | packaged: false,
24 | webapp: false,
25 | cache: false
26 | });
--------------------------------------------------------------------------------
/shared/ext_modules/ext.js:
--------------------------------------------------------------------------------
1 | var ext = require('lib/ext');
2 | var keys = Object.keys(ext.paths).sort();
3 |
4 | var extUrl = function(url) {
5 | if (typeof url !== 'string') {
6 | throw new TypeError('Bad argument');
7 | }
8 |
9 | var pathFound = keys.some(function(path) {
10 | if (!url.indexOf(path)) {
11 | var prefix = ext.paths[path];
12 |
13 | url = prefix + url.slice(path.length);
14 | return true;
15 | }
16 | });
17 |
18 | if (pathFound) {
19 | return url;
20 | }
21 |
22 | return ext.getURL(url);
23 | };
24 |
25 | module.exports = {
26 | url: extUrl,
27 | load: ext.load,
28 | loadSync: ext.loadSync,
29 | paths: ext.paths,
30 | getURL: ext.getURL
31 | };
--------------------------------------------------------------------------------
/firefox/lib/storage.js:
--------------------------------------------------------------------------------
1 | var storage = require('sdk/simple-storage').storage;
2 |
3 | module.exports = {
4 | set: function(key, value) {
5 | try {
6 | storage[key] = value;
7 | return Promise.resolve();
8 | } catch (e) {
9 | return Promise.reejct(e);
10 | }
11 | },
12 | get: function(key) {
13 | try {
14 | var val = storage[key];
15 | return Promise.resolve(val);
16 | } catch (e) {
17 | return Promise.reejct(e);
18 | }
19 | },
20 | remove: function(key) {
21 | try {
22 | delete storage[key];
23 | return Promise.resolve();
24 | } catch (e) {
25 | return Promise.reejct();
26 | }
27 | },
28 | getAll: function() {
29 | return Promise.resolve(storage);
30 | }
31 | };
--------------------------------------------------------------------------------
/firefox/lib/ext.js:
--------------------------------------------------------------------------------
1 | const { extRoot } = require('lib/loader');
2 | const { readURI, readURISync } = require('sdk/net/url');
3 |
4 | let getURL = function(path) {
5 | if (typeof path !== 'string') {
6 | throw new TypeError('Bad argument');
7 | }
8 |
9 | if (!path.indexOf('/')) {
10 | return extRoot + path.replace(/^\/+/, '');
11 | }
12 |
13 | return extRoot + path.replace(/^([\/\.])*/, '');
14 | };
15 |
16 | exports.getURL = getURL;
17 | exports.paths = {
18 | 'lib/': getURL('lib/'),
19 | 'data/': getURL('data/'),
20 | 'shared/': getURL('data/shared/')
21 | };
22 |
23 | exports.loadSync = function(url) {
24 | return readURISync(this.url(url));
25 | };
26 |
27 | exports.load = function(url) {
28 | url = this.url(url);
29 | return readURI(url);
30 | };
--------------------------------------------------------------------------------
/shared/ext_modules/backend.js:
--------------------------------------------------------------------------------
1 | var ext = require('shared/ext.js');
2 | var providers = [
3 | 'es6'
4 | ];
5 | var backendCode;
6 |
7 | exports.providers = providers;
8 | exports.getCode = function() {
9 | if (backendCode) return backendCode;
10 |
11 | var debugBackendCode = ext.loadSync('shared/promises-backend.js'),
12 | debugProvidersCode = '';
13 |
14 | providers.forEach(function(provider) {
15 | var code = ext.loadSync('shared/providers/' + provider + '.js');
16 |
17 | debugProvidersCode += ';(function(PromisesDebugger, global) {' +
18 | code + '}(PromisesDebugger, this));';
19 | });
20 |
21 | debugBackendCode = debugBackendCode + debugProvidersCode;
22 | backendCode = ';var backendCode = ' + JSON.stringify(debugBackendCode) + ';';
23 |
24 | return backendCode;
25 | };
--------------------------------------------------------------------------------
/chrome/scripts/ext.js:
--------------------------------------------------------------------------------
1 | var getURL = function(path) {
2 | return chrome.runtime.getURL(path);
3 | };
4 |
5 | exports.getURL = getURL;
6 |
7 | exports.paths = {
8 | 'data/': getURL('data/'),
9 | 'lib/': getURL('scripts/'),
10 | 'shared/': getURL('shared/')
11 | };
12 |
13 | exports.loadSync = function(url) {
14 | var xhr = new XMLHttpRequest();
15 |
16 | xhr.open('GET', this.url(url), false);
17 | xhr.send();
18 |
19 | return xhr.response;
20 | };
21 |
22 | exports.load = function(url) {
23 | var self = this;
24 |
25 | return new Promise(function(resolve, reject) {
26 | var xhr = new XMLHttpRequest();
27 | var loaded = false;
28 |
29 | xhr.onload = function() {
30 | loaded = true;
31 | resolve(xhr.response);
32 | };
33 |
34 | xhr.onloadend = function() {
35 | if (loaded) return;
36 | reject();
37 | };
38 |
39 | xhr.open('GET', self.url(url), true);
40 | xhr.send();
41 | })
42 | };
--------------------------------------------------------------------------------
/shared/fw/modules/checkbox.js:
--------------------------------------------------------------------------------
1 | var ui = require('ui'),
2 | parser = require('parser');
3 |
4 | var exports = {
5 | events: events.getMap(module.name, [
6 | 'checked'
7 | ])
8 | };
9 |
10 | ui.define('checkbox', {
11 | base: ['input[type="checkbox"]'],
12 | handler: function() {
13 | var self = this,
14 | selfChecked = self.get('checked'),
15 | baseChecked = self.node.checked;
16 |
17 | if (selfChecked && !baseChecked) {
18 | self.node.checked = true;
19 | } else if (!selfChecked && baseChecked) {
20 | self.set('boolean:checked', true);
21 | }
22 |
23 | events.on(self.node, 'click change', function() {
24 | var checked = self.node.checked;
25 |
26 | if (self.get('checked') !== checked) {
27 | self.set('boolean:checked', checked);
28 | events.fire(self, exports.events.checked);
29 | }
30 | });
31 | },
32 | properties: {
33 | checked: ['boolean', false, {
34 | set: function(control, name, value) {
35 | this.node.checked = value;
36 | }
37 | }]
38 | }
39 | });
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Promises Debugger Extension
2 |
3 | ## Hello
4 |
5 | Promises Debugger Extension allow you debug native Promises (ES6) right now in current and higher versions of Chrome and Firefox.
6 |
7 | Please see video for details. Extension is in really early version, but soon it will have more features.
8 |
9 | ## Video
10 |
11 |
14 |
15 | ## How to use
16 |
17 | * First you need to run ```init.bat``` if you are on Window, or ```init.sh``` if you are on Linux/OS X
18 | * To run Firefox extension you should have Addons-SDK installed, then go to ```firefox``` subfolder and run ```cfx run```
19 | * To run Chrome extension, just load it as an unpacket extension from subfolder ```chrome```
20 |
21 | __**Note:** Doesn't catch Promise errors from scripts which are produced before document is completely parsed.
22 | By some reason scripts cannot be injected before it, at least in Chrome.
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Arthur Stolyar
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/shared/ext_modules/prefs.js:
--------------------------------------------------------------------------------
1 | var storage = require('shared/storage.js');
2 | var ext = require('shared/ext.js');
3 |
4 | var PREFS_KEY = 'prefs';
5 | var PREFS_FILE = 'shared/prefs.json';
6 |
7 | exports.Prefs = function(url) {
8 | this.url = url || PREFS_FILE;
9 | this.init();
10 | };
11 |
12 | exports.Prefs.prototype = {
13 | _prefs: null,
14 | init: function() {
15 | var self = this;
16 |
17 | this.ready = storage.get(PREFS_KEY).then(function(prefs) {
18 | if (!prefs) return self.load();
19 |
20 | return prefs;
21 | }, function(err) {
22 | // do error log here
23 |
24 | return self.load();
25 | }).then(function(prefs) {
26 | self.local = prefs;
27 | });
28 | },
29 | get: function(key) {
30 | return this.local[key];
31 | },
32 | set: function(key, val) {
33 | this.local[key] = val;
34 |
35 | storage.set(PREFS_KEY, this.local);
36 | },
37 | getAll: function() {
38 | return this.local;
39 | },
40 | load: function() {
41 | return ext.load(this.url).then(function(res) {
42 | if (!res) return null;
43 |
44 | res = res.replace(/\/\/([\s\S]+?)$/mg, '').trim();
45 |
46 | return JSON.parse(res);
47 | });
48 | }
49 | };
--------------------------------------------------------------------------------
/chrome/scripts/storage.js:
--------------------------------------------------------------------------------
1 | var lastError = function() {
2 | return chrome.runtime.lastError;
3 | };
4 |
5 | module.exports = {
6 | set: function(key, value) {
7 | var pass = {};
8 |
9 | pass[key] = value;
10 |
11 | return new Promise(function(resolve, reject) {
12 | chrome.storage.local.set(pass, function() {
13 | if (lastError()) {
14 | reject(lastError());
15 | return;
16 | }
17 |
18 | resolve();
19 | });
20 | });
21 | },
22 | get: function(key) {
23 | if (typeof key !== 'string') {
24 | return Promise.reject(new TypeError('Bad argument'));
25 | }
26 |
27 | return new Promise(function(resolve, reject) {
28 | chrome.storage.local.get(key, function(items) {
29 | if (lastError()) {
30 | reject(lastError());
31 | return;
32 | }
33 |
34 | resolve(items[key]);
35 | });
36 | });
37 | },
38 | remove: function(key) {
39 | return new Promise(function(resolve, reject) {
40 | chrome.storage.local.remove(key, function() {
41 | if (lastError()) {
42 | reject(lastError());
43 | return;
44 | }
45 |
46 | resolve();
47 | });
48 | });
49 | },
50 | getAll: function() {
51 | return new Promise(function(resolve, reject) {
52 | chrome.storage.get(null, function(items) {
53 | if (lastError()) {
54 | reject(lastError());
55 | return;
56 | }
57 |
58 | resolve(items);
59 | });
60 | });
61 | },
62 | };
--------------------------------------------------------------------------------
/chrome/scripts/commonjs.js:
--------------------------------------------------------------------------------
1 | (function(global) {
2 | var modules = new Map();
3 |
4 | var LIB_URL = chrome.runtime.getURL('/scripts/');
5 | var SHARED_URL = chrome.runtime.getURL('/shared/ext_modules/');
6 |
7 | var loadModule = function(path) {
8 | var xhr = new XMLHttpRequest();
9 |
10 | xhr.open('GET', path, false);
11 | xhr.send();
12 |
13 | try {
14 | var response = xhr.response;
15 | } catch (e) {}
16 |
17 | if (!response) return;
18 |
19 | var module = {
20 | exports: {},
21 | name: path
22 | };
23 |
24 | response = '"use strict";\n\n' + response;
25 |
26 | var fn = new Function('module', 'exports', response);
27 | fn.call(global, module, module.exports);
28 |
29 | return module;
30 | };
31 |
32 | global.require = function(path) {
33 | path = path.replace(/(?:\.js)?$/i, '.js');
34 |
35 | if (!path.indexOf('chrome-extension://')) {
36 | // do nothing
37 | } else if (!path.indexOf('shared/')) {
38 | path = SHARED_URL + path.replace('shared/', '');
39 | } else if (!path.indexOf('lib/')) {
40 | path = LIB_URL + path.replace('lib/', '');
41 | } else if (path[0] === '.' || path[0] === '/') {
42 | path = chrome.runtime.getURL(path);
43 | } else {
44 | // relative
45 | path = LIB_URL + path;
46 | }
47 |
48 | if (!path) return null;
49 |
50 | if (modules.has(path)) {
51 | return modules.get(path).exports;
52 | }
53 |
54 | var module = loadModule(path);
55 |
56 | if (!module) return null;
57 |
58 | console.log('[require]:', path);
59 |
60 | // same as firefox sdk does
61 | Object.freeze(module.exports);
62 | modules.set(path, module);
63 |
64 | return module.exports;
65 | };
66 | }(this));
--------------------------------------------------------------------------------
/shared/fw/cui/loader.debug.js:
--------------------------------------------------------------------------------
1 | (function(win) {
2 | var LOADER_VERSION = 'LOADER_VERSION',
3 | LOADER_MODULES = 'LOADER_MODULES',
4 | LOCAL_STORAGE = 'localStorage',
5 | GET_ITEM = 'getItem',
6 | FUNCTION = 'Function',
7 | DOCUMENT = 'document',
8 | SET_TIMEOUT = 'setTimeout',
9 | ASYNC = 'async',
10 | PUSH = 'push',
11 | SCRIPT_TAG = 'script',
12 | LOADER = 'loader',
13 | R_EVAL = /\$\{([^\=\&^\}]*?)\}/gi;
14 |
15 | var domReady = [],
16 | doc = win[DOCUMENT],
17 | domReadyHandler = function() {
18 | for (var i = 0, len = domReady.length; i < len; i++) {
19 | win[SET_TIMEOUT](domReady[i], 1);
20 | }
21 |
22 | domReady = 1;
23 | };
24 |
25 | var modules = win.modules = {
26 | dom: function(fn) {
27 | if (domReady === 1) {
28 | win[SET_TIMEOUT](fn, 1);
29 | } else {
30 | domReady[PUSH](fn);
31 | }
32 | },
33 | ready: function(fn) {
34 | modules.readyList[PUSH](fn);
35 | },
36 | load: function(loader) {
37 | loader.debug = true;
38 | modules.loader = loader;
39 |
40 | if ((win[LOCAL_STORAGE][GET_ITEM](LOADER_VERSION) | 0) === loader.version) {
41 | domReady[PUSH](new win[FUNCTION](win[LOCAL_STORAGE][GET_ITEM](LOADER_MODULES)));
42 | } else {
43 | var url = loader.url.replace(R_EVAL, function(input, key) {
44 | return (new Function(LOADER, 'with(' + LOADER + ') {(' + loader[key] + ')}'))(loader);
45 | });
46 |
47 | doc.write('');
48 | }
49 | },
50 | readyList: [],
51 | LOADER_VERSION: LOADER_VERSION,
52 | LOADER_MODULES: LOADER_MODULES,
53 | PACKAGED_CALLBACK: '_PCB' + +(new Date), // Packaged CallBack
54 | R_EVAL: R_EVAL
55 | };
56 |
57 | doc.addEventListener('DOMContentLoaded', domReadyHandler, !1);
58 | }(this));
--------------------------------------------------------------------------------
/shared/fw/cui/loader2.js:
--------------------------------------------------------------------------------
1 | (function(win) {
2 | var LOADER_VERSION = 'LOADER_VERSION',
3 | LOADER_MODULES = 'LOADER_MODULES',
4 | LOCAL_STORAGE = 'localStorage',
5 | GET_ITEM = 'getItem',
6 | FUNCTION = 'Function',
7 | DOCUMENT = 'document',
8 | SET_TIMEOUT = 'setTimeout',
9 | ADD_EVENT_LISTENER = 'addEventListner',
10 | REPLACE = 'replace';
11 |
12 | var domReady = [],
13 | version = +'= intval($version) ?>',
14 | deps = '= json_encode($files) ?>',
15 | url = '= $getter ?>',
16 | doc = win[DOCUMENT],
17 | domReadyHandler = function() {
18 | for (var i = 0, len = domReady.length; i < len; i++) {
19 | win[SET_TIMEOUT](domReady[i], 1);
20 | }
21 |
22 | domReady = 1;
23 | },
24 | cached;
25 |
26 | win.modules = {
27 | dom: function(fn) {
28 | if (domReady === 1) {
29 | win[SET_TIMEOUT](fn, 1);
30 | } else {
31 | domReady.push(fn);
32 | }
33 | },
34 | loader: {
35 | version: version,
36 | deps: deps,
37 | url: url,
38 | VERSION_KEY: LOADER_VERSION,
39 | MODULES_KEY: LOADER_MODULES
40 | },
41 | ready: function(fn) {
42 | modules.readyList.push(fn);
43 | },
44 | readyList: []
45 | };
46 |
47 | if (doc[ADD_EVENT_LISTENER]) {
48 | doc[ADD_EVENT_LISTENER]('DOMContentLoaded', domReadyHandler, !1);
49 | } else {
50 | win.attachEvent('onload', domReadyHandler);
51 | }
52 |
53 | if (cached = (win[LOCAL_STORAGE][GET_ITEM](VERSION_KEY) | 0) === version) {
54 | (new win[FUNCTION]([LOCAL_STORAGE][GET_ITEM](MODULES_KEY)))();
55 | }
56 |
57 | doc.write('');
58 | }(this));
59 |
60 | modules.ready(function(mods) {
61 | var parser = mods.parser,
62 | events = mods.events;
63 |
64 | events.fire(document.body, parser.events.parse);
65 | });
--------------------------------------------------------------------------------
/shared/fw/cui/loader.js:
--------------------------------------------------------------------------------
1 | (function(win) {
2 | var LOADER_VERSION = 'LOADER_VERSION',
3 | LOADER_MODULES = 'LOADER_MODULES',
4 | LOCAL_STORAGE = 'localStorage',
5 | GET_ITEM = 'getItem',
6 | FUNCTION = 'Function',
7 | DOCUMENT = 'document',
8 | SET_TIMEOUT = 'setTimeout',
9 | ASYNC = 'async',
10 | PUSH = 'push',
11 | SCRIPT_TAG = 'script',
12 | LOADER = 'loader',
13 | R_EVAL = /\$\{([^\=\&^\}]*?)\}/gi;
14 |
15 | var domReady = [],
16 | doc = win[DOCUMENT],
17 | domReadyHandler = function() {
18 | for (var i = 0, len = domReady.length; i < len; i++) {
19 | win[SET_TIMEOUT](domReady[i], 1);
20 | }
21 |
22 | domReady = 1;
23 | };
24 |
25 | var modules = win.modules = {
26 | dom: function(fn) {
27 | if (domReady === 1) {
28 | win[SET_TIMEOUT](fn, 1);
29 | } else {
30 | domReady[PUSH](fn);
31 | }
32 | },
33 | ready: function(fn) {
34 | modules.readyList[PUSH](fn);
35 | },
36 | load: function(loader) {
37 | var script = doc.createElement(SCRIPT_TAG),
38 | first = doc.querySelector(SCRIPT_TAG),
39 | insert = function() {
40 | first.parentNode.insertBefore(script, first);
41 | };
42 |
43 | modules.loader = loader;
44 |
45 | if ((win[LOCAL_STORAGE][GET_ITEM](LOADER_VERSION) | 0) === loader.version) {
46 | domReady[PUSH](new win[FUNCTION](win[LOCAL_STORAGE][GET_ITEM](LOADER_MODULES)));
47 | } else {
48 | script.src = loader.url.replace(R_EVAL, function(input, key) {
49 | return (new Function(LOADER, 'with(' + LOADER + ') {(' + loader[key] + ')}'))(loader);
50 | });
51 |
52 | if (ASYNC in script) {
53 | script[ASYNC] = !0;
54 | insert();
55 | } else {
56 | domReady[PUSH](insert);
57 | }
58 | }
59 | },
60 | readyList: [],
61 | LOADER_VERSION: LOADER_VERSION,
62 | LOADER_MODULES: LOADER_MODULES,
63 | PACKAGED_CALLBACK: '_PCB' + +(new Date), // Packaged CallBack
64 | R_EVAL: R_EVAL
65 | };
66 |
67 | doc.addEventListener('DOMContentLoaded', domReadyHandler, !1);
68 | }(this));
69 |
70 | /*modules.load({
71 | version: 1,
72 | url: '/modules.js?deps=${deps}&v=${version}&init=${!modules.inited}&callback=${modules.PACKAGED_CALLBACK}'
73 | });*/
--------------------------------------------------------------------------------
/shared/promises-panel.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
24 | Promises Debugger
25 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
53 |
54 |
Start Watch & Reload page
58 |
59 |
Start Watch
63 |
64 |
65 |
66 |
74 |
75 |
76 |
77 |
80 |
83 |
84 |
85 |
93 |
96 |
100 |
101 |
109 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/chrome/promises-frontend.js:
--------------------------------------------------------------------------------
1 | ;(function(global) {
2 | console.log('inject isWatchingPage:', global.isWatchingPage);
3 |
4 | if (global.isWatchingPage) return;
5 | global.isWatchingPage = true;
6 |
7 | var port,
8 | messageBuffer = [],
9 | isChrome = true;
10 |
11 | var onDisconnect = function() {
12 | window.removeEventListener('message', backendListener);
13 | port = null;
14 | messageBuffer = [];
15 | global.isAttached = false;
16 | };
17 |
18 | var handleEverStack = function(stack) {
19 | var lines = stack.split(/(?:\n+|\->)/),
20 | line,
21 | i = 0,
22 | newLines = [],
23 | firstLine = lines[0],
24 | message;
25 |
26 | if (isChrome && firstLine &&
27 | firstLine.search(/\bat\b/) === -1 && firstLine.search(/error/i) !== -1) {
28 | message = firstLine;
29 | lines = lines.slice(1);
30 | }
31 |
32 | if (true) {
33 | while (i < lines.length) {
34 | line = lines[i];
35 | ++i;
36 |
37 | if (
38 | line && (
39 | line.indexOf('(native)') !== -1 ||
40 | line.indexOf('(:') !== -1 ||
41 | line.indexOf('resource://') !== -1 ||
42 | line.indexOf('jar:file://') !== -1
43 | )
44 | ) {
45 | continue;
46 | }
47 |
48 | if (line) {
49 | newLines.push(line);
50 | }
51 | }
52 | } else {
53 | newLines = lines;
54 | }
55 |
56 | if (!newLines.length) {
57 | return null;
58 | }
59 |
60 | return {
61 | lines: newLines,
62 | message: message
63 | };
64 | };
65 |
66 | global.registerDevToolsListeners = function(name) {
67 | console.log('registerDevToolsListeners:', name);
68 |
69 | if (port) return;
70 |
71 | port = chrome.runtime.connect({
72 | name: name
73 | });
74 |
75 | global.isAttached = true;
76 |
77 | port.onDisconnect.addListener(onDisconnect);
78 |
79 | if (messageBuffer.length) {
80 | messageBuffer.forEach(function(message) {
81 | // console.log('resend messages');
82 | port.postMessage(message);
83 | });
84 |
85 | messageBuffer = null;
86 | }
87 |
88 | console.log(port);
89 | };
90 |
91 | var backendListener = function(e) {
92 | if (e.source !== window) {
93 | console.warn('bad source');
94 | return;
95 | }
96 |
97 | var data = e.data;
98 |
99 | if (!data || !data.PromisesDebugger) return;
100 |
101 | if (data.method === 'requestUpdate') {
102 | var message = {
103 | action: 'update_data',
104 | data: data.message
105 | };
106 |
107 |
108 | if (port) {
109 | port.postMessage(message);
110 | } else {
111 | messageBuffer.push(message);
112 | }
113 | } else if (data.method === 'reportError') {
114 | global.reportError(data.message);
115 | }
116 | };
117 |
118 | global.attachToBackend = function() {
119 | global.registerDevToolsListeners('FRONT_END__TO__DEV_TOOLS');
120 | window.addEventListener('message', backendListener);
121 | };
122 |
123 | global.detachFromBackend = function() {
124 | if (port) {
125 | port.disconnect();
126 | }
127 |
128 | onDisconnect();
129 | };
130 |
131 | global.attachToBackend();
132 | global.evalBackend = function(code) {
133 | var script = document.createElement('script');
134 |
135 | script.textContent = code;
136 | document.documentElement.appendChild(script);
137 | document.documentElement.removeChild(script);
138 | };
139 |
140 | global.reportError = function(message) {
141 | var error = message.error,
142 | provider = message.provider || '';
143 |
144 | if (!error || !error.value) return;
145 |
146 | var value = error.value,
147 | message,
148 | stack;
149 |
150 | message = (value.name ? value.name + ': ' : '') + value.message;
151 | stack = value.stack ? handleEverStack(value.stack) : null;
152 |
153 | var showProvider = false;
154 |
155 | console.groupCollapsed(
156 | '%cPromise reject:' + (showProvider ? '[' + provider + ']:' : '') + ' ' + ((stack && stack.message) || message || ''),
157 | 'color: red;'
158 | );
159 |
160 | if (stack && stack.lines.length) {
161 | stack.lines.forEach(function(line) {
162 | console.log('%c' + line.trim(), 'color: red;');
163 | });
164 | } else {
165 | console.log('%c', 'color: red;')
166 | }
167 |
168 | console.groupEnd();
169 | };
170 |
171 | (function() {
172 | console.log("hello from injected code");
173 |
174 |
175 | if (typeof backendCode !== 'undefined') {
176 | global.evalBackend(backendCode);
177 | }
178 | }());
179 | }(this));
--------------------------------------------------------------------------------
/firefox/lib/target-logger.js:
--------------------------------------------------------------------------------
1 | const XHTML_NS = "http://www.w3.org/1999/xhtml";
2 | const isChrome = false;
3 |
4 | var handleEverStack = function(stack) {
5 | var lines = stack.split(/(?:\n+|\->)/),
6 | line,
7 | i = 0,
8 | newLines = [],
9 | firstLine = lines[0],
10 | message;
11 |
12 | if (isChrome && firstLine &&
13 | firstLine.search(/\bat\b/) === -1 && firstLine.search(/error/i) !== -1) {
14 | message = firstLine;
15 | lines = lines.slice(1);
16 | }
17 |
18 | if (true) {
19 | while (i < lines.length) {
20 | line = lines[i];
21 | ++i;
22 |
23 | if (
24 | line && (
25 | line.indexOf('(native)') !== -1 ||
26 | line.indexOf('(:') !== -1 ||
27 | line.indexOf('resource://') !== -1 ||
28 | line.indexOf('jar:file://') !== -1
29 | )
30 | ) {
31 | continue;
32 | }
33 |
34 | if (line) {
35 | newLines.push(line);
36 | }
37 | }
38 | } else {
39 | newLines = lines;
40 | }
41 |
42 | if (!newLines.length) {
43 | return null;
44 | }
45 |
46 | return {
47 | lines: newLines,
48 | message: message
49 | };
50 | };
51 |
52 | var makeMessage = function(document, data) {
53 | let value = data.error.value;
54 | let provider = data.provider;
55 | let name = value.name;
56 | let title = 'Promise reject: ' + (name ? name + ': ' : '') +
57 | (value.message || '');
58 |
59 | let messageNode = document.createElementNS(XHTML_NS, 'div');
60 |
61 | messageNode.style.display = 'block';
62 | messageNode.style.color = '#CD2929';
63 |
64 | let groupTitle = makeGroupTitle(document, title);
65 | messageNode.appendChild(groupTitle);
66 |
67 | let groupContainer = makeGroupContainer(document);
68 | messageNode.appendChild(groupContainer);
69 |
70 | groupTitle.addEventListener('click', function() {
71 | groupContainer.hidden = !groupContainer.hidden;
72 |
73 | var display = groupTitle.cornerOpened.style.display === 'inline-block' ?
74 | 'none' : 'inline-block';
75 |
76 | groupTitle.cornerClosed.style.display =
77 | (groupTitle.cornerOpened.style.display = display) === 'inline-block' ?
78 | 'none' : 'inline-block';
79 | });
80 |
81 | let stack = value.stack ? handleEverStack(value.stack) : null;
82 |
83 | if (stack && stack.lines.length) {
84 | stack.lines.forEach(function(line) {
85 | let lineNode = makeLogItem(document, line);
86 |
87 | groupContainer.appendChild(lineNode);
88 | });
89 | } else {
90 | let lineNode = makeLogItem(document, '');
91 |
92 | groupContainer.appendChild(lineNode);
93 | }
94 |
95 | return messageNode;
96 | },
97 | makeGroupTitle = function(document, title) {
98 | let groupTitle = document.createElementNS(XHTML_NS, 'div');
99 |
100 | // groupTitle.style.position = 'relative';
101 | groupTitle.style.cursor = 'pointer';
102 |
103 | let cornerClosed = document.createElementNS(XHTML_NS, 'span');
104 |
105 | cornerClosed.style.display = 'inline-block';
106 | cornerClosed.style.width = 0;
107 | cornerClosed.style.height = 0;
108 | cornerClosed.style.borderTop = '4px solid transparent'
109 | cornerClosed.style.borderBottom = '4px solid transparent'
110 | cornerClosed.style.borderLeft = '6px solid #777';
111 | cornerClosed.style.verticalAlign = 'middle';
112 | cornerClosed.style.margin = '0 10px 0 0';
113 |
114 | groupTitle.appendChild(cornerClosed);
115 |
116 | let cornerOpened = document.createElementNS(XHTML_NS, 'span');
117 |
118 | cornerOpened.style.display = 'none';
119 | cornerOpened.style.width = 0;
120 | cornerOpened.style.height = 0;
121 | cornerOpened.style.borderLeft = '4px solid transparent'
122 | cornerOpened.style.borderRight = '4px solid transparent'
123 | cornerOpened.style.borderTop = '6px solid #777';
124 | cornerOpened.style.verticalAlign = 'middle';
125 | cornerOpened.style.margin = '1px 8px 1px 0';
126 |
127 | groupTitle.appendChild(cornerOpened);
128 |
129 | groupTitle.cornerOpened = cornerOpened;
130 | groupTitle.cornerClosed = cornerClosed;
131 |
132 | let text = document.createElementNS(XHTML_NS, 'span');
133 |
134 | text.textContent = title;
135 | text.style.fontWeight = 'bold';
136 | text.style.verticalAlign = 'middle';
137 |
138 | groupTitle.appendChild(text);
139 |
140 | return groupTitle;
141 | },
142 | makeGroupContainer = function(document) {
143 | let groupContainer = document.createElementNS(XHTML_NS, 'div');
144 |
145 | groupContainer.hidden = true;
146 | groupContainer.style.margin = '5px 0 5px 15px';
147 | groupContainer.style.paddingLeft = '14px';
148 | groupContainer.style.borderLeft = '1px solid #777';
149 |
150 | return groupContainer;
151 | },
152 | makeLogItem = function(document, text) {
153 | let logItem = document.createElementNS(XHTML_NS, 'div');
154 |
155 | logItem.textContent = text;
156 | logItem.style.margin = '5px 0';
157 |
158 | return logItem;
159 | };
160 |
161 | exports.Logger = function(webConsoleUI) {
162 | this.ui = webConsoleUI;
163 | };
164 |
165 | exports.Logger.prototype = {
166 | promiseError: function(data) {
167 | let ui = this.ui;
168 | let message = makeMessage(ui.document, data);
169 |
170 | message = ui.createMessageNode(3, 0, message, '', 0, '');
171 | ui.outputMessage(3, message);
172 | }
173 | };
--------------------------------------------------------------------------------
/shared/fw/cui/modules/templates-utils.js:
--------------------------------------------------------------------------------
1 |
2 | ui.define('compiler', {
3 | parent: 'element',
4 | properties: {
5 | template: ['Default']
6 | },
7 | handler: function() {
8 | var self = this,
9 | compile;
10 |
11 | this.compile = function(data, sanitization) {
12 | var config = {
13 | params: Sync.extend({}, self.get('params'))
14 | };
15 |
16 | compile || (compile = template(self.get('template')));
17 |
18 | if (typeof sanitization === 'undefined' || sanitization === true) {
19 | sanitize(data, 'request', config);
20 | } else {
21 | if (Array.isArray(data)) {
22 | data = data.concat();
23 | } else if (typeof data === 'object') {
24 | data = Sync.extend({}, data);
25 | }
26 |
27 | config.request = data;
28 | }
29 |
30 | events.fire(self.node, exports.events.beforeCompile, config);
31 |
32 | return compile(config);
33 | };
34 | }
35 | });
36 |
37 | ui.define('inline-template', {
38 | parent: 'compiler',
39 | handler: function() {
40 | var template = this.view.innerHTML,
41 | self = this;
42 |
43 | // IE wtf
44 | template = template.replace(/='([\s\S]*?)'/g, function(str, pattern) {
45 | return '="' + utils.escapeHTML(pattern) + '"';
46 | });
47 |
48 | this.set('template', template);
49 | this.view.innerHTML = '';
50 |
51 | events.on(this.view, ui.events.destroy, function() {
52 | self.view.innerHTML = template;
53 | });
54 |
55 | var node = exports.currentNode();
56 |
57 | if (node) {
58 | node.children = [];
59 | }
60 | }
61 | });
62 |
63 | //John Resig template pattern
64 | //http://ejohn.org/blog/javascript-micro-templating/
65 | function template(str, fn) {
66 | if (str.nodeType) {
67 | return template(str.innerHTML);
68 | } else {
69 | str = str.replace(/[\r\t\n]/g, " ")
70 | .split("<%").join("\t")
71 | .replace(/((^|%>)[^\t]*)'/g, "$1\r")
72 | .replace(/\t=(.*?)%>/g, "',$1,'")
73 | .split("\t").join("');")
74 | .split("%>").join("p.push('")
75 | .split("\r").join("\\'");
76 |
77 | fn = new Function("var p=[],print=function(){p.push.apply(p,arguments);};" +
78 | "with(this){p.push('" + str + "');}return p.join('');");
79 | };
80 |
81 | return function(data) {
82 | return fn.call(data);
83 | };
84 | }
85 |
86 | function sanitize(value, key, self) {
87 | if (value && typeof value === 'string') {
88 | value = utils.escapeHTML(value);
89 | } else if (Array.isArray(value)) {
90 | (value = value.concat()).forEach(sanitize);
91 | } else if (value && typeof value === 'object' &&
92 | !(ui.is(value, 'element')) && !value.nodeType) {
93 | Sync.each(value = Sync.extend({}, value), sanitize);
94 | }
95 |
96 | self[key] = value;
97 | }
98 |
99 | function generateTemplate(text, name) {
100 | return (text && name) ? ui.create('compiler', {
101 | properties: {
102 | template: text,
103 | templateName: name
104 | }
105 | }) : null;
106 | }
107 |
108 | function generateFromMap(value, tplName) {
109 | var tmp,
110 | templates = modules.require('templates');
111 |
112 | value = Sync.extend({}, value);
113 |
114 | if (tplName) {
115 | return templates.hasTemplate(tmp = value[tplName]) ?
116 | generateTemplate(templates.getTemplate(tmp), tmp) : null;
117 | } else {
118 | Object.keys(value).forEach(function(tpl) {
119 | if (templates.hasTemplate(tmp = value[tpl])) {
120 | value[tpl] = generateTemplate(templates.getTemplate(tmp), tmp);
121 | } else {
122 | delete value[tpl];
123 | }
124 | });
125 |
126 | return value;
127 | }
128 | }
129 |
130 | ui.type.define('tpl', {
131 | factory: function(data) {
132 | return {
133 | _default: data || ''
134 | }
135 | },
136 | get: function(control, name, tplName) {
137 | var cache = typedCache(this.type, control, name),
138 | templates = modules.require('templates'),
139 | value,
140 | tmp = null;
141 |
142 | if (cache) {
143 | cache = cache.valueOf();
144 |
145 | if (cache instanceof ui.controls.Compiler && !tplName) {
146 | return generateTemplate(cache.get('template'), cache.get('templateName'));
147 | } else if (typeof cache === 'object' && !isArray(cache)) {
148 | return generateFromMap(cache, tplName);
149 | } else if (typeof cache === 'string' && !tplName) {
150 | return templates.hasTemplate(cache) ?
151 | generateTemplate(templates.getTemplate(cache), cache) : null;
152 | }
153 | }
154 |
155 | value = ui.types.json.get.call(this, control, name);
156 |
157 | if (value && typeof value === 'object' && !Array.isArray(value)) {
158 | tmp = generateFromMap(value, tplName);
159 | } else if (value = ui.types.string.get.call(this, control, name)) {
160 | tmp = templates.hasTemplate(value) ?
161 | generateTemplate(templates.getTemplate(value), value) : null;
162 | }
163 |
164 | return tmp;
165 | },
166 | set: function(control, name, value) {
167 | if (!value) return;
168 |
169 | if (typeof value === 'string') {
170 | var templates = modules.require('templates');
171 |
172 | if (templates.hasTemplate(value)) {
173 | return typedCache(this.type, control, name, value);
174 | }
175 |
176 | } else if (typeof value === 'object' &&
177 | value instanceof ui.controls.Compiler || !isArray(value)) {
178 | return typedCache(this.type, control, name, value);
179 | }
180 | }
181 | });
--------------------------------------------------------------------------------
/chrome/scripts/runtime.js:
--------------------------------------------------------------------------------
1 | var prefs = new (require('shared/prefs.js').Prefs);
2 | var ext = require('shared/ext.js');
3 | var backend = require('shared/backend.js');
4 | var global = this;
5 |
6 | prefs.ready.then(function() {
7 | console.log(prefs.getAll());
8 | });
9 |
10 | var inspections = new (global.Set || global.WeakSet),
11 | inspectionsMap = {},
12 | webNavigationWanting = false;
13 |
14 | var onBeforeNavigate = function(details) {
15 | if (details.frameId !== 0) return;
16 |
17 | var inspectData = inspectionsMap[details.tabId];
18 | if (!inspectData) return;
19 |
20 | attachToTarget(inspectData);
21 |
22 | inspectData = null;
23 | },
24 | onCommitted = function(details) {
25 | if (details.frameId !== 0) return;
26 |
27 | var inspectData = inspectionsMap[details.tabId];
28 | if (!inspectData) return;
29 |
30 | attachToTarget(inspectData);
31 |
32 | inspectData.port.postMessage({
33 | action: 'reload'
34 | });
35 |
36 | inspectData = null;
37 | };
38 |
39 | var startWebNavigationWatch = function() {
40 | webNavigationWanting = true;
41 |
42 | chrome.webNavigation.onBeforeNavigate.addListener(onBeforeNavigate);
43 | chrome.webNavigation.onCommitted.addListener(onCommitted);
44 | },
45 | stopWebNavigationWatch = function() {
46 | webNavigationWanting = false;
47 |
48 | chrome.webNavigation.onBeforeNavigate.removeListener(onBeforeNavigate);
49 | chrome.webNavigation.onCommitted.removeListener(onCommitted);
50 | },
51 | attachToTarget = function(inspectData, callback) {
52 | chrome.tabs.executeScript(inspectData.tabId, {
53 | code: injectCode,
54 | runAt: 'document_start'
55 | }, function() {
56 | if (callback) {
57 | callback();
58 | }
59 | });
60 | };
61 |
62 | chrome.runtime.onConnect.addListener(function(port) {
63 | if (port.name !== 'DEV_TOOLS') return;
64 |
65 | console.log('port connect');
66 |
67 | var inspectData = {
68 | port: port
69 | };
70 |
71 | var messageListener = function(message, port) {
72 | if (!('tabId' in inspectData)) {
73 | handleTabId(message, port);
74 | }
75 |
76 | if (message.action === 'start_watch_page') {
77 | startWatchHandler(message, port);
78 | }
79 |
80 | if (message.action === 'stop_watch_page') {
81 | stopWatchHandler(message, port);
82 | }
83 |
84 | if (message.action === 'prepare_front_end') {
85 | prepareFrontEnd(message, port);
86 | }
87 | };
88 |
89 | var startWatchHandler = function(message, port) {
90 | if (!webNavigationWanting) {
91 | // first call from dev_tools
92 | // start watching webNavigation
93 | startWebNavigationWatch();
94 | }
95 |
96 | inspectData.tab.then(function() {
97 | if (message.data.attach) {
98 | attachToTarget(inspectData);
99 | }
100 |
101 | port.postMessage({
102 | action: 'watch_started'
103 | });
104 | });
105 | },
106 | stopWatchHandler = function(message, port) {
107 | if (webNavigationWanting) {
108 | // first call from dev_tools
109 | // start watching webNavigation
110 | stopWebNavigationWatch();
111 | }
112 | },
113 | prepareFrontEnd = function(message, port) {
114 | chrome.tabs.executeScript(inspectData.tabId, {
115 | code: ';(function() {}());',
116 | runAt: 'document_start'
117 | }, function() {
118 |
119 | });
120 | },
121 | handleTabId = function(message, port) {
122 | var handleTab = function(tab) {
123 | inspectData.tab = tab;
124 | },
125 | handleMap = function(id) {
126 | console.log('got tab id');
127 |
128 | inspectData.tabId = id;
129 | inspectionsMap[id] = inspectData;
130 | };
131 |
132 | // port.sender.id always exists
133 | // always self extension id?
134 | if (port.sender.tab) {
135 | // debug extension, not sure only self or not
136 | // message.data.tabId is undefined
137 | // but send.tab and port.sender.url exists
138 | handleMap(port.sender.tab.id);
139 | handleTab(Promise.resolve(port.sender.tab));
140 | } else if (message.data && 'tabId' in message.data) {
141 | // debug web page
142 | // tab object is not exists, only tabId in message.data
143 | // need to get tab object
144 | handleMap(message.data.tabId);
145 |
146 | handleTab(new Promise(function(resolve) {
147 | chrome.tabs.get(message.data.tabId, function(tab) {
148 | resolve(tab);
149 | });
150 | }));
151 | }
152 | };
153 |
154 | inspections.add(inspectData);
155 | port.onMessage.addListener(messageListener);
156 |
157 | port.onDisconnect.addListener(function() {
158 | console.log('port disconnect');
159 | port.onMessage.removeListener(messageListener);
160 |
161 | stopWatchHandler();
162 |
163 | if (inspectData && inspectData.tabId) {
164 | inspectionsMap[inspectData.tabId] = null;
165 | }
166 |
167 | inspections.delete(inspectData);
168 | });
169 | });
170 |
171 | chrome.runtime.onConnect.addListener(function(port) {
172 | if (port.name !== 'FRONT_END__TO__DEV_TOOLS') return;
173 |
174 | var inspectData = inspectionsMap[port.sender.tab.id];
175 |
176 | // console.log('BOUND TO FRONT_END', inspectData);
177 | if (!inspectData) return;
178 |
179 |
180 | inspectData.port.postMessage({
181 | action: 'front_end_started'
182 | });
183 |
184 | var messageListener = function(message) {
185 | // console.log('resend message');
186 | inspectData.port.postMessage({
187 | action: 'front_end_event',
188 | data: message
189 | });
190 | };
191 |
192 | var disconnectHandler = function() {
193 | port.onMessage.removeListener(messageListener);
194 | port.onDisconnect.removeListener(disconnectHandler);
195 | };
196 |
197 | inspectData.port.onDisconnect.addListener(function() {
198 | disconnectHandler();
199 | port.disconnect();
200 | });
201 |
202 | port.onMessage.addListener(messageListener);
203 | port.onDisconnect.addListener(function() {
204 | // console.log('FRONT_END__TO__DEV_TOOLS disconnect');
205 | });
206 |
207 | port.onDisconnect.addListener(disconnectHandler);
208 | });
209 |
210 | var debugFrontendCode = ext.loadSync('promises-frontend.js');
211 | var debugBackendCode = backend.getCode();
212 | var injectCode = debugBackendCode + debugFrontendCode;
--------------------------------------------------------------------------------
/chrome/devtools.js:
--------------------------------------------------------------------------------
1 | var panel,
2 | panelWindow,
3 | panelPending = [],
4 | watchListenersRegistered;
5 |
6 | chrome.devtools.panels.sources.createSidebarPane("My Sidebar", function(sidebar) {
7 | console.log(sidebar);
8 | // sidebar initialization code here
9 | sidebar.setObject({ some_data: "Some data to show" });
10 | });
11 |
12 | chrome.devtools.panels.create('Promises', 'shared/images/promises.png', 'shared/promises-panel.html', function(promisesPanel) {
13 | panel = promisesPanel;
14 |
15 | panel.onShown.addListener(function waitShow(win) {
16 | panelWindow = win;
17 |
18 | var arr = panelPending;
19 |
20 | panelPending = [];
21 |
22 | arr.forEach(function(arr) {
23 | UIAction(arr[0], arr[1]);
24 | });
25 |
26 | panel.onShown.removeListener(waitShow);
27 |
28 | registerWatchListeners();
29 | listenUICommands();
30 |
31 | isWatchingPagePromise.then(function() {
32 | if (isWatchingPage) {
33 | UIAction('show_not_attached');
34 | } else {
35 | UIAction('show_need_reload');
36 | }
37 | });
38 | });
39 | });
40 |
41 | var port = chrome.runtime.connect({
42 | name: 'DEV_TOOLS'
43 | });
44 |
45 | var requestWatchTab = function(callback, options) {
46 | port.postMessage({
47 | action: 'start_watch_page',
48 | data: {
49 | tabId: chrome.devtools.inspectedWindow.tabId,
50 | attach: options && !!options.attach
51 | }
52 | });
53 |
54 | var waitForWatchStart = function(message, port) {
55 | if (message.action !== 'watch_started') return;
56 |
57 | // here we need reload
58 | // show reload view
59 | port.onMessage.removeListener(waitForWatchStart);
60 | startWaitReloads();
61 |
62 | if (callback) {
63 | callback();
64 | }
65 | };
66 |
67 | port.onMessage.addListener(waitForWatchStart);
68 | },
69 | requestStopWatch = function() {
70 | stopWaitReloads();
71 |
72 | port.postMessage({
73 | action: 'stop_watch_page',
74 | data: {
75 | tabId: chrome.devtools.inspectedWindow.tabId
76 | }
77 | });
78 | },
79 | registerWatchListeners = function() {
80 | console.log('registerWatchListeners');
81 |
82 | if (!watchListenersRegistered) {
83 | port.onMessage.addListener(function(message) {
84 | if (message.action === 'front_end_event') {
85 | handleFrontEndEvent(message.data);
86 | }
87 | });
88 | }
89 |
90 | watchListenersRegistered = true;
91 | },
92 | startWaitReloads = function() {
93 | // request wait reloads
94 | port.onMessage.addListener(onReload);
95 | },
96 | stopWaitReloads = function() {
97 | // request wait reloads
98 | port.onMessage.removeListener(onReload);
99 | },
100 | handleFrontEndEvent = function(message) {
101 | // console.log('handleFrontEndEvent', message);
102 |
103 | UIAction(message.action, message.data);
104 | },
105 | frontEndCommand = function(command) {
106 | chrome.devtools.inspectedWindow.eval(command + '();', {
107 | useContentScriptContext: true
108 | });
109 | },
110 | UIAction = function(action, message) {
111 | if (panelWindow) {
112 | panelWindow.postMessage({
113 | action: action,
114 | message: message
115 | }, '*');
116 | } else {
117 | panelPending.push([action, message]);
118 | }
119 | },
120 | listenUICommands = function() {
121 | if (!panelWindow) return;
122 |
123 | panelWindow.addEventListener('message', function(e) {
124 | var data = e.data;
125 |
126 | // console.log('UI command', data);
127 |
128 | if (data && data.serviceAction &&
129 | serviceActions.hasOwnProperty(data.serviceAction)
130 | ) {
131 | serviceActions[data.serviceAction](data.message);
132 | }
133 | });
134 | },
135 | onReloadHandler = function() {
136 | console.log('on reload handle');
137 | UIAction('show_main');
138 | UIAction('reload');
139 |
140 | // console.log('reload');
141 | },
142 | onReload = function(message, port) {
143 | if (message.action !== 'reload') return;
144 |
145 | onReloadHandler();
146 | };
147 |
148 | var serviceActions = {
149 | attach: function() {
150 | isAttached = true;
151 |
152 | var wasWatched = isWatchingPage;
153 |
154 | requestWatchTab(function() {
155 | if (wasWatched) {
156 | frontEndCommand('attachToBackend');
157 | }
158 | }, {
159 | attach: !isWatchingPage
160 | });
161 |
162 | onReloadHandler();
163 | },
164 | reload_and_attach: function() {
165 | isAttached = true;
166 |
167 | requestWatchTab(function() {
168 | chrome.devtools.inspectedWindow.reload();
169 | });
170 | },
171 | open_resource: function(message) {
172 | if (chrome.devtools.panels.openResource) {
173 | chrome.devtools.panels.openResource(message.file, message.line - 1);
174 | }
175 | },
176 | detach: function() {
177 | console.log('detach');
178 | requestStopWatch();
179 | frontEndCommand('detachFromBackend');
180 | isAttached = false;
181 | }
182 | };
183 |
184 | port.onMessage.addListener(function(message) {
185 | if (message.action !== 'front_end_started') return;
186 |
187 | isWatchingPage = true;
188 | });
189 |
190 | port.postMessage({
191 | action: 'prepare_front_end',
192 | data: {
193 | tabId: chrome.devtools.inspectedWindow.tabId
194 | }
195 | });
196 |
197 | var isWatchingPage,
198 | isAttached,
199 | makeIsFalse = function() {
200 | isWatchingPage = false;
201 | isAttached = false;
202 | };
203 |
204 | var isWatchingPagePromise = new Promise(function(resolve) {
205 | var WAIT_LIMIT = 5000,
206 | currentWait = 0;
207 |
208 | var doEval = function() {
209 | chrome.devtools.inspectedWindow.eval(
210 | '({ isWatchingPage: this.isWatchingPage, isAttached: this.isAttached })', {
211 | useContentScriptContext: true
212 | }, function(result, exception) {
213 | if (exception) {
214 | if (exception.isError && exception.code === 'E_NOTFOUND') {
215 | if (currentWait < 5000) {
216 | currentWait += 100;
217 | setTimeout(doEval, 100);
218 | return;
219 | } else {
220 | makeIsFalse();
221 | }
222 | } else {
223 | makeIsFalse();
224 | }
225 | } else if (result) {
226 | isAttached = result.isAttached;
227 | isWatchingPage = result.isWatchingPage
228 | } else {
229 | makeIsFalse();
230 | }
231 |
232 | console.log('isWatchingPage', isWatchingPage);
233 | console.log('isAttached', isAttached);
234 |
235 | resolve();
236 | }
237 | );
238 | };
239 |
240 | doEval();
241 | });
--------------------------------------------------------------------------------
/shared/promises-backend.js:
--------------------------------------------------------------------------------
1 | console.log('PromisesDebugger inside');
2 |
3 | (function(global) {
4 | "use strict";
5 |
6 | if (global.PromisesDebugger) return;
7 |
8 | var hasOwn = Object.prototype.hasOwnProperty;
9 |
10 | var PromisesDebugger = {
11 | promiseToRecord: new WeakMap(),
12 | nextId: 0,
13 | providers: {},
14 |
15 | get: function(promise) {
16 | return PromisesDebugger.promiseToRecord.get(promise);
17 | },
18 | requestUpdate: function(diffData) {
19 | setTimeout(function() {
20 |
21 | // console.log('requestUpdate');
22 |
23 | window.postMessage({
24 | PromisesDebugger: true,
25 | method: 'requestUpdate',
26 | message: diffData
27 | }, '*');
28 | }, 0);
29 | },
30 | registerProvider: function(name, config) {
31 | var provider = new Provider(name, config);
32 |
33 | PromisesDebugger.providers[name] = provider;
34 |
35 | return provider;
36 | },
37 | reportError: function(provider, error) {
38 | var errValue = error.value;
39 |
40 | if (errValue instanceof Error) {
41 | var value = {
42 | stack: error.value.stack,
43 | message: error.value.message,
44 | name: error.value.name
45 | };
46 | } else {
47 | var value = {
48 | message: errValue + ''
49 | };
50 | }
51 |
52 | setTimeout(function() {
53 | window.postMessage({
54 | PromisesDebugger: true,
55 | method: 'reportError',
56 | message: {
57 | error: {
58 | value: value
59 | },
60 | provider: provider.name
61 | }
62 | }, '*');
63 | }, 0);
64 | }
65 | };
66 |
67 | var Provider = function(name, config) {
68 | this.name = name;
69 | this.config = config;
70 | };
71 |
72 | Provider.prototype = {
73 | get: function(promise) {
74 | return PromisesDebugger.promiseToRecord.get(promise);
75 | },
76 | reportError: function(error) {
77 | PromisesDebugger.reportError(this, error);
78 | },
79 | register: function(promise, params) {
80 | var provider = this;
81 |
82 | var registeredData = {
83 | promise: promise,
84 | setValue: function(val) {
85 | var value = val.value,
86 | sendData = {
87 | id: registeredData.id,
88 | state: val.type
89 | };
90 |
91 | if (value && typeof value === 'object' && !Array.isArray(value)) {
92 | value = value.valueOf();
93 | }
94 |
95 | var isPromise;
96 |
97 | if (provider.isPromise && (isPromise = provider.isPromise(value))) {
98 | var record = provider.get(isPromise);
99 |
100 | sendData.value = {
101 | type: 'promise',
102 | id: record.id
103 | };
104 | } else if (
105 | typeof value === 'string' ||
106 | typeof value === 'number' ||
107 | typeof value === 'boolean'
108 | ) {
109 | // truncate long strings
110 | if (typeof value === 'string' && value.length > 100) {
111 | value = value.slice(0, 100);
112 | }
113 |
114 | sendData.value = {
115 | type: 'primitive',
116 | value: value,
117 | primitive: typeof value
118 | };
119 | } else if (value instanceof Error) {
120 | sendData.value = {
121 | type: 'error',
122 | error: {
123 | stack: value.stack,
124 | message: value.message,
125 | code: value.code
126 | }
127 | };
128 | } else if (Array.isArray(value)) {
129 | sendData.value = {
130 | type: 'array'
131 | };
132 | } else if (value && typeof value === 'object') {
133 | var keys = Object.keys(value),
134 | allKeys = Object.getOwnPropertyNames(value),
135 | objStr = value + '',
136 | objName = objStr.match(/^\[object (\w+?)\]$/);
137 |
138 | objName = objName ? objName[1] : objStr;
139 |
140 | if (keys && (keys.length || allKeys.length)) {
141 | sendData.value = {
142 | type: 'keys',
143 | keys: keys,
144 | allKeys: allKeys
145 | };
146 | } else {
147 | sendData.value = {
148 | type: 'object',
149 | object: value + ''
150 | };
151 | }
152 | } else if (typeof value === 'function') {
153 | var strVal = value + '',
154 | nameEnd = strVal.indexOf(')'),
155 | isNative = strVal.indexOf('[native code]') !== -1;
156 |
157 | sendData.value = {
158 | type: 'function',
159 | function: isNative ? strVal : strVal.slice(0, nameEnd + 1)
160 | };
161 | } else {
162 | // console.log('value unknown:', value);
163 | sendData.value = {
164 | type: 'unknown',
165 | typeOf: typeof value
166 | };
167 | }
168 |
169 | this.value = value;
170 | this.state = val.type;
171 |
172 | PromisesDebugger.requestUpdate({
173 | event: 'value',
174 | data: sendData
175 | });
176 | },
177 | id: PromisesDebugger.nextId++,
178 | chaining: [],
179 | stack: params && params.stack,
180 | topLevel: params ? params.topLevel !== false : true,
181 | provider: provider.name
182 | },
183 | topLevel = registeredData.topLevel,
184 | parentPromise,
185 | name = params && params.name || '',
186 | caller = params.caller;
187 |
188 | if (topLevel) {
189 |
190 | } else {
191 | params.parent.chaining.push(registeredData);
192 | parentPromise = params.parent.id;
193 | }
194 |
195 | PromisesDebugger.requestUpdate({
196 | event: 'create',
197 | data: {
198 | id: registeredData.id,
199 | topLevel: topLevel,
200 | stack: registeredData.stack,
201 | parentPromise: parentPromise,
202 | name: name,
203 | caller: caller
204 | }
205 | });
206 |
207 | if (params && hasOwn.call(params, 'value')) {
208 | registeredData.setValue(params.value);
209 | }
210 |
211 | PromisesDebugger.promiseToRecord.set(promise, registeredData);
212 | promise.__recordData__ = registeredData;
213 |
214 | return registeredData;
215 | },
216 | };
217 |
218 | PromisesDebugger.Provider = Provider;
219 |
220 | window.PromisesDebugger = PromisesDebugger;
221 | }(this));
--------------------------------------------------------------------------------
/shared/fw/cui/modules/events.js:
--------------------------------------------------------------------------------
1 | var lib = require('lib'),
2 | libEvents = lib.events,
3 | slice = Array.prototype.slice,
4 | isArray = Array.isArray,
5 | hasOwn = Object.prototype.hasOwnProperty,
6 | defaultOptions = {};
7 |
8 | var EVENTS_TARGET_KEY = 'events_node_target',
9 | EVENTS_NAMESPACE = 'mod_events',
10 | EVENTS_CACHE_KEY = 'events_center',
11 | EVENT_TARGET_TAG = 'event-target',
12 | EVENTS_SC_GROUP_HANDLERS = 'events_sc_group_handlers';
13 |
14 | var EventsCenter = function(node, options) {
15 | if (!node) return null;
16 |
17 | if (!node.addEventListener) {
18 | var cache = lib.cache(node);
19 |
20 | if (!(node = cache[EVENTS_TARGET_KEY])) {
21 | node = cache[EVENTS_TARGET_KEY] = document.createElement(EVENT_TARGET_TAG);
22 | }
23 | }
24 |
25 | options || (options = defaultOptions);
26 |
27 | this.eventLast = options.eventLast;
28 | this.eventForward = !options.noEventForward;
29 | this.queued = options.eventsQueue;
30 | this.node = node;
31 | };
32 |
33 | EventsCenter.init = function(node, options) {
34 | var cache = lib.cache(node),
35 | center = cache[EVENTS_CACHE_KEY];
36 |
37 | if (!center) {
38 | center = cache[EVENTS_CACHE_KEY] = new EventsCenter(node, options);
39 | }
40 |
41 | return center;
42 | };
43 |
44 | EventsCenter.addMethod = function(name, method) {
45 | EventsCenter.prototype[name] = function selfMethod(arg) {
46 | if (!arg) return this;
47 |
48 | if (typeof arg === 'object' && !isArray(arg)) {
49 | return selfMethod.apply(EventsCenter.init(arg), slice.call(arguments, 1));
50 | }
51 |
52 | if (typeof arg === 'string') {
53 | arg = arg.split(' ');
54 | if (arg.length === 1) {
55 | arg = arg[0];
56 | }
57 | }
58 |
59 | if (isArray(arg)) {
60 | var args = slice.call(arguments, 1);
61 | arg.forEach(function(arg) {
62 | method.apply(this, [arg].concat(args));
63 | }, this);
64 |
65 | return this;
66 | }
67 |
68 | return method.apply(this, arguments);
69 | };
70 | };
71 |
72 | EventsCenter.prototype = {
73 | all: function(nodes, event, callback, capture) {
74 | var len = nodes.length,
75 | node;
76 |
77 | for (var i = len; i--;) {
78 | (node = nodes[i]) && this.once(node, event, function() {
79 | if (!--len) {
80 | callback();
81 | }
82 | }, capture);
83 | }
84 | },
85 | group: function(nodes, event, callback, capture) {
86 | for (var i = nodes.length; i--;) {
87 | nodes[i] && this.on(nodes[i], event, callback, capture);
88 | }
89 | },
90 | proxy: function(what, who, params) {
91 | if (!isArray(what) || !isArray(who)) return this;
92 | var self = this;
93 |
94 | this.on(what[0], what[1], function(e, data) {
95 | self.fire(who[0], who[1], data, params);
96 | });
97 | },
98 | clean: function(node) {
99 | var cache = lib.cache(node),
100 | center = cache[EVENTS_CACHE_KEY];
101 |
102 | libEvents.clean(node, EVENTS_NAMESPACE);
103 | cache[EVENTS_CACHE_KEY] = null;
104 | cache[EVENTS_TARGET_KEY] = null;
105 | if (center) {
106 | center.node = null;
107 | }
108 | }
109 | };
110 |
111 | lib.each({
112 | action: function(event, callback, useCaptures) {
113 | var eventForward = this.eventForward,
114 | eventLast = this.eventLast,
115 | node = this.node,
116 | self = this;
117 |
118 | libEvents.add(node, event, {
119 | handler: function(e) {
120 | var args = e.detail || [],
121 | actionsDesc = args.length ? args[0] : null,
122 | actions = actionsDesc && actionsDesc.actions,
123 | actionKeys = actions && Object.keys(actions),
124 | actionEnd = actionsDesc && actionsDesc.end,
125 | actionCalled;
126 |
127 | if (actionKeys) {
128 | var newActions = {};
129 |
130 | actionKeys.forEach(function(key) {
131 | var action = actions[key];
132 |
133 | newActions[key] = function() {
134 | actionCalled = true;
135 | e.stopImmediatePropagation();
136 | return action.apply(this, arguments);
137 | };
138 | });
139 |
140 | actions = newActions;
141 | newActions = null;
142 | }
143 |
144 | args = [actionsDesc && actionsDesc.data, actions];
145 |
146 | if (eventForward) {
147 | args = self.eventLast ? (args.push(e), args) : [e].concat(args);
148 | }
149 |
150 | if (callback.apply(node, args) === false) {
151 | e.stopPropagation();
152 | e.preventDefault();
153 | }
154 |
155 | if (actionKeys) {
156 | actionKeys.forEach(function() {
157 | actions[key] = null;
158 | });
159 |
160 | /*actionsDesc.actions = */actions = null;
161 | }
162 |
163 | if (!actionCalled && typeof actionEnd === 'function') {
164 | actionEnd();
165 | }
166 |
167 | actionEnd = null;
168 | },
169 | callback: callback,
170 | capture: !!useCapture,
171 | namespace: EVENTS_NAMESPACE
172 | });
173 | },
174 | on: function(event, callback, useCapture) {
175 | var eventForward = this.eventForward,
176 | eventLast = this.eventLast,
177 | node = this.node,
178 | self = this;
179 |
180 | if (event == null) {
181 | // console.warn('Attempt to listen undefined event');
182 | throw new Error('Attempt to listen undefined event');
183 | }
184 |
185 | libEvents.add(node, event, {
186 | handler: function(e) {
187 | var args = e.detail || [];
188 |
189 | if (eventForward) {
190 | args = self.eventLast ? (args.push(e), args) : [e].concat(args);
191 | }
192 |
193 | if (callback.apply(node, args) === false) {
194 | e.stopPropagation();
195 | e.preventDefault();
196 | }
197 | },
198 | callback: callback,
199 | capture: !!useCapture,
200 | namespace: EVENTS_NAMESPACE
201 | });
202 |
203 | return this;
204 | },
205 | remove: function(event, callback, useCapture) {
206 | if (event == null) {
207 | // console.warn('Attempt to remove undefined event');
208 | throw new Error('Attempt to remove undefined event');
209 | }
210 |
211 | if (typeof callback !== 'function') {
212 | if (typeof callback === 'boolean') {
213 | useCapture = callback;
214 | }
215 |
216 | var node = this.node;
217 |
218 | libEvents.removeAll(node, event, {
219 | capture: !!useCapture,
220 | namespace: EVENTS_NAMESPACE
221 | });
222 |
223 | return this;
224 | }
225 |
226 | var node = this.node;
227 |
228 | libEvents.remove(node, event, {
229 | callback: callback,
230 | capture: !!useCapture,
231 | namespace: EVENTS_NAMESPACE
232 | });
233 |
234 | return this;
235 | },
236 | fire: function(event) {
237 | var node = this.node;
238 |
239 | if (event == null) {
240 | // console.warn('Attempt to fire undefined event');
241 | throw new Error('Attempt to fire undefined event');
242 | }
243 |
244 | libEvents.dispatch(node, event, {
245 | options: {
246 | bubbles: false,
247 | cancelable: true,
248 | detail: slice.call(arguments, 1)
249 | },
250 | type: 'CustomEvent'
251 | });
252 |
253 | return this;
254 | },
255 | dispatch: function(event) {
256 | var node = this.node;
257 |
258 | if (event == null) {
259 | // console.warn('Attempt to dispatch undefined event');
260 | throw new Error('Attempt to dispatch undefined event');
261 | }
262 |
263 | libEvents.dispatch(node, event, {
264 | options: {
265 | bubbles: true,
266 | cancelable: true,
267 | detail: slice.call(arguments, 1)
268 | },
269 | type: 'CustomEvent'
270 | });
271 |
272 | return this;
273 | },
274 | once: function(event, callback) {
275 | var self = this,
276 | node = this.node,
277 | autoRemove = function() {
278 | callback.apply(this, arguments);
279 | self.remove(node, event, autoRemove);
280 | };
281 |
282 | return this.on(event, autoRemove);
283 | },
284 | delegate: function(event, selector, callback) {
285 | var eventForward = this.eventForward,
286 | node = this.node;
287 |
288 | libEvents.add(node, event, {
289 | handler: function(e) {
290 | var target = e.target;
291 |
292 | do {
293 | if (target.matches(selector)) {
294 | var args = e.detail || [],
295 | control = target.uiControl;
296 |
297 | if (!control) {
298 | break;
299 | }
300 |
301 | if (eventForward) {
302 | args = [e, control].concat(args);
303 | }
304 |
305 | if (callback.apply(node, args) === false) {
306 | e.stopPropagation();
307 | e.preventDefault();
308 | }
309 |
310 | break;
311 | }
312 | } while (target !== this && (target = target.parentNode) &&
313 | target.nodeType !== Node.DOCUMENT_NODE);
314 | },
315 | callback: callback,
316 | capture: false,
317 | namespace: EVENTS_NAMESPACE
318 | });
319 |
320 | return this;
321 | },
322 | expr: function(event, fn) {
323 | var self = this,
324 | node = this.node;
325 |
326 | this.on(node, event, function exprHandler() {
327 | if (fn.apply(this, arguments)) {
328 | self.remove(event, exprHandler);
329 | }
330 | });
331 | }
332 | }, function(method, name) {
333 | EventsCenter.addMethod(name, method);
334 | });
335 |
336 | var events = new EventsCenter(
337 | document.createElement(EVENT_TARGET_TAG), {
338 | noEventForward: true
339 | }
340 | );
341 |
342 | events.EventsCenter = EventsCenter;
343 |
344 | events.getMap = function(mod, list) {
345 | return list.reduce(function(map, event) {
346 | map[event] = event + '.' + mod;
347 |
348 | return map;
349 | }, {})
350 | };
351 |
352 | events.wrap = function(node, options) {
353 | return EventsCenter.init(node, options);
354 | };
355 |
356 | var exports = events;
357 |
358 | if (modules && modules.globalRequire) {
359 | modules.globalRequire[module.name] = module.name;
360 | }
--------------------------------------------------------------------------------
/firefox/lib/runtime.js:
--------------------------------------------------------------------------------
1 | const { Cc, Ci, Cu, Cr } = require("chrome");
2 | const self = require("sdk/self");
3 |
4 | const { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
5 | const { DevToolsUtils } = Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm", {});
6 | const devtools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
7 |
8 | const events = require("sdk/event/core");
9 | const { on, once, off, emit } = events;
10 | const { setTimeout, clearTimeout } = require('sdk/timers');
11 |
12 | const { TargetLogger } = require('lib/target-logger.js');
13 | const prefs = new (require('shared/prefs.js').Prefs);
14 | const backend = require('shared/backend.js');
15 | const ext = require('shared/ext.js');
16 |
17 | prefs.ready.then(function() {
18 | console.log(prefs.getAll());
19 | });
20 |
21 | console.log('Start');
22 |
23 | var getDesc = Object.getOwnPropertyDescriptor;
24 |
25 | var log = {
26 | prefix: '[PromisesDebugger]:',
27 | warn: function(...args) {
28 | args.unshift(this.prefix);
29 | console.warn(...args);
30 | }
31 | };
32 |
33 | var buildProgressQI = function(obj) {
34 | obj.QueryInterface = function(aIID) {
35 | if (
36 | aIID.equals(Ci.nsIWebProgressListener) ||
37 | aIID.equals(Ci.nsISupportsWeakReference) ||
38 | aIID.equals(Ci.nsIXULBrowserWindow) ||
39 | aIID.equals(Ci.nsISupports)
40 | ) {
41 | return this;
42 | }
43 |
44 | throw Cr.NS_NOINTERFACE;
45 | }
46 |
47 | return obj;
48 | };
49 |
50 | var buildProgressListener = function(obj, methods) {
51 | var listener = buildProgressQI({});
52 |
53 | Object.keys(methods).forEach((key) => {
54 | listener[key] = methods[key].bind(obj);
55 | });
56 |
57 | return listener;
58 | };
59 |
60 | let promisesBackendCode = backend.getCode();
61 |
62 | var PromisesPanel = function(window, toolbox) {
63 | this.toolbox = toolbox;
64 | this.panelWindow = window;
65 | this.target = toolbox.target;
66 | this.webProgress = this.target.tab.linkedBrowser.webProgress;
67 | // this.inspectedWindow = this.webProgress.DOMWindow;
68 |
69 |
70 | this.waitUICommands();
71 |
72 | if (this.isDebuggerAttached()) {
73 | this.UIAction('show_not_attached');
74 | } else {
75 | this.waitAttachRequest();
76 | }
77 |
78 | this.toolbox.loadTool('jsdebugger').then((Debugger) => {
79 | let DebuggerController = Debugger._controller;
80 | let SourceScripts = DebuggerController.SourceScripts;
81 |
82 | SourceScripts.debuggerClient.addListener("newSource", function(e, data) {
83 | let source = data.source;
84 |
85 | if (
86 | source.addonPath &&
87 | source.addonPath.indexOf('promises-debugger-extension') !== -1
88 | ) {
89 | let panelWin = Debugger.panelWin;
90 | let onPaused = () => {
91 | panelWin.off(panelWin.EVENTS.SOURCE_SHOWN, onPaused);
92 |
93 | setTimeout(function() {
94 | SourceScripts.setBlackBoxing(source, true);
95 | }, 100);
96 | };
97 |
98 | panelWin.on(panelWin.EVENTS.SOURCE_SHOWN, onPaused);
99 | }
100 | });
101 | });
102 |
103 | this.logger = this.toolbox.loadTool('webconsole').then(WebConsolePanel => {
104 | let ui = WebConsolePanel.hud.ui;
105 | return new TargetLogger(ui);
106 | });
107 | };
108 |
109 | PromisesPanel.prototype = {
110 | get inspectedWindow() {
111 | return this.webProgress.DOMWindow;
112 | },
113 | isDebuggerAttached: function() {
114 | return !!this.inspectedWindow.__PromisesDebuggerAttached__;
115 | },
116 | attachToTarget: function() {
117 | if (this.isDebuggerAttached()) return;
118 |
119 | var inspectedWindow = this.inspectedWindow;
120 |
121 | inspectedWindow.__PromisesDebuggerAttached__ = true;
122 |
123 | // here promisesBackendCode must be present
124 | // if it's possible need to 'then' promise and add
125 | // destroy handle to toolbox
126 | if (!promisesBackendCode) {
127 | log.warn(' is not present');
128 | return;
129 | }
130 |
131 | if (this.target.isLocalTab) {
132 | inspectedWindow.eval(promisesBackendCode);
133 | } else {
134 | this.attachToRemote(promisesBackendCode);
135 | }
136 | },
137 | attachToRemote: function(promisesBackendCode) {
138 | this.toolbox.loadTool('jsdebugger').then((Debugger) => {
139 | var DebuggerController = Debugger._controller;
140 |
141 | var doEval = () => {
142 | this.toolbox.loadTool('webconsole').then(function(WebConsole) {
143 | WebConsole.hud.jsterm.requestEvaluation(promisesBackendCode).then(function() {
144 | console.log('zzz', arguments);
145 | DebuggerController.activeThread.resume(function() {
146 | console.log('resume', arguments);
147 | });
148 | }, function() {
149 | console.log('xxx', arguments);
150 | });
151 | });
152 | };
153 |
154 | if (DebuggerController.activeThread.state === 'paused') {
155 | doEval();
156 | } else {
157 | DebuggerController.activeThread.interrupt(function(res) {
158 | console.log('interrupt:', res);
159 |
160 | doEval()
161 | });
162 | }
163 | });
164 | },
165 | startWaitReloads: function() {
166 | if (!this.target.isLocalTab) {
167 | this.target.on('will-navigate', () => {
168 | this.onReload();
169 | });
170 |
171 | return;
172 | }
173 |
174 | let webProgress = this.webProgress;
175 |
176 | // not really need buildListener with arrow functions
177 | this.progressListener = buildProgressListener(this, {
178 | onLocationChange: (aWebProgress, aRequest, aLocationURI, aFlags) => {
179 | if (aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT |
180 | aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) {
181 | return;
182 | }
183 |
184 | this.onReload()
185 | }
186 | });
187 |
188 | webProgress.addProgressListener(
189 | this.progressListener,
190 | webProgress.NOTIFY_STATE_WINDOW | webProgress.NOTIFY_LOCATION
191 | );
192 | },
193 | stopWaitReloads: function() {
194 | let webProgress = this.webProgress;
195 |
196 | if (this.progressListener) {
197 | webProgress.removeProgressListener(this.progressListener);
198 | this.progressListener = null;
199 | }
200 | },
201 | startWatchBackend: function() {
202 | this.backendWatchListener = (e) => {
203 | var data = e.data;
204 |
205 | if (!data || !data.PromisesDebugger) return;
206 |
207 | if (data.method === 'requestUpdate') {
208 | // console.log('PromisesDebugger:UpdateData');
209 |
210 | this.UIAction('update_data', data.message);
211 | } else if (data.method === 'reportError') {
212 | this.reportError(data.message);
213 | }
214 | };
215 |
216 | this.inspectedWindow.addEventListener('message', this.backendWatchListener);
217 | },
218 | stopWatchBackend: function() {
219 | this.inspectedWindow.removeEventListener('message', this.backendWatchListener);
220 | },
221 | UIAction: function(action, message) {
222 | this.panelWindow.postMessage({
223 | action: action,
224 | message: message
225 | }, '*');
226 | },
227 | waitAttachRequest: function() {
228 | // XXX change to show_need_attach
229 | this.UIAction('show_need_reload');
230 | },
231 | waitUICommands: function() {
232 | var serviceActions = {
233 | attach: () => {
234 | this.startWaitReloads();
235 |
236 | this.onReload();
237 | },
238 | reload_and_attach: () => {
239 | this.startWaitReloads();
240 |
241 | this.inspectedWindow.location.reload();
242 | },
243 | open_resource: (message) => {
244 | var toolbox = this.toolbox;
245 | const WAIT_LIMIT = 5000;
246 |
247 | toolbox.selectTool('jsdebugger').then(function(Debugger) {
248 | let perform = () => {
249 | let DebuggerView = Debugger._view;
250 | let waiting = 0;
251 |
252 | if (DebuggerView.Sources.containsValue(message.file)) {
253 | DebuggerView.setEditorLocation(message.file, +message.line, {
254 | align: 'center',
255 | charOffset: +message.col
256 | });
257 | } else if (waiting < WAIT_LIMIT) {
258 | waiting += 70;
259 | setTimeout(perform, 70);
260 | }
261 | };
262 |
263 | if (Debugger.isReady) {
264 | perform();
265 | } else {
266 | toolbox.on('jsdebugger-ready', perform);
267 | }
268 | });
269 | },
270 | detach: () => {
271 | this.stopWaitReloads();
272 | this.stopWatchBackend();
273 | }
274 | };
275 |
276 | this.panelWindow.addEventListener('message', function(e) {
277 | var data = e.data;
278 |
279 | // console.log('got service action', data);
280 |
281 | if (data && data.serviceAction &&
282 | serviceActions.hasOwnProperty(data.serviceAction)
283 | ) {
284 | serviceActions[data.serviceAction](data.message);
285 | }
286 | });
287 | },
288 | reportError: function(data) {
289 | this.logger.then((logger) => {
290 | logger.promiseError(data);
291 | });
292 | },
293 |
294 | onReload: function() {
295 | this.UIAction('show_main');
296 | this.UIAction('reload');
297 |
298 | this.attachToTarget();
299 | this.startWatchBackend();
300 | },
301 |
302 | get target() {
303 | return this.toolbox.target;
304 | },
305 | destroy: function() {
306 | this.stopWaitReloads();
307 | this.stopWatchBackend();
308 | }
309 | };
310 |
311 | /*gDevTools.on('promises-destroy', function() {
312 | console.log('promises-destroy');
313 | });*/
314 |
315 | gDevTools.registerTool({
316 | id: 'promises',
317 | url: self.data.url('shared/promises-panel.html'),
318 | label: 'Promises',
319 | tooltip: 'Promises Debugger',
320 | icon: ext.getURL('data/shared/images/promises.png'),
321 | isTargetSupported: target => target.isLocalTab,
322 | build: (window, toolbox) => {
323 | /*toolbox.on('destroy', function() {
324 | console.log('toolbox destroy');
325 | });*/
326 |
327 | return new PromisesPanel(window, toolbox);
328 | }
329 | });
330 |
331 | // DebuggerView.setEditorLocation(where.url, where.line);
332 | // selectFrame: function(aDepth) {
333 | // DebuggerView.updateEditor
334 | // Debugger._view.setEditorLocation();
--------------------------------------------------------------------------------
/shared/fw/cui/modules/utils.js:
--------------------------------------------------------------------------------
1 | var lib = require('lib');
2 |
3 | var selectableEvents = [
4 | 'selectionstart',
5 | 'selectstart',
6 | 'dragstart'
7 | // 'mousedown',
8 | //'touchstart'
9 | ],
10 | focusableEvents = [
11 | 'DOMActivate',
12 | 'activate',
13 | 'beforeactivate',
14 | 'focus',
15 | 'focusin'
16 | ],
17 | defaultSelectOptions = {
18 | preventTab: false,
19 | onlySelf: false,
20 | useCapture: true
21 | };
22 |
23 | var isArray = Array.isArray,
24 | extend = lib.extend,
25 | call = Function.call,
26 | hasOwn = Object.prototype.hasOwnProperty,
27 | hasTouch = 'ontouchstart' in document;
28 |
29 | var R_TYPE_2_CLASS = /(?:\b)(\w)([\w\-]+)(?:\b)/ig,
30 | R_CSS_2_DOM = /-([a-z]|[0-9])/ig,
31 | R_MS_PREFIX = /^-ms-/,
32 | R_CAMEL_2_CSS = /[A-Z](?=\w)/g,
33 | R_URL = /^(?:(http(?:s?)\:)?\/\/([a-zA-Z_\-а-яА-ЯёЁ0-9\.]+))?(\:\d+)?(\/(?:[^?#]*)?)?(\?(?:[^#]*)?)?(#[\S]*)?/g,
34 | UNSELECTABLED_KEY = '_unselectabledObject';
35 |
36 | var toUpperCase = function(str, letter) {
37 | return (letter + '').toUpperCase();
38 | },
39 | type2class = function(str, p1, p2) {
40 | return (p1 + '').toUpperCase() + exports.css2dom(p2);
41 | },
42 | camel2css = function(w) {
43 | return ('-' + w).toLowerCase();
44 | };
45 |
46 | var exports = {
47 | escapeHTML: function escapeHTML(value) {
48 | return value && (value + '')
49 | .replace(/&/gi, '&')
50 | .replace(//gi, '>')
52 | .replace(/"/gi, '"')
53 | .replace(/'/gi, ''')
54 | .replace(/\//gi, '/') || '';
55 | },
56 | makeUnselectable: function(node, options) {
57 | options = extend({}, defaultSelectOptions, options);
58 |
59 | var bindEvents = options.preventTab ?
60 | selectableEvents.concat(focusableEvents) : selectableEvents,
61 | cache = lib.cache(node),
62 | unselectables = cache[UNSELECTABLED_KEY] || (cache[UNSELECTABLED_KEY] = []),
63 | listeners = {},
64 | send = {
65 | options: options,
66 | listeners: listeners
67 | };
68 |
69 | bindEvents.forEach(function(key) {
70 | var listener = function(e) {
71 | var target = e.target;
72 |
73 | if (options.onlySelf && target !== node) return;
74 |
75 | e.preventDefault();
76 | e.stopPropagation();
77 | e.stopImmediatePropagation();
78 |
79 | return false;
80 | };
81 |
82 | events.on(node, key, listener, options.useCapture);
83 | listeners[key] = listener;
84 | });
85 |
86 | events.on(node, 'touchstart', listeners['touchstart'] = function() {}, false);
87 |
88 | node.setAttribute('unselectable', 'on');
89 | node.setAttribute('draggable', 'false');
90 |
91 | if (options.preventTab) {
92 | send.tabIndex = node.tabIndex | 0;
93 | node.tabIndex = -1;
94 | }
95 |
96 | unselectables.push(send);
97 | },
98 | restoreSelectable: function(node) {
99 | var unselectables = lib.cache(node)[UNSELECTABLED_KEY],
100 | send,
101 | options,
102 | useCapture,
103 | listeners;
104 |
105 | if (!unselectables || !unselectables.length) return;
106 |
107 | send = unselectables.pop(),
108 | listeners = send.listeners,
109 | options = send.options,
110 | useCapture = options.useCapture;
111 |
112 | lib.each(listeners, function(val, key) {
113 | events.remove(node, key, val, useCapture);
114 | });
115 |
116 | if (!unselectables.length) {
117 | node.removeAttribute('unselectable');
118 | node.removeAttribute('draggable');
119 | }
120 |
121 | if (options.preventTab) {
122 | var tabIndex = send.tabIndex;
123 | if (isFinite(tabIndex)) {
124 | node.tabIndex = tabIndex;
125 | }
126 | }
127 | },
128 | getBox: function(node, options, params) {
129 | var computed = window.getComputedStyle(node),
130 | data = {},
131 | offset = 0;
132 |
133 | options = {
134 | border: typeof options.border === 'boolean' ? options.border : false,
135 | metric: typeof options.metric === 'boolean' ? options.metric : true,
136 | inner: typeof options.inner === 'boolean' ? options.inner : true,
137 | outer: typeof options.outer === 'boolean' ? options.outer : false
138 | };
139 |
140 | if (options.inner) {
141 | options.border = false;
142 | options.outer = false;
143 | offset = -(parseInt(computed[params.padding[0]]) + parseInt(computed[params.padding[1]]));
144 | }
145 |
146 | if (options.outer) {
147 | offset = parseInt(computed[params.margin[0]]) + parseInt(computed[params.margin[1]]);
148 | }
149 |
150 | return (options.metric ? (options.border ? node[params.metric[0]] : node[params.metric[1]]) : 0) + offset;
151 | },
152 | boxHeight: function(node, options) {
153 | return exports.getBox(node, options, {
154 | margin: ['marginTop', 'marginBottom'],
155 | padding: ['paddingTop', 'paddingBottom'],
156 | metric: ['offsetHeight', 'clientHeight']
157 | });
158 | },
159 | boxWidth: function(node, options) {
160 | return exports.getBox(node, options, {
161 | margin: ['marginLeft', 'marginRight'],
162 | padding: ['paddingLeft', 'paddingRight'],
163 | metric: ['offsetWidth', 'clientWidth']
164 | });
165 | },
166 | css2dom: function(str) {
167 | return str.replace(R_MS_PREFIX, 'ms-').replace(R_CSS_2_DOM, toUpperCase);
168 | },
169 | type2class: function(type) {
170 | return (type || '').replace(R_TYPE_2_CLASS, type2class);
171 | },
172 | camel2css: function(str) {
173 | return str.replace(R_CAMEL_2_CSS, camel2css);
174 | },
175 | checkIntoView: function(node, height) {
176 | var rect = node.nodeType ? rect = node.getBoundingClientRect() : node;
177 | height || (height = window.innerHeight);
178 |
179 | var topHeight = rect.top + rect.height,
180 | isBetween = (rect.top > 0 && topHeight < height),
181 | isAbove = (rect.top < 0 && topHeight < 0 && topHeight < height),
182 | isBelow = (rect.top > 0 && rect.top > height && topHeight > height),
183 | isOutflow = (rect.top < 0 && rect.top + rect.height > height),
184 | singleOutflow = !isBelow && !isAbove && !isBetween && !isOutflow,
185 | isHidden = !rect.width && !rect.height;
186 |
187 | return {
188 | isIntoView: isHidden ? false :
189 | isBetween || (!isAbove && !isBelow) || isOutflow,
190 | isBetween: isBetween,
191 | isAbove: isAbove,
192 | isBelow: isBelow,
193 | isOutflow: isOutflow,
194 | isOutflowBottom: singleOutflow && rect.top > 0,
195 | isOutflowTop: singleOutflow && rect.top < 0,
196 | rect: rect,
197 | topHeight: topHeight,
198 | height: height
199 | };
200 | },
201 | html2fragment: function(string, iterator) {
202 | var div = document.createElement('div'),
203 | child,
204 | iterate = typeof iterator === 'function',
205 | fragment = document.createDocumentFragment();
206 |
207 | div.innerHTML = string;
208 |
209 | while (child = div.firstChild) {
210 | if (!iterate || iterator(child) !== true) {
211 | fragment.appendChild(child);
212 | }
213 | }
214 |
215 | div = null;
216 | return fragment;
217 | },
218 | attr: function(node, attr, value) {
219 | if (!node || !attr) return null;
220 |
221 | if (value !== void 0 || value === null) {
222 | node.setAttribute(attr, value);
223 | return value;
224 | }
225 |
226 | // return node.hasAttribute(attr) ? node.getAttribute(attr) : void 0;
227 | attr = node.getAttribute(attr);
228 | return attr == null ? void 0 : attr;
229 | },
230 | debounce: function(fn, delay, thisArg) {
231 | var timer,
232 | throttle = function() {
233 | if (timer) clearTimeout(timer);
234 | var args = arguments,
235 | _this = thisArg || this;
236 |
237 | timer = setTimeout(function() {
238 | fn.apply(_this || null, args);
239 | }, delay);
240 | };
241 |
242 | throttle.stop = function() {
243 | if (timer) clearTimeout(timer);
244 | };
245 |
246 | return throttle;
247 | },
248 | goLink: function(url, target) {
249 | var go = function() {
250 | try {
251 | window.location.assign(url);
252 | } catch (e) {
253 | window.location.href = url;
254 | }
255 | };
256 |
257 | //if (target && target !== '_self') {
258 | var a = document.createElement('a');
259 |
260 | a.href = url || '';
261 | a.target = target || '';
262 | document.body.appendChild(a);
263 |
264 | //setTimeout(function() {
265 | if (a.click) {
266 | try {
267 | a.click();
268 | } catch (e) {
269 | go();
270 | }
271 |
272 | window.focus();
273 | } else {
274 | go();
275 | }
276 |
277 | setTimeout(function() {
278 | document.body.removeChild(a);
279 | a = null;
280 | }, 1);
281 | //}, 1);
282 | /*} else {
283 | go();
284 | }*/
285 | }
286 | };
287 |
288 | var ParsedURL = function(url) {
289 | url = url.trim();
290 | R_URL.lastIndex = 0;
291 |
292 | var match = R_URL.exec(url);
293 |
294 | if (!match) {
295 | return null;
296 | }
297 |
298 | if (!match[0]) {
299 | match[4] = location.pathname.replace(/(\/)[^\/?#]*?$/, '$1' + url);
300 | }
301 |
302 | var protocol = match[1] || location.protocol,
303 | hostname = match[2] || location.hostname,
304 | port = match[3] || '',
305 | pathname = match[4] || location.pathname,
306 | search = match[5] || '',
307 | hash = match[6] || '',
308 | origin = protocol + '//' + hostname + port;
309 |
310 | this.protocol = protocol,
311 | this.hostname = hostname,
312 | this.host = hostname + port,
313 | this.port = port,
314 | this.pathname = pathname,
315 | this.path = pathname + search,
316 | this.search = search,
317 | this.hash = hash,
318 | this.origin = origin,
319 | this.href = origin + pathname + search + hash;
320 | };
321 |
322 | exports.parseUrl = function(url) {
323 | if (typeof url !== 'string') {
324 | return url instanceof ParsedURL ? url : null
325 | }
326 |
327 | return new ParsedURL(url);
328 | };
329 |
330 | exports.inherits = function(options) {
331 | var handler = options.handler,
332 | parent = options.parent,
333 | proto = options.proto,
334 | meta = options.meta,
335 | mixins = options.mixins,
336 | name = options.name || 'unnamed' + Date.now(),
337 | parentMixins,
338 | handlers,
339 | classProto;
340 |
341 | if (parent) {
342 | classProto = Class.prototype = Object.create(parent.prototype);
343 | parentMixins = parent.__mixins__;
344 | } else {
345 | classProto = Class.prototype;
346 | }
347 |
348 | if (isArray(mixins) && mixins.length) {
349 | mixins = mixins.filter(function(mix) {
350 | if (!mix || parentMixins &&
351 | parentMixins.indexOf(mix) !== -1) return false;
352 |
353 | extend(true, Class, mix);
354 | extend(classProto, mix.prototype);
355 |
356 | return true;
357 | });
358 | }
359 |
360 | handlers = (parent && parent.__handlers__ || []).concat(mixins ? mixins.reduce(function(result, mix) {
361 | return result.concat(mix.__handlers__);
362 | }, []) : []).filter(function(handler, i, arr) {
363 | return arr.indexOf(handler) === i;
364 | });
365 |
366 | handler && handlers.push(handler);
367 |
368 | extend(true, Class, parent, meta);
369 | extend(classProto, proto);
370 |
371 | classProto.constructor = Class;
372 |
373 | if (parent) {
374 | classProto.__super__ = parent;
375 | classProto.__parent__ = parent.prototype;
376 | }
377 |
378 | Class.toString = function() {
379 | return '[User Class ' + name + ']';
380 | };
381 |
382 | classProto.toString = function() {
383 | return '[User Object ' + name + ']';
384 | };
385 |
386 | Class.__name__ = name;
387 | Class.__mixins__ = mixins;
388 | Class.__handlers__ = handlers;
389 |
390 | function Class() {
391 | var self = this;
392 |
393 | if (parent && !(this instanceof parent)) {
394 | self = Object.create(parent.prototype);
395 | }
396 |
397 | for (var i = 0, len = handlers.length, handler; i < len; i++) {
398 | handler = handlers[i];
399 | /*mix && */handler.apply(self, arguments);
400 | }
401 |
402 | return self;
403 | }
404 |
405 | return Class;
406 | };
--------------------------------------------------------------------------------
/shared/fw/cui/modules/basic.js:
--------------------------------------------------------------------------------
1 | var ui = require('ui'),
2 | parser = require('parser'),
3 | utils = require('utils'),
4 | touch = require('touch'),
5 | uiStates = ui.states;
6 |
7 | var exports = {
8 | events: events.getMap(module.name, [
9 | 'deactiveControl'
10 | ])
11 | };
12 |
13 | var statesMap = {
14 | hover: {
15 | allow: ['none', 'active', 'focus'],
16 | from: ['none']
17 | },
18 | active: {
19 | blocks: ['hover'],
20 | from: ['none', 'hover']
21 | },
22 | focus: {
23 | blocks: ['hover', 'active'],
24 | from: ['none', 'hover', 'active']
25 | },
26 | error: {
27 | blocks: ['none', 'hover', 'active', 'focus', 'selected']
28 | },
29 | selected: {
30 | blocks: ['none', 'hover', 'active', 'focus'],
31 | from: ['none', 'hover', 'active', 'focus']
32 | },
33 | loading: {
34 | blocks: ['none', 'hover', 'active', 'focus', 'selected']
35 | },
36 | readonly: {
37 | blocks: ['none', 'hover', 'active', 'focus', 'selected', 'loading', 'error']
38 | },
39 | disabled: {
40 | blocks: ['none', 'hover', 'active', 'focus', 'selected', 'loading', 'error', 'readonly']
41 | }
42 | },
43 | originalStateSet = parser.OriginalElement.properties.state.set;
44 |
45 | ui.define('live-element', {
46 | mixins: ['touch-element'],
47 | handler: function() {
48 | var startValue,
49 | self = this,
50 | view = this.view,
51 | node = this.node,
52 | beforeActive = ui.states.none,
53 | deactiveConst = 'mouseup mousedown',
54 | docDeactiveConst = deactiveConst,
55 | activeConst = 'mousedown';
56 |
57 | if (utils.hasTouch) {
58 | activeConst = 'touchstart';
59 | deactiveConst = 'touchend touchcancel touchleave';
60 | docDeactiveConst = 'touchend touchcancel';
61 | }
62 |
63 | var deactiveHandler = function(e) {
64 | if (!self) return;
65 |
66 | if (self.get('state') === ui.states.active) {console.log('deactive', e.type, e.currentTarget.nodeName);
67 | if (e.currentTarget === document || e.target === view || view.contains(e.target)) {
68 | if (!utils.hasTouch) {
69 | self.set('state', ui.states.none, {
70 | silent: false,
71 | direct: false
72 | });
73 | }
74 |
75 | self.set('state', beforeActive, {
76 | direct: true
77 | });
78 | } else if (beforeActive === ui.states.hover) {
79 | self.set('state', ui.states.none, {
80 | direct: true
81 | });
82 | }
83 |
84 | console.log(self.get('state'), self.view.getAttribute('data-state'));
85 | if (self.get('state') !== self.view.getAttribute('data-state')) {
86 | debugger;
87 | }
88 | }
89 |
90 | events.remove(view, deactiveConst + ' ' + ui.events.destroy, deactiveHandler);
91 | events.remove(document, docDeactiveConst, deactiveHandler);
92 | },
93 | activeHandler = function(e) {
94 | var state = self.get('state');
95 |
96 | if (state !== ui.states.none && state !== ui.states.hover) return;
97 |
98 | console.log('activate');
99 |
100 | beforeActive = state;
101 | self.set('state', ui.states.active, {
102 | direct: true
103 | });
104 |
105 | events.once(document, 'mousedown', function() {
106 | events.on(document, docDeactiveConst, deactiveHandler);
107 | });
108 | events.on(view,
109 | deactiveConst + ' ' + ui.events.destroy, deactiveHandler);
110 | };
111 |
112 | events.on(self, ui.events.destroy, function() {
113 | self = view = node = null;
114 | });
115 |
116 | events.on(view, 'mouseenter mouseleave', function(e) {
117 | var state = self.get('state');
118 |
119 | if (state !== ui.states.none && state !== ui.states.hover) return;
120 |
121 | if (e.type === 'mouseenter') {
122 | state = ui.states.hover;
123 | } else {
124 | state = ui.states.none;
125 | }
126 |
127 | self.set('state', state, {
128 | direct: true
129 | });
130 | });
131 |
132 | events.on(view, activeConst, activeHandler);
133 | events.on(view, exports.events.deactiveControl, deactiveHandler);
134 |
135 | events.on(self, ui.events.changeState, function(e, data) {
136 | if (data.state === ui.states.disabled) {
137 | events.fire(self, ui.events.disabled);
138 | } else if (data.state === ui.states.none && self.get('disabled')) {
139 | events.fire(self, ui.events.enabled);
140 | }
141 | });
142 |
143 | events.on(self, ui.events.disabled, function() {
144 | utils.makeUnselectable(node, {
145 | preventTab: true
146 | });
147 |
148 | self.set('disabled', true);
149 | node.blur();
150 | });
151 |
152 | events.on(self, ui.events.enabled, function() {
153 | utils.restoreSelectable(node);
154 | self.set('disabled', false);
155 | });
156 | },
157 | properties: {
158 | state: {
159 | type: 'string',
160 | set: function(control, name, state, params) {
161 | if (params) {
162 | var direct = params.direct,
163 | silent = params.silent;
164 | }
165 |
166 | var current = control.get(name),
167 | currentMap = statesMap[current],
168 | newMap = statesMap[state];
169 |
170 | if (state === current) {
171 | return state;
172 | }
173 |
174 | if (direct) {
175 | var iter = function(state) {
176 | return uiStates[state] === current;
177 | };
178 |
179 | if ((currentMap && (currentMap = currentMap.blocks) &&
180 | currentMap.some(iter)) ||
181 | (newMap && (newMap = newMap.from) && !newMap.some(iter))) {
182 | return;
183 | }
184 | }
185 |
186 | // console.log('state: ', state === '' ? '(empty)' : state);
187 |
188 | originalStateSet.call(this, control, name, state, {
189 | state: state,
190 | direct: direct,
191 | silent: silent
192 | });
193 |
194 | // control.set(this.type + ':' + name, state);
195 | }
196 | },
197 | disabled: {
198 | type: 'boolean',
199 | set: function(control, name, value) {
200 | control.set('boolean:' + name, value);
201 | control.node.disabled = value;
202 | }
203 | }
204 | }
205 | });
206 |
207 | ui.define('focusable', {
208 | handler: function() {
209 | var self = this,
210 | node = this.node;
211 |
212 | var getValue = function(control) {
213 | return control.get('value');
214 | },
215 | listenInput = function() {
216 | if (getValue(self) !== startValue) {
217 | self.set('state', ui.states.none, {
218 | silent: false,
219 | direct: false
220 | });
221 |
222 | self.set('state', ui.states.focus);
223 |
224 | events.remove(self, ui.events.change, listenInput);
225 | }
226 | };
227 |
228 | events.on(node, 'focus blur', function(e) {
229 | var state = self.get('state');
230 |
231 | if (state === ui.states.error/* ||
232 | state === ui.states.loading ||
233 | state === ui.states.disabled*/) return;
234 |
235 | self.set('state', e.type === 'focus' ? ui.states.focus : ui.states.none, {
236 | direct: true
237 | });
238 | });
239 |
240 | events.on(self, ui.events.changeState, function(e, data) {
241 | if (data.state !== ui.states.error) return;
242 |
243 | events.on(node, 'focus', function() {
244 | startValue = getValue(self);
245 | events.on(self, ui.events.change, listenInput);
246 | });
247 | });
248 | }
249 | });
250 |
251 | /*ui.define('live-element', {
252 | mixins: ['touch-element'],
253 | handler: function() {
254 | var startValue,
255 | self = this,
256 | view = this.view,
257 | node = this.node,
258 | beforeActive = ui.states.none,
259 | deactiveConst = 'mouseup mousedown',
260 | docDeactiveConst = deactiveConst,
261 | activeConst = 'mousedown';
262 |
263 | if (utils.hasTouch) {
264 | activeConst = 'touchstart';
265 | deactiveConst = 'touchend touchcancel touchleave';
266 | docDeactiveConst = 'touchend touchcancel';
267 | }
268 |
269 | var deactiveHandler = function(e) {
270 | if (!self) return;
271 |
272 | if (self.get('state') === ui.states.active) {console.log('deactive', e.type, e.currentTarget.nodeName);
273 | if (e.currentTarget === document || e.target === view || view.contains(e.target)) {
274 | if (!utils.hasTouch) {
275 | self.set('state', ui.states.none, {
276 | silent: false,
277 | direct: false
278 | });
279 | }
280 |
281 | self.set('state', beforeActive, {
282 | direct: true
283 | });
284 | } else if (beforeActive === ui.states.hover) {
285 | self.set('state', ui.states.none, {
286 | direct: true
287 | });
288 | }
289 |
290 | console.log(self.get('state'), self.view.getAttribute('data-state'));
291 | if (self.get('state') !== self.view.getAttribute('data-state')) {
292 | debugger;
293 | }
294 | }
295 |
296 | events.remove(view, deactiveConst + ' ' + ui.events.destroy, deactiveHandler);
297 | events.remove(document, docDeactiveConst, deactiveHandler);
298 | },
299 | activeHandler = function(e) {
300 | var state = self.get('state');
301 |
302 | if (state !== ui.states.none && state !== ui.states.hover) return;
303 |
304 | console.log('activate');
305 |
306 | beforeActive = state;
307 | self.set('state', ui.states.active, {
308 | direct: true
309 | });
310 |
311 | events.once(document, 'mousedown', function() {
312 | events.on(document, docDeactiveConst, deactiveHandler);
313 | });
314 | events.on(view,
315 | deactiveConst + ' ' + ui.events.destroy, deactiveHandler);
316 | };
317 |
318 | events.on(self, ui.events.destroy, function() {
319 | self = view = node = null;
320 | });
321 |
322 | events.on(view, 'mouseenter mouseleave', function(e) {
323 | var state = self.get('state');
324 |
325 | if (state !== ui.states.none && state !== ui.states.hover) return;
326 |
327 | if (e.type === 'mouseenter') {
328 | state = ui.states.hover;
329 | } else {
330 | state = ui.states.none;
331 | }
332 |
333 | self.set('state', state, {
334 | direct: true
335 | });
336 | });
337 |
338 | events.on(view, activeConst, activeHandler);
339 | events.on(view, exports.events.deactiveControl, deactiveHandler);
340 |
341 | events.on(self, ui.events.changeState, function(e, data) {
342 | if (data.state === ui.states.disabled) {
343 | events.fire(self, ui.events.disabled);
344 | } else if (data.state === ui.states.none && self.get('disabled')) {
345 | events.fire(self, ui.events.enabled);
346 | }
347 | });
348 | },
349 | properties: {
350 | state: {
351 | type: 'string',
352 | set: function(control, name, state, params) {
353 | if (params) {
354 | var direct = params.direct,
355 | silent = params.silent;
356 | }
357 |
358 | var current = control.get(name),
359 | currentMap = statesMap[current],
360 | newMap = statesMap[state];
361 |
362 | if (state === current) {
363 | return state;
364 | }
365 |
366 | if (direct) {
367 | var iter = function(state) {
368 | return uiStates[state] === current;
369 | };
370 |
371 | if (
372 | (currentMap && (currentMap = currentMap.blocks) && currentMap.some(iter)) ||
373 | (newMap && (newMap = newMap.from) && !newMap.some(iter))
374 | ) {
375 | return;
376 | }
377 | }
378 |
379 | // console.log('state: ', state === '' ? '(empty)' : state);
380 |
381 | originalStateSet.call(this, control, name, state, {
382 | state: state,
383 | direct: direct,
384 | silent: silent
385 | });
386 |
387 | // control.set(this.type + ':' + name, state);
388 | }
389 | }
390 | }
391 | });*/
392 |
393 | /*utils.boxWidth(node, {
394 | inner: true
395 | });*/
--------------------------------------------------------------------------------
/shared/providers/es6.js:
--------------------------------------------------------------------------------
1 | if (!global.Promise) return false;
2 |
3 | var isChrome = typeof chrome !== 'undefined';
4 |
5 | var getDesc = Object.getOwnPropertyDescriptor,
6 | hasOwn = Object.prototype.hasOwnProperty,
7 | recurciveGetDesc = function(object, prop) {
8 | do {
9 | var result = getDesc(object, prop);
10 | } while (!result && (object = Object.getPrototypeOf(object)));
11 |
12 | return result;
13 | };
14 |
15 | var promiseByProxy = new WeakMap(),
16 | provider = PromisesDebugger.registerProvider('es6', {});
17 |
18 | var promiseDesc = recurciveGetDesc(global, 'Promise'),
19 | originalPromise = global.Promise,
20 | originalPromiseResolve = recurciveGetDesc(originalPromise, 'resolve'),
21 | originalPromiseReject = recurciveGetDesc(originalPromise, 'reject'),
22 | originalPromiseAll = recurciveGetDesc(originalPromise, 'all'),
23 | originalPromiseRace = recurciveGetDesc(originalPromise, 'race'),
24 | PromiseForInstanceCheck;
25 |
26 | if (!global.Proxy) {
27 | var PromiseProxy = (function() {
28 | var PromiseConstructor;
29 | var PromiseProxy = function(target, params) {
30 | if (typeof target === 'function') {
31 | return (PromiseConstructor = ProxyPromiseConstructor(target, params));
32 | } else if (target instanceof originalPromise) {
33 | return ProxyPromiseInstance(target, params);
34 | }
35 | };
36 |
37 | var ProxyPromiseInstance = function(target, params) {
38 | // target is instance of Promise
39 |
40 | var proxy = Object.create(PromiseConstructor.prototype);
41 | // target.proxyInstance = proxy;
42 | proxy.promise = target;
43 |
44 | if (params.get) {
45 | var thenDesc = recurciveGetDesc(target, 'then'),
46 | catchDesc = recurciveGetDesc(target, 'catch');
47 |
48 | Object.defineProperties(proxy, {
49 | then: {
50 | enumerable: thenDesc.enumerable,
51 | configurable: thenDesc.configurable,
52 | get: function() {
53 | return params.get(target, 'then')
54 | }
55 | },
56 | catch: {
57 | enumerable: catchDesc.enumerable,
58 | configurable: catchDesc.configurable,
59 | get: function() {
60 | return params.get(target, 'catch')
61 | }
62 | }
63 | });
64 | }
65 |
66 | return proxy;
67 | };
68 |
69 | var ProxyPromiseConstructor = function(target, params) {
70 | if (params.construct) {
71 | // This is proxy constructor
72 | var proxy = function PromiseProxy(executor) {
73 | var proxyInstance = params.construct(target, arguments);
74 |
75 | if (proxyInstance.promise) {
76 | this.promise = proxyInstance.promise;
77 | }
78 |
79 | return proxyInstance;
80 | };
81 | } else {
82 | var proxy = function() {};
83 | }
84 |
85 | if (params.get) {
86 | var PromiseConstructorPropGetter = function(prop) {
87 | var desc = recurciveGetDesc(target, prop);
88 |
89 | return {
90 | get: function() {
91 | return params.get(target, prop, target);
92 | },
93 | configurable: desc.configurable,
94 | enumerable: desc.enumerable
95 | };
96 | };
97 |
98 | Object.defineProperties(proxy, {
99 | resolve: PromiseConstructorPropGetter('resolve'),
100 | reject: PromiseConstructorPropGetter('reject'),
101 | all: PromiseConstructorPropGetter('all'),
102 | race: PromiseConstructorPropGetter('race')
103 | });
104 | }
105 |
106 | return proxy;
107 | };
108 |
109 | return PromiseProxy;
110 | }());
111 | }
112 |
113 | var makeProxy = function(target, params) {
114 | if (global.Proxy) {
115 | return new Proxy(target, params);
116 | } else {
117 | return PromiseProxy(target, params);
118 | }
119 | };
120 |
121 | var promiseWrap = function(promise, registeredData) {
122 | var doThen = function(onResolve, onReject, caller) {
123 | var resolve = function(val) {
124 | chaingRegistered.setValue({
125 | type: 'value',
126 | value: val
127 | });
128 |
129 | return val;
130 | },
131 | reject = function(val) {
132 | chaingRegistered.setValue({
133 | type: 'error',
134 | value: val
135 | });
136 |
137 | provider.reportError({
138 | value: val
139 | });
140 |
141 | return val;
142 | };
143 |
144 | if (onResolve == null) {
145 | onResolve = function() {};
146 | } else if (typeof onResolve !== 'function' && false) {
147 | throw new TypeError('...');
148 | }
149 |
150 | if (onReject == null) {
151 | onReject = function() {};
152 | } else if (typeof onReject !== 'function' && false) {
153 | throw new TypeError('...');
154 | }
155 |
156 | function onResolveWrap(val) {
157 | if (isChrome) {
158 | var ret = new originalPromise(function(retResolve, DONT_USE) {
159 | setTimeout(function() {
160 | ret.then(function(a) {
161 | resolve(a);
162 | }, function(b) {
163 | reject(b);
164 | });
165 | }, 0);
166 |
167 | var retVal = onResolve.call(promise, val);
168 |
169 | retResolve(retVal);
170 | });
171 |
172 | return ret;
173 | }
174 |
175 | var retVal = onResolve.call(promise, val);
176 |
177 | // resolve(retVal);
178 | return retVal;
179 | }
180 |
181 | function onRejectWrap(val) {
182 | if (isChrome) {
183 | var ret = new originalPromise(function(retResolve, DONT_USE) {
184 | setTimeout(function() {
185 | ret.then(function(a) {
186 | resolve(a);
187 | }, function(b) {
188 | reject(b);
189 | });
190 | }, 0);
191 |
192 | var retVal = onReject.call(promise, val);
193 |
194 | retResolve(retVal);
195 | });
196 |
197 | return ret;
198 | }
199 |
200 | var val = onReject.call(promise, val);
201 | // reject(val);
202 | return val;
203 | }
204 |
205 | var result = promise.then(onResolveWrap, onRejectWrap);
206 |
207 | try {
208 | throw new Error();
209 | } catch (e) {
210 | var stack = e.stack;
211 | }
212 |
213 | if (!isChrome) {
214 | result.then(resolve, reject);
215 | }
216 |
217 | caller = 'Promise.' + caller + '()';
218 |
219 | var chaingRegistered = provider.register(result, {
220 | topLevel: false,
221 | stack: stack,
222 | parent: registeredData,
223 | caller: caller
224 | });
225 |
226 | return promiseWrap(result, chaingRegistered);
227 | },
228 | thenWrap = function(onResolve, onReject) {
229 | return doThen.call(this, onResolve, onReject, 'then');
230 | },
231 | catchWrap = function(onReject) {
232 | return doThen.call(this, null, onReject, 'catch');
233 | };
234 |
235 | var proxy = makeProxy(promise, {
236 | get: function(target, name) {
237 | if (name === 'then') return thenWrap;
238 | if (name === 'catch') return catchWrap;
239 |
240 | return target[name];
241 | }
242 | });
243 |
244 | promiseByProxy.set(proxy, promise);
245 |
246 | return proxy;
247 | };
248 |
249 | Object.defineProperty(global, 'Promise', {
250 | value: PromiseForInstanceCheck = makeProxy(originalPromise, {
251 | construct: function(Promise, args) {
252 | var executor = args[0],
253 | registerValue,
254 | name = executor.name;
255 |
256 | if (typeof executor !== 'function') throw new TypeError('...');
257 |
258 | var promise = new Promise(function(resolve, reject) {
259 | var result = executor.call(this, function resolveWrap(val) {
260 | /*var value = {
261 | type: 'value',
262 | value: val
263 | };
264 |
265 | if (registeredData) {
266 | registeredData.setValue(value);
267 | } else {
268 | registerValue = value;
269 | }*/
270 |
271 | if (registerValue) return;
272 |
273 | return resolve.call(this, val);
274 | }, function rejectWrap(val) {
275 | /*var value = {
276 | type: 'error',
277 | value: val
278 | };
279 |
280 | if (registeredData) {
281 | registeredData.setValue(value);
282 | } else {
283 | registerValue = value;
284 | }*/
285 |
286 | if (registerValue) return;
287 |
288 | return reject.call(this, val);
289 | });
290 |
291 | return result;
292 | });
293 |
294 | try {
295 | throw new Error();
296 | } catch (e) {
297 | var stack = e.stack;
298 | }
299 |
300 | var caller = 'new Promise()';
301 |
302 | var registeredData = provider.register(promise, {
303 | stack: stack,
304 | caller: caller,
305 | name: name
306 | });
307 |
308 | promise.then(function(val) {
309 | var value = {
310 | type: 'value',
311 | value: val
312 | };
313 |
314 | registerValue = value;
315 |
316 | registeredData.setValue(value);
317 | }, function(val) {
318 | var value = {
319 | type: 'error',
320 | value: val
321 | };
322 |
323 | registerValue = value;
324 |
325 | provider.reportError({
326 | value: val
327 | });
328 |
329 | registeredData.setValue(value);
330 | });
331 |
332 | /*if (registerValue) {
333 | registeredData.setValue(registerValue);
334 | }*/
335 |
336 | return promiseWrap(promise, registeredData);
337 | },
338 | get: function(target, name) {
339 | // console.log('get', arguments);
340 |
341 | if (fake.hasOwnProperty(name)) {
342 | return fake[name];
343 | }
344 |
345 | return target[name];
346 | }
347 | }),
348 | enumerable: promiseDesc.enumerable,
349 | configurable: promiseDesc.configurable,
350 | writable: promiseDesc.writable
351 | });
352 |
353 | var fake = {};
354 |
355 | fake.resolve = function(val) {
356 | var result = originalPromiseResolve.value.call(originalPromise, val);
357 |
358 | try {
359 | throw new Error();
360 | } catch (e) {
361 | var stack = e.stack;
362 | }
363 |
364 | var registeredData = provider.register(result, {
365 | stack: stack,
366 | caller: 'Promise.resolve()'
367 | });
368 |
369 | result.then(function(val) {
370 | registeredData.setValue({
371 | type: 'value',
372 | value: val
373 | });
374 | });
375 |
376 | return promiseWrap(result, registeredData);
377 | };
378 |
379 | fake.reject = function(val) {
380 | var result = originalPromiseReject.value.call(originalPromise, val);
381 |
382 | try {
383 | throw new Error();
384 | } catch (e) {
385 | var stack = e.stack;
386 | }
387 |
388 | var registeredData = provider.register(result, {
389 | stack: stack,
390 | caller: 'Promise.reject()'
391 | });
392 |
393 | result.then(null, function(val) {
394 | registeredData.setValue({
395 | type: 'error',
396 | value: val
397 | });
398 |
399 | provider.reportError({
400 | value: val
401 | });
402 | });
403 |
404 | return promiseWrap(result, registeredData);
405 | };
406 |
407 | fake.all = function(arr) {
408 | arr = arr.map(function(proxy) {
409 | return promiseByProxy.get(proxy);
410 | });
411 |
412 | var result = originalPromiseAll.value.call(originalPromise, arr);
413 |
414 | try {
415 | throw new Error();
416 | } catch (e) {
417 | var stack = e.stack;
418 | }
419 |
420 | var registeredData = provider.register(result, {
421 | stack: stack,
422 | caller: 'Promise.all()'
423 | });
424 |
425 | result.then(function(val) {
426 | registeredData.setValue({
427 | type: 'value',
428 | value: val
429 | });
430 | }, function(val) {
431 | registeredData.setValue({
432 | type: 'error',
433 | value: val
434 | });
435 | });
436 |
437 | return promiseWrap(result, registeredData);
438 | };
439 |
440 | fake.race = function(arr) {
441 | arr = arr.map(function(proxy) {
442 | return promiseByProxy.get(proxy);
443 | });
444 |
445 | var result = originalPromiseRace.value.call(originalPromise, arr);
446 |
447 | try {
448 | throw new Error();
449 | } catch (e) {
450 | var stack = e.stack;
451 | }
452 |
453 | var registeredData = provider.register(result, {
454 | stack: stack,
455 | caller: 'Promise.race()'
456 | });
457 |
458 | result.then(function(val) {
459 | registeredData.setValue({
460 | type: 'value',
461 | value: val
462 | });
463 | }, function(val) {
464 | registeredData.setValue({
465 | type: 'error',
466 | value: val
467 | });
468 | });
469 |
470 | return promiseWrap(result, registeredData);
471 | };
472 |
473 | provider.isPromise = function(value) {
474 | if (value instanceof originalPromise ||
475 | value instanceof PromiseForInstanceCheck
476 | ) {
477 | value = promiseByProxy.get(value) || value;
478 | return value;
479 | }
480 | };
--------------------------------------------------------------------------------
/shared/css/style.css:
--------------------------------------------------------------------------------
1 | html,
2 | body {
3 | font-size: 15px;
4 | }
5 |
6 | body {
7 | margin: 0;
8 | width: 100%;
9 | height: 100%;
10 | font-family: "Open Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
11 | overflow-y: scroll;
12 | background: #f0f0f0;
13 | }
14 |
15 | #promises-table {
16 | /*table-layout: fixed;*/
17 | }
18 |
19 | #head {
20 | position: fixed;
21 | top: 0;
22 | left: 0;
23 | right: 0;
24 | z-index: 100;
25 | }
26 |
27 | #content {
28 | padding-top: 74px;
29 | }
30 |
31 | #need-reload {
32 | padding-top: 74px;
33 | }
34 |
35 | .attach-toggle {
36 | display: inline-block;
37 | height: 20px;
38 | width: 40px;
39 | background: rgb(196, 196, 196);
40 | vertical-align: middle;
41 | margin-left: 20px;
42 | border-radius: 10px;
43 | cursor: pointer;
44 | box-shadow: inset 0 0 5px 0px rgba(0, 0, 0, 0.3);
45 | }
46 |
47 | @-moz-document url-prefix() {
48 | .attach-toggle {
49 | box-shadow: inset 0 0 5px -1px rgba(0, 0, 0, 0.3);
50 | }
51 | }
52 |
53 | .attach-toggle[selected] .attach-toggle-ball {
54 | transform: translateX(0);
55 | background-color: rgb(211, 89, 89);
56 | box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.3);
57 | }
58 |
59 | .attach-toggle-ball {
60 | width: 20px;
61 | height: 20px;
62 | border-radius: 50%;
63 |
64 | transform: translateX(20px);
65 | background-color: rgb(211, 210, 210);
66 | box-shadow: 0 0 3px 0px rgba(0, 0, 0, 0.3);
67 |
68 | transition: background-color 0.3s, transform 0.3s;
69 | }
70 |
71 | .pd-table-cell {
72 | cursor: default;
73 | }
74 |
75 | .pd-table-cell-header {
76 | background-color: #f0f0f0 !important;
77 | }
78 |
79 | .pd-show-error {
80 | cursor: pointer;
81 | width: 100%;
82 | }
83 |
84 | .cell-id {
85 | text-align: center;
86 | }
87 |
88 | .resource-link {
89 | font-size: 13px;
90 | color: #333;
91 | text-decoration: underline;
92 | }
93 |
94 | .primitive-value {
95 | word-wrap: nowrap;
96 | overflow-wrap: nowrap;
97 | white-space: nowrap;
98 | overflow: hidden;
99 | text-overflow: ellipsis;
100 | }
101 |
102 | .keys-value {
103 | max-height: 100px;
104 | overflow: hidden;
105 | }
106 |
107 |
108 | .pd-promise-chain {
109 | border-left: 1px solid black;
110 | padding-left: 10px;
111 | margin-top: 10px;
112 |
113 | }
114 |
115 | .pd-promise-chain-item {
116 | position: relative;
117 | }
118 |
119 | .pd-promise-chain-item::before {
120 | content: '';
121 | height: 1px;
122 | background-color: black;
123 | position: absolute;
124 | top: 50%;
125 | left: -10px;
126 | width: 10px;
127 | margin-top: -0.5px;
128 | }
129 |
130 |
131 | .pd-table-body {
132 | margin-bottom: 10px;
133 | }
134 |
135 | .tbody-pending .pd-table-cell {
136 | // background-color: #fafafa;
137 | background-color: white;
138 | }
139 |
140 | .pd-table-extend .ui.segment,
141 | .pd-table-extend .ui.message {
142 | background-color: #fafafa;
143 | box-shadow: inset 0px 0px 0px 1px rgba(0, 0, 0, 0.1);
144 | border-radius: 0;
145 | }
146 |
147 | .pd-header-icons {
148 | height: 20px;
149 | float: right;
150 | margin-top: 2px;
151 | }
152 |
153 | .pd-header-icons .icon {
154 | height: 20px;
155 | font-size: 19px;
156 | line-height: 19px;
157 | padding: 0 !important;
158 | margin: 0 !important;
159 | display: inline-block !important;
160 | margin-left: 10px !important;
161 | width: 30px !important;
162 | padding-left: 10px !important;
163 | border-left: 1px solid #ccc;
164 | }
165 |
166 | .pd-main-header {
167 | z-index: 10;
168 | border-bottom: 1px solid #cacaca !important;
169 | line-height: 1.40 !important;
170 | }
171 |
172 | [data-control="checkbox"][data-checked="true"] {
173 | color: green;
174 | }
175 |
176 |
177 | /* ####################### Table ###################### */
178 |
179 |
180 | /* Prototype */
181 | .pd-table {
182 | width: 100%;
183 | border-collapse: collapse;
184 | }
185 |
186 | /* Table Content */
187 | .pd-table-cell,
188 | .pd-table-cell-header {
189 | border-collapse: collapse;
190 | -webkit-box-sizing: border-box;
191 | -moz-box-sizing: border-box;
192 | -ms-box-sizing: border-box;
193 | box-sizing: border-box;
194 | -webkit-transition: all 0.1s ease-out;
195 | -moz-transition: all 0.1s ease-out;
196 | transition: all 0.1s ease-out;
197 |
198 | flex-grow: 2;
199 | width: 25%;
200 | display: flex;
201 | align-items: center;
202 | }
203 |
204 | .pd-table-cell:nth-child(1),
205 | .pd-table-cell-header:nth-child(1) {
206 | width: 50px;
207 | /*padding-right: 0;
208 | padding-left: 0;*/
209 | justify-content: center;
210 | }
211 |
212 | .pd-table-cell:nth-child(2),
213 | .pd-table-cell-header:nth-child(2) {
214 | flex-grow: 3;
215 | width: 40%;
216 | }
217 |
218 | .pd-table-cell:nth-child(3),
219 | .pd-table-cell-header:nth-child(3) {
220 | flex-grow: 1;
221 | width: 15%;
222 | justify-content: center;
223 | }
224 |
225 | .pd-table-cell:nth-child(4),
226 | .pd-table-cell-header:nth-child(4) {
227 | flex-grow: 4;
228 | width: 40%;
229 | }
230 |
231 | .pd-table-cell:nth-child(5),
232 | .pd-table-cell-header:nth-child(5) {
233 | width: 70px;
234 | /*padding-right: 0;
235 | padding-left: 0;*/
236 | justify-content: center;
237 | }
238 |
239 | /* Headers */
240 | .pd-table-head {
241 | // border-bottom: 1px solid rgba(0, 0, 0, 0.03);
242 | }
243 |
244 | .pd-table-foot .pd-table-cell {
245 | background-color: rgba(0, 0, 0, 0.03);
246 | }
247 |
248 | .pd-table-cell-header {
249 | cursor: auto;
250 | background-color: rgba(0, 0, 0, 0.05);
251 | text-align: left;
252 | color: rgba(0, 0, 0, 0.8);
253 | padding: 0.5em 0.7em;
254 | vertical-align: middle;
255 | font-weight: bold;
256 | }
257 |
258 | .pd-dialog {
259 | background-color: rgba(0, 0, 0, 0.4);
260 | position: fixed;
261 | top: 0;
262 | left: 0;
263 | height: 100%;
264 | width: 100%;
265 | z-index: 1000;
266 | }
267 |
268 | .pd-dialog .ui.modal {
269 | display: initial !important;
270 | top: 50px !important;
271 | box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.5) !important;
272 | }
273 |
274 | .pd-branches {
275 | margin-bottom: 0 !important;
276 | border-radius: 0 !important;
277 | box-shadow: inset 0px 0px 0px 1px rgba(0, 0, 0, 0.1) !important;
278 | background: #FFF !important;
279 | }
280 |
281 | .pd-branches-title {
282 | width: auto !important;
283 | float: right !important;
284 | color: rgba(0, 0, 0, 0.4) !important;
285 | }
286 |
287 | .pd-branch-item {
288 | width: 40px;
289 | text-align: center;
290 | }
291 |
292 | .pd-branch-item::before {
293 | display: block !important;
294 | left: auto !important;
295 | right: 0px !important;
296 | }
297 |
298 | /*.pd-table-head .pd-table-cell-header:first-child {
299 | border-radius: 5px 0px 0px 0px;
300 | }
301 |
302 | .pd-table-head .pd-table-cell-header:last-child {
303 | border-radius: 0px 5px 0px 0px;
304 | }
305 |
306 | .pd-table-foot .pd-table-cell-header:first-child {
307 | border-radius: 0px 0px 0px 5px;
308 | }
309 |
310 | .pd-table-foot .pd-table-cell-header:last-child {
311 | border-radius: 0px 0px 5px 0px;
312 | }
313 |
314 | .pd-table-foot .pd-table-cell-header:only-child {
315 | border-radius: 0px 0px 5px 5px;
316 | }*/
317 | /* Table Cells */
318 | .pd-table-cell {
319 | padding: 0.40em 0.7em;
320 | vertical-align: middle;
321 | }
322 | /* Footer */
323 | .pd-table-foot {
324 | border-top: 1px solid rgba(0, 0, 0, 0.03);
325 | }
326 | .pd-table-foot .pd-table-cell-header {
327 | font-weight: normal;
328 | font-style: italic;
329 | }
330 | /* Table Striping */
331 | .pd-table .pd-table-body .pd-table-cell-header:nth-child(2n) {
332 | background-color: rgba(0, 0, 50, 0.02);
333 | }
334 | /* Icons */
335 | .pd-table .icon {
336 | vertical-align: baseline;
337 | }
338 | .pd-table .icon:only-child {
339 | margin: 0em;
340 | }
341 | /* Table Segment */
342 | .pd-table.segment:after {
343 | display: none;
344 | }
345 | .pd-table.segment.stacked:after {
346 | display: block;
347 | }
348 |
349 | /*******************************
350 | States
351 | *******************************/
352 | /*--------------
353 | Hover
354 | ---------------*/
355 | /* Sortable */
356 | .pd-table.sortable .pd-table-cell-header.disabled:hover {
357 | cursor: auto;
358 | text-align: left;
359 | font-weight: bold;
360 | color: #333333;
361 | color: rgba(0, 0, 0, 0.8);
362 | }
363 | .pd-table.sortable .pd-table-head .pd-table-cell-header:hover {
364 | background-color: rgba(0, 0, 0, 0.13);
365 | color: rgba(0, 0, 0, 0.8);
366 | }
367 | /* Inverted Sortable */
368 | .ui.inverted.sortable.table .pd-table-head .pd-table-cell-header:hover {
369 | background-color: rgba(255, 255, 255, 0.13);
370 | color: #ffffff;
371 | }
372 | /*--------------
373 | Positive
374 | ---------------*/
375 | .pd-table .pd-table-row-cont.positive,
376 | .pd-table .pd-table-cell.positive {
377 | -webkit-box-shadow: 2px 0px 0px #119000 inset;
378 | box-shadow: 2px 0px 0px #119000 inset;
379 | }
380 | .pd-table .pd-table-row-cont.positive .pd-table-cell,
381 | .pd-table .pd-table-cell.positive {
382 | background-color: #F2F8F0 !important;
383 | color: #119000 !important;
384 | }
385 | .pd-table.celled .pd-table-row-cont.positive:hover .pd-table-cell,
386 | .pd-table.celled .pd-table-row-cont:hover .pd-table-cell.positive,
387 | .pd-table .pd-table-row-cont.positive:hover .pd-table-cell,
388 | .pd-table .pd-table-cell:hover.positive,
389 | .pd-table .pd-table-cell-header:hover.positive {
390 | background-color: #ECF5E9 !important;
391 | color: #119000 !important;
392 | }
393 | /*--------------
394 | Negative
395 | ---------------*/
396 | .pd-table .pd-table-row-cont.negative,
397 | .pd-table .pd-table-cell.negative {
398 | -webkit-box-shadow: 2px 0px 0px #CD2929 inset;
399 | box-shadow: 2px 0px 0px #CD2929 inset;
400 | }
401 | .pd-table .pd-table-row-cont.negative .pd-table-cell,
402 | .pd-table .pd-table-cell.negative {
403 | background-color: #F9F4F4;
404 | color: #CD2929 !important;
405 | }
406 | .pd-table.celled .pd-table-row-cont.negative:hover .pd-table-cell,
407 | .pd-table.celled .pd-table-row-cont:hover .pd-table-cell.negative,
408 | .pd-table .pd-table-row-cont.negative:hover .pd-table-cell,
409 | .pd-table .pd-table-cell:hover.negative,
410 | .pd-table .pd-table-cell-header:hover.negative {
411 | background-color: #F2E8E8;
412 | color: #CD2929;
413 | }
414 | /*--------------
415 | Error
416 | ---------------*/
417 | .pd-table .pd-table-row-cont.error,
418 | .pd-table .pd-table-cell.error {
419 | -webkit-box-shadow: 2px 0px 0px #CD2929 inset;
420 | box-shadow: 2px 0px 0px #CD2929 inset;
421 | }
422 | .pd-table .pd-table-row-cont.error .pd-table-cell,
423 | .pd-table .pd-table-cell.error,
424 | .pd-table .pd-table-cell-header.error {
425 | background-color: #F9F4F4;
426 | color: #CD2929;
427 | }
428 | .pd-table.celled .pd-table-row-cont.error:hover .pd-table-cell,
429 | .pd-table.celled .pd-table-row-cont:hover .pd-table-cell.error,
430 | .pd-table .pd-table-row-cont.error:hover .pd-table-cell,
431 | .pd-table .pd-table-cell:hover.error,
432 | .pd-table .pd-table-cell-header:hover.error {
433 | background-color: #F2E8E8;
434 | color: #CD2929;
435 | }
436 | /*--------------
437 | Warning
438 | ---------------*/
439 | .pd-table .pd-table-row-cont.warning,
440 | .pd-table .pd-table-cell.warning {
441 | -webkit-box-shadow: 2px 0px 0px #7D6C00 inset;
442 | box-shadow: 2px 0px 0px #7D6C00 inset;
443 | }
444 | .pd-table .pd-table-row-cont.warning .pd-table-cell,
445 | .pd-table .pd-table-cell.warning,
446 | .pd-table .pd-table-cell-header.warning {
447 | background-color: #FBF6E9;
448 | color: #7D6C00;
449 | }
450 | .pd-table.celled .pd-table-row-cont.warning:hover .pd-table-cell,
451 | .pd-table.celled .pd-table-row-cont:hover .pd-table-cell.warning,
452 | .pd-table .pd-table-row-cont.warning:hover .pd-table-cell,
453 | .pd-table .pd-table-cell:hover.warning,
454 | .pd-table .pd-table-cell-header:hover.warning {
455 | background-color: #F3EDDC;
456 | color: #7D6C00;
457 | }
458 | /*--------------
459 | Active
460 | ---------------*/
461 | .pd-table .pd-table-row-cont.active,
462 | .pd-table .pd-table-cell.active {
463 | -webkit-box-shadow: 2px 0px 0px rgba(50, 50, 50, 0.9) inset;
464 | box-shadow: 2px 0px 0px rgba(50, 50, 50, 0.9) inset;
465 | }
466 | .pd-table .pd-table-row-cont.active .pd-table-cell,
467 | .pd-table .pd-table-row-cont .pd-table-cell.active {
468 | background-color: #E0E0E0;
469 | color: rgba(50, 50, 50, 0.9);
470 | /* border-color: rgba(0, 0, 0, 0.15) !important; */
471 | }
472 | /*--------------
473 | Disabled
474 | ---------------*/
475 | .pd-table .pd-table-row-cont.disabled .pd-table-cell,
476 | .pd-table .pd-table-row-cont .pd-table-cell.disabled,
477 | .pd-table .pd-table-row-cont.disabled:hover .pd-table-cell,
478 | .pd-table .pd-table-row-cont:hover .pd-table-cell.disabled {
479 | color: rgba(150, 150, 150, 0.3);
480 | }
481 | /*******************************
482 | Variations
483 | *******************************/
484 | /*--------------
485 | Celled
486 | ---------------*/
487 | .pd-table.celled {
488 | color: rgba(0, 0, 0, 0.8);
489 | }
490 | .pd-table.celled .pd-table-body .pd-table-row-cont,
491 | .pd-table.celled .pd-table-foot .pd-table-row-cont {
492 | border: none;
493 | }
494 | .pd-table.celled .pd-table-cell-header,
495 | .pd-table.celled .pd-table-cell {
496 | border: 1px solid rgba(0, 0, 0, 0.1);
497 | }
498 | /* Coupling with segment */
499 | .pd-table.celled.segment .pd-table-cell-header:first-child,
500 | .pd-table.celled.segment .pd-table-cell:first-child {
501 | border-left: none;
502 | }
503 | .pd-table.celled.segment .pd-table-cell-header:last-child,
504 | .pd-table.celled.segment .pd-table-cell:last-child {
505 | border-right: none;
506 | }
507 | /*--------------
508 | Sortable
509 | ---------------*/
510 | .pd-table.sortable .pd-table-head .pd-table-cell-header {
511 | cursor: pointer;
512 | white-space: nowrap;
513 | }
514 | .pd-table.sortable .pd-table-head .pd-table-cell-header.sorted,
515 | .pd-table.sortable .pd-table-head .pd-table-cell-header.sorted:hover {
516 | -webkit-user-select: none;
517 | -moz-user-select: none;
518 | -ms-user-select: none;
519 | user-select: none;
520 | }
521 | .pd-table.sortable .pd-table-head .pd-table-cell-header:after {
522 | display: inline-block;
523 | content: '';
524 | width: 1em;
525 | opacity: 0.8;
526 | margin: 0em 0em 0em 0.5em;
527 | font-family: 'Icons';
528 | font-style: normal;
529 | font-weight: normal;
530 | text-decoration: inherit;
531 | }
532 | .pd-table.sortable .pd-table-head .pd-table-cell-header.ascending:after {
533 | content: '\25b4';
534 | }
535 | .pd-table.sortable .pd-table-head .pd-table-cell-header.descending:after {
536 | content: '\25be';
537 | }
538 | /*--------------
539 | Inverted
540 | ---------------*/
541 | /* Text Color */
542 | .pd-table.inverted .pd-table-cell {
543 | color: rgba(255, 255, 255, 0.9);
544 | }
545 | .pd-table.inverted .pd-table-cell-header {
546 | background-color: rgba(0, 0, 0, 0.15);
547 | color: rgba(255, 255, 255, 0.9);
548 | }
549 | /* Stripes */
550 | .pd-table.inverted .pd-table-body .pd-table-row-cont:nth-child(2n) {
551 | background-color: rgba(255, 255, 255, 0.06);
552 | }
553 | /*--------------
554 | Definition
555 | ---------------*/
556 | .pd-table.definition .pd-table-cell:first-child {
557 | font-weight: bold;
558 | }
559 | /*--------------
560 | Collapsing
561 | ---------------*/
562 | .pd-table.collapsing {
563 | width: auto;
564 | }
565 | /*--------------
566 | Basic
567 | ---------------*/
568 | .pd-table.basic .pd-table-cell-header {
569 | background-color: transparent;
570 | padding: 0.5em;
571 | }
572 | .pd-table.basic .pd-table-body .pd-table-row-cont {
573 | border-bottom: 1px solid rgba(0, 0, 0, 0.03);
574 | }
575 | .pd-table.basic .pd-table-cell {
576 | padding: 0.8em 0.5em;
577 | }
578 | .pd-table.basic .pd-table-body .pd-table-row-cont:nth-child(2n) {
579 | background-color: transparent !important;
580 | }
581 | /*--------------
582 | Padded
583 | ---------------*/
584 | .pd-table.padded .pd-table-cell-header,
585 | .pd-table.padded .pd-table-cell {
586 | padding: 0.8em 1em;
587 | }
588 | .pd-table.compact .pd-table-cell-header {
589 | padding: 0.3em 0.5em;
590 | }
591 | .pd-table.compact .pd-table-cell {
592 | padding: 0.2em 0.5em;
593 | }
594 | /*--------------
595 | Sizes
596 | ---------------*/
597 | /* Small */
598 | .pd-table.small {
599 | font-size: 0.875em;
600 | }
601 | /* Standard */
602 | .pd-table {
603 | font-size: 1em;
604 | }
605 | /* Large */
606 | .pd-table.large {
607 | font-size: 1.1em;
608 | }
609 |
610 | .pd-table-row-cont {
611 | display: flex;
612 | }
--------------------------------------------------------------------------------
/shared/fw/cui/modules/ajax.js:
--------------------------------------------------------------------------------
1 | var exports = {},
2 | lib = require('lib'),
3 | utils = require('utils'),
4 | hasOwn = Object.prototype.hasOwnProperty;
5 |
6 | exports.eventsArr = [
7 | 'load',
8 | 'error',
9 | 'progress',
10 | 'timeout',
11 | 'end',
12 | 'abort',
13 | 'result'
14 | ];
15 |
16 | exports.events = events.getMap(module.name, exports.eventsArr);
17 | exports.events.load = exports.events.result;
18 |
19 | var AjaxError = function AjaxError(reason, status, transport) {
20 | Error.call(this);
21 |
22 | this.reason = reason;
23 | this.status = status;
24 | this.transport = transport;
25 |
26 | if (Error.captureStackTrace) {
27 | Error.captureStackTrace(this, AjaxError);
28 | }
29 | },
30 | ajax = exports;
31 |
32 | AjaxError.prototype = Object.create(Error.prototype);
33 |
34 | var JSONPCount = 0,
35 | FN_KEY = '_jsonpCallback',
36 | DEFAULT_JSONP_CALLBACK = 'callback';
37 |
38 | var requestTypes = {
39 | urlencoded: 'application/x-www-form-urlencoded',
40 | json: 'application/json',
41 | text: 'text/plain'
42 | },
43 | requestTypeHandlers = {
44 | urlencoded: function(data) {
45 | return Sync.escape(data);
46 | },
47 | json: function(data) {
48 | return JSON.stringify(data);
49 | },
50 | text: function(data) {
51 | return data;
52 | }
53 | },
54 | responseTypes = {
55 | json: function(text) {
56 | return text ? JSON.parse(text) : null;
57 | }
58 | },
59 | responseTypesMap = {
60 | 'application/json': 'json'
61 | };
62 |
63 | var appendQuery = function(url, query) {
64 | if (url.indexOf('?') !== -1) {
65 | return url + '&' + query;
66 | } else {
67 | return url + '?' + query;
68 | }
69 | },
70 | extendPromise = function(promise, map) {
71 | events.wrap(promise, {
72 | noEventForward: true
73 | });
74 |
75 | exports.eventsArr.forEach(function(eventKey) {
76 | promise[eventKey] = function(val) {
77 | if (typeof val === 'function') {
78 | events.on(promise, exports.events[eventKey], val);
79 | return this;
80 | }
81 |
82 | if (map && hasOwn.call(map, eventKey)) {
83 | map[eventKey].call(promise, val);
84 | } else {
85 | events.fire(promise, exports.events[eventKey], val);
86 | }
87 |
88 | return this;
89 | };
90 | });
91 | },
92 | getAjaxError = function(reason, status, transport, name) {
93 | var error = new AjaxError(reason, status, transport);
94 |
95 | error.transportName = name;
96 | error[name] = transport;
97 |
98 | return error;
99 | };
100 |
101 | ajax.send = function(options) {
102 | var xhr = new XMLHttpRequest(),
103 | method = typeof options.method === 'string' ?
104 | options.method.toUpperCase() : 'GET',
105 | contentType = typeof options.contentType === 'string' ?
106 | options.contentType.toLowerCase() : 'urlencoded',
107 | data = options.data,
108 | url = options.url,
109 | responseType = typeof options.responseType === 'string' ?
110 | options.responseType.toLowerCase() : '';
111 |
112 | var promise = new Promise(function(resolve, reject) {
113 | var fireError = function(reason, status, event) {
114 | if (errorFired) return;
115 | errorFired = true;
116 |
117 | var error = getAjaxError(reason, status, xhr, 'xhr');
118 |
119 | if (event) {
120 | event.fire(promise, exports.events[event], error);
121 | } else {
122 | events.fire(promise, exports.events.error, error);
123 | }
124 |
125 | reject(error);
126 | },
127 | errorFired;
128 |
129 | if (typeof data === 'object' && data) {
130 | data = requestTypeHandlers[method === 'POST' ?
131 | contentType : 'urlencoded'](data);
132 | }
133 |
134 | typeof data === 'string' || (data = '');
135 |
136 | if (method !== 'POST' && data) {
137 | url = appendQuery(url, data);
138 | data = null;
139 | }
140 |
141 | xhr.url = url;
142 | xhr.open(method, url, /*async*/ true);
143 |
144 | if (responseType) {
145 | xhr.responseType = responseType;
146 | }
147 |
148 | if (options.withCredentials) {
149 | xhr.withCredentials = true;
150 | }
151 |
152 | xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
153 |
154 | if (method === 'POST' || contentType !== 'urlencoded') {
155 | xhr.setRequestHeader('Content-Type', requestTypes[contentType]);
156 | }
157 |
158 | if (options.headers) {
159 | Sync.each(options.headers, function(val, key) {
160 | xhr.setRequestHeader(key, val);
161 | });
162 | }
163 |
164 | events.on(xhr, 'load', function(e) {
165 | var response = xhr.response,
166 | responseType = xhr.responseType,
167 | hasError;
168 |
169 | if (!responseType && response) {
170 | responseType = xhr.getResponseHeader('Content-Type');
171 | responseType = responseType.split(';', 1)[0];
172 |
173 | if (hasOwn.call(responseTypesMap, responseType)) {
174 | responseType = responseTypesMap[responseType];
175 | var handleResponse = responseTypes[responseType];
176 | }
177 | }
178 |
179 | if (handleResponse) {
180 | try {
181 | response = response ? handleResponse(response) : '';
182 | } catch (e) {
183 | response = '';
184 | hasError = 'parseerror';
185 | }
186 | }
187 |
188 | if (hasError) {
189 | fireError(hasError);
190 | return;
191 | }
192 |
193 | var status = xhr.status,
194 | scheme = url.match(/^(\w+?\:)\/\//),
195 | isFsReq;
196 |
197 | if ((scheme && scheme[1] === 'file:') ||
198 | !scheme && window.location.protocol === 'file:') {
199 | isFsReq = true;
200 | }
201 |
202 | if ((status >= 200 && status < 300) || !status && isFsReq) {
203 | if (!status) {
204 | status = 200;
205 | }
206 |
207 | events.fire(promise, exports.events.result, response, status);
208 |
209 | resolve({
210 | response: response,
211 | status: status,
212 | xhr: xhr
213 | });
214 | } else if (status >= 400/* && status < 600*/) {
215 | fireError('httperror', status);
216 | } else if (status === 304) {
217 | // handle http cache here
218 | // if no cached content:
219 | fireError('cacheerror');
220 | }
221 | });
222 |
223 | events.on(xhr, 'error', function() {
224 | fireError('neterror');
225 | });
226 |
227 | events.on(xhr, 'progress', function(e) {
228 | events.fire(promise, exports.events.progress, {
229 | lengthComputable: e.lengthComputable,
230 | loaded: e.loaded,
231 | total: e.total
232 | });
233 | });
234 |
235 | events.on(xhr, 'abort', function() {
236 | // events.fire(promise, exports.events.abort);
237 | fireError('abort', void 0, 'timeout');
238 | });
239 |
240 | events.on(xhr, 'timeout', function() {
241 | // events.fire(promise, exports.events.timeout);
242 | fireError('timeout', void 0, 'timeout');
243 | });
244 |
245 | events.on(xhr, 'loadend', function() {
246 | events.fire(promise, exports.events.end, xhr);
247 | });
248 |
249 | xhr.send(data);
250 | });
251 |
252 | extendPromise(promise, {
253 | abort: function() {
254 | xhr.abort();
255 | }
256 | });
257 |
258 | return promise;
259 | };
260 |
261 | ajax.script = function(options) {
262 | var url = typeof options === 'string' ? options : options.url;
263 |
264 | if (typeof url !== 'string' || !url) {
265 | return Promise.reject(getAjaxError('nourl', void 0, null, 'script'));
266 | // return Promise.reject(new AjaxError('nourl'));
267 | }
268 |
269 | return new Promise(function(resolve, reject) {
270 | var script = loadScript(url, function(err) {
271 | if (err) {
272 | var error = getAjaxError('error', void 0, script, 'script');
273 | // var error = new AjaxError('error');
274 |
275 | reject(error);
276 | } else {
277 | resolve(script)
278 | }
279 | });
280 | });
281 | };
282 |
283 | ajax.jsonp = function(options) {
284 | var url = options.url,
285 | data = options.data || '',
286 | callbackKey = options.callbackKey || DEFAULT_JSONP_CALLBACK,
287 | aborted,
288 | abortMethod;
289 |
290 | var promise = new Promise(function(resolve, reject) {
291 | var fn = FN_KEY + (JSONPCount++),
292 | executed = false,
293 | loadedData;
294 |
295 | var fireError = function(reason, status, event) {
296 | if (errorFired) return;
297 | errorFired = true;
298 |
299 | var error = getAjaxError(reason, status, script, 'jsonp');
300 |
301 | if (event) {
302 | event.fire(promise, exports.events[event], error);
303 | } else {
304 | events.fire(promise, exports.events.error, error);
305 | }
306 |
307 | reject(error);
308 | },
309 | errorFired;
310 |
311 | if (typeof data === 'object') {
312 | data[callbackKey] = fn;
313 | data = Sync.escape(data);
314 | } else {
315 | data += (data ? '&' : '') + callbackKey + '=' + fn;
316 | }
317 |
318 | url = appendQuery(url, data);
319 |
320 | window[fn] = function(data) {
321 | executed = true;
322 | loadedData = data;
323 | };
324 |
325 | abortMethod = function() {
326 | if (aborted) return;
327 |
328 | window[fn] = null;
329 | aborted = true;
330 | script.remove();
331 |
332 | fireError('abort', void 0, 'abort');
333 | /*events.fire(promise, exports.events.abort);
334 | reject(new AjaxError('abort'));*/
335 | };
336 |
337 | var script = loadScript(url, function(err) {
338 | if (aborted) return;
339 |
340 | window[fn] = null;
341 |
342 | if (!executed || err) {/*
343 | var error = new AjaxError('error');
344 | events.fire(promise, exports.events.error, error);*/
345 |
346 | fireError('error');
347 |
348 | reject(error);
349 | } else {
350 | events.fire(promise, exports.events.result, loadedData);
351 |
352 | resolve({
353 | response: loadedData
354 | });
355 | }
356 | });
357 | });
358 |
359 | extendPromise(promise, {
360 | abort: abortMethod
361 | });
362 |
363 | return promise;
364 | };
365 |
366 | var FRAME_OPTIONS = {
367 | method: 'GET',
368 | enctype: 'application/x-www-form-urlencoded',
369 | action: '',
370 | global: false,
371 | target: '',
372 | timeout: 0
373 | };
374 |
375 | ajax.frame = function(options) {
376 | if (!options) {
377 | // return Promise.reject(new AjaxError('noarg'));
378 | return Promise.reject(getAjaxError('noarg', void 0, null, 'frame'));
379 | }
380 |
381 | var nodeName = options.nodeName;
382 |
383 | if (typeof nodeName === 'string' && nodeName.toLowerCase() === 'form') {
384 | form = options;
385 |
386 | options = lib.extend({}, FRAME_OPTIONS, arguments[1]);
387 |
388 | [
389 | 'action',
390 | 'method',
391 | 'enctype',
392 | 'global',
393 | 'target'
394 | ].forEach(function(key) {
395 | var val = form.getAttribute(key);
396 |
397 | if (val) {
398 | options[key] = val;
399 | }
400 | });
401 | } else {
402 | options = lib.extend({}, FRAME_OPTIONS, options);
403 | }
404 |
405 | var target = document.body || document.head || document.documentElement,
406 | data,
407 | url,
408 | method,
409 | form,
410 | autoRemoveForm;
411 |
412 | var sendAsync = function() {
413 | var iframe,
414 | submit,
415 | key,
416 | ignoreLoad,
417 | pendingTimer,
418 | abortMethod;
419 |
420 | var promise = new Promise(function(resolve, reject) {
421 | var loadHandler = function() {
422 | if (ignoreLoad) return;
423 |
424 | setTimeout(cleanUp, 1);
425 |
426 | try {
427 | var win = this.contentWindow;
428 | } catch (e) {}
429 |
430 | if (win) {
431 | var response = options.responseHandler;
432 |
433 | if (response) {
434 | response = response(win);
435 | } else {
436 | response = win;
437 | }
438 |
439 | events.fire(promise, exports.events.result, response);
440 |
441 | resolve({
442 | response: response,
443 | win: win
444 | });
445 | } else {
446 | fireError('error');
447 | }
448 | },
449 | cleanUp = function() {
450 | try {
451 | target.removeChild(iframe);
452 | } catch (e) {};
453 |
454 | iframe = target = null;
455 | clearTimeout(pendingTimer);
456 | };
457 |
458 | var fireError = function(reason, status, event) {
459 | if (errorFired) return;
460 | errorFired = true;
461 |
462 | var error = getAjaxError(reason, status, iframe, 'frame');
463 |
464 | if (event) {
465 | event.fire(promise, exports.events[event], error);
466 | } else {
467 | events.fire(promise, exports.events.error, error);
468 | }
469 |
470 | reject(error);
471 | },
472 | errorFired;
473 |
474 | iframe = document.createElement('iframe');
475 | iframe.style.display = 'none';
476 | iframe.src = 'javascript: true';
477 |
478 | abortMethod = function() {
479 | ignoreLoad = true;
480 |
481 | try {
482 | if (this.contentWindow.stop) {
483 | this.contentWindow.stop();
484 | } else {
485 | this.contentWindow.document.execCommand('Stop');
486 | }
487 | } catch (e) {
488 | this.src = 'about:blank';
489 | }
490 |
491 | cleanUp();
492 | fireError('abort', void 0, 'abort');
493 | };
494 |
495 | isFinite(options.timeout) && (pendingTimer = setTimeout(function() {
496 | ignoreLoad = true;
497 | cleanUp();
498 | fireError('timeout', void 0, 'timeout');
499 | }, options.timeout));
500 |
501 | if (form) {
502 | submit = form.constructor.prototype.submit;
503 | key = 'iframe' + Date.now();
504 | iframe.id = iframe.name = form.target = key;
505 |
506 | events.once(iframe, 'load', function() {
507 | events.once(iframe, 'load', function() {
508 | loadHandler.apply(this, arguments);
509 |
510 | if (form.parentNode === target && autoRemoveForm) {
511 | target.removeChild(form);
512 | }
513 |
514 | form.target = null;
515 | form = null;
516 | });
517 |
518 | setTimeout(function() {
519 | submit.call(form);
520 | }, 1);
521 | });
522 | } else {
523 | events.on(iframe, 'load', loadHandler);
524 | iframe.src = url;
525 | }
526 |
527 | target.appendChild(iframe);
528 | });
529 |
530 | extendPromise(promise, {
531 | abort: abortMethod
532 | });
533 |
534 | return promise;
535 | },
536 | sendGlobal = function() {
537 | if (form) {
538 | var submit = form.constructor.prototype.submit;
539 |
540 | if (options.target) {
541 | form.target = options.target;
542 | }
543 |
544 | setTimeout(function() {
545 | submit.call(form);
546 | }, 1);
547 | } else {
548 | utils.goLink(url, options.target);
549 | }
550 |
551 | return Promise.resolve();
552 | };
553 |
554 | url = (options.action || options.url || window.location.href);
555 | method = (options.method + '').toUpperCase();
556 |
557 | if (method === 'POST' && !form) {
558 | form = document.createElement('form');
559 | form.style.display = 'none';
560 | form.action = url;
561 | form.method = 'POST';
562 | form.setAttribute('enctype', options.enctype);
563 |
564 | data = options.data;
565 | data && (data = lib.unescape(lib.escape(data), true));
566 |
567 | if (typeof data === 'object') {
568 | var fragment = document.createDocumentFragment();
569 |
570 | lib.each(data, function(val, key) {
571 | var input = document.createElement('input');
572 |
573 | input.type = 'hidden';
574 | input.name = key;
575 | input.value = val;
576 |
577 | fragment.append(input);
578 | });
579 |
580 | form.append(fragment);
581 | }
582 |
583 | autoRemoveForm = !options.global;
584 | target.append(form);
585 | } else if (method === 'GET') {
586 | data = options.data;
587 | data = data ? (typeof data === 'object' ? lib.escape(data) : data) : '';
588 |
589 | if (data = data.trim()) {
590 | url += (url.indexOf('?') !== -1 ? '&' : '?') + data;
591 | }
592 | }
593 |
594 | if (options.global) {
595 | return sendGlobal();
596 | }
597 |
598 | return sendAsync();
599 | };
600 |
601 | function loadScript(url, callback) {
602 | var script = document.createElement('script'),
603 | target = document.head,
604 | called = false;
605 |
606 | var end = function(e) {
607 | if (!called) {
608 | typeof callback === 'function' &&
609 | callback.call(script, e.type === 'error');
610 |
611 | called = true;
612 | target.removeChild(script);
613 | }
614 | };
615 |
616 | script.async = true;
617 | script.onerror = script.onload = end;
618 | script.src = url;
619 |
620 | return target.appendChild(script);
621 | };
--------------------------------------------------------------------------------
/shared/fw/cui/modules/ui.js:
--------------------------------------------------------------------------------
1 | var utils = require('utils'),
2 | lib = require('lib');
3 |
4 | var exports = {
5 | events: events.getMap(module.name, [
6 | 'childControl',
7 | 'changeState',
8 | 'idControl',
9 | 'change',
10 | 'select',
11 | 'disabled',
12 | 'enabled',
13 | 'destroy',
14 | 'load',
15 | 'error',
16 | 'open',
17 | 'close',
18 | 'show',
19 | 'hide',
20 | 'remove',
21 | 'attach',
22 | 'detach',
23 | 'activate',
24 | 'resize',
25 | ]),
26 | mixins: {},
27 | controls: {},
28 | states: {
29 | hover: 'hover',
30 | active: 'active',
31 | focus: 'focus',
32 | none: '',
33 | blur: 'blur',
34 | error: 'error',
35 | click: 'click',
36 | disabled: 'disabled',
37 | loading: 'loading',
38 | selected: 'selected',
39 | readonly: 'readonly'
40 | },
41 | elements: {},
42 | types: {},
43 | keys: {
44 | DELETE: 46,
45 | DOWN: 40,
46 | RIGHT: 39,
47 | UP: 38,
48 | LEFT: 37,
49 | ESC: 27,
50 | ENTER: 13,
51 | BACKSPACE: 8,
52 | SPACE: 32,
53 | END: 35,
54 | HOME: 36
55 | },
56 | cache: function(object, key, value) {
57 | var cahceObj = libCache(object, UI_CACHE_KEY);
58 |
59 | if (!object || !cahceObj) return null;
60 |
61 | if (typeof key === 'undefined') {
62 | return cahceObj;
63 | }
64 |
65 | if (key === null) {
66 | libCache(object, UI_CACHE_KEY, null);
67 | }
68 |
69 | if (typeof value !== 'undefined') {
70 | return (cahceObj[key] = value);
71 | } else {
72 | return cahceObj[key];
73 | }
74 | },
75 | is: function(control, type) {
76 | if (!control) return false;
77 |
78 | // type = utils.type2class(type);
79 |
80 | return typeof controls[type] === 'function' &&
81 | control instanceof controls[type];
82 | },
83 | get: function(key) {
84 | if (hasOwn.call(elements, key)) {
85 | return elements[key];
86 | }
87 |
88 | return null;
89 | },
90 | rect: function(element) {
91 | var cache = uiCache(element),
92 | data = cache[RECT_DATA_KEY];
93 |
94 | if (!data) {
95 | data = cache[RECT_DATA_KEY] = {
96 | rect: element.getBoundingClientRect(),
97 | scrollTop: window.pageYOffset,
98 | scrollLeft: window.pageXOffset
99 | };
100 |
101 | var handler = function() {
102 | events.remove(element, exports.events.resize, handler);
103 | events.remove(window, 'resize', handler);
104 | cache[RECT_DATA_KEY] = null;
105 | };
106 |
107 | events.on(element, exports.events.resize, handler);
108 | events.on(window, 'resize', handler);
109 |
110 | return data.rect;
111 | }
112 |
113 | var rect = data.rect,
114 | offsetLeft = (data.scrollLeft - window.pageXOffset),
115 | offsetTop = (data.scrollTop - window.pageYOffset);
116 |
117 | return {
118 | left: rect.left + offsetLeft,
119 | top: rect.top + offsetTop,
120 | right: rect.right + offsetLeft,
121 | bottom: rect.bottom + offsetTop,
122 | width: rect.width,
123 | height: rect.height
124 | };
125 | },
126 | create: function createControl(type, options, node) {
127 | var instance;
128 |
129 | if (typeof controls[type] === 'undefined') {
130 | return null;
131 | }
132 |
133 | (options || (options = {})).type = type;
134 | type = controls[type];
135 |
136 | node || (node = document.createElement('div'));
137 | instance = new type(node, options);
138 |
139 | return instance;
140 | },
141 | define: function defineControl(type, options) {
142 | var parent,
143 | proto,
144 | meta,
145 | properties,
146 | mixins;
147 |
148 | options || (options = {});
149 |
150 | parent = options.parent;
151 | parent = parent && hasOwn.call(controls, parent) ? parent : 'element';
152 |
153 | if (parent !== type && hasOwn.call(controls, type)) {
154 | throw new Error('Cannot define duplicate control: ' + type);
155 | }
156 |
157 | parent = controls[parent];
158 |
159 | if (isArray(mixins = options.mixins) && mixins.length) {
160 | mixins = mixins.map(function(mixin) {
161 | return controls[mixin];
162 | });
163 | } else {
164 | mixins = null;
165 | }
166 |
167 | if (options.contains || options.base /* real dom node*/) {
168 | proto = {};
169 |
170 | if (isArray(options.contains)) {
171 | proto.contains = options.contains/*.map(function(type) {
172 | return utils.type2class(type);
173 | })*/;
174 | }
175 |
176 | if (isArray(options.base /* real dom node*/)) {
177 | proto.base /* real dom node*/ = options.base /* real dom node*/;
178 | }
179 | }
180 |
181 | properties = options.properties;
182 |
183 | if (typeof properties === 'object' && !isArray(properties)) {
184 | meta = {
185 | properties: handleProperties(properties)
186 | };
187 | }
188 |
189 | return (controls[type] = utils.inherits({
190 | parent: parent,
191 | handler: options.handler,
192 | meta: meta,
193 | proto: proto,
194 | mixins: mixins,
195 | name: type
196 | }));
197 | },
198 | control: function(viewOrBase, control) {
199 | var control = uiCache(viewOrBase, UI_CONTROL_CACHE_KEY, control);
200 | return control;
201 | },
202 | DEFAULT_TYPE: '',
203 | DEFAULT_PROP: ''
204 | };
205 |
206 | var hasOwn = Object.prototype.hasOwnProperty,
207 | slice = Array.prototype.slice,
208 | isArray = Array.isArray,
209 | css2dom = utils.css2dom,
210 | controls = exports.controls,
211 | elements = exports.elements,
212 | types = exports.types,
213 | states = exports.states,
214 | extend = lib.extend,
215 | libCache = lib.cache,
216 | uiCache = exports.cache,
217 | uiControl = exports.control,
218 | idInc = 0;
219 |
220 | var RECT_DATA_KEY = 'rect_data',
221 | UI_CACHE_KEY = 'ui_cache',
222 | UI_CONTROL_CACHE_KEY = 'ui_control_cache',
223 | DEFAULT_TYPE = exports.DEFAULT_TYPE,
224 | DEFAULT_PROP = exports.DEFAULT_PROP;
225 |
226 | var destroy = function(params) {
227 | if (this.zombie) {
228 | console.log('destroy return by the zombie');
229 | return;
230 | }
231 |
232 | var parent = this.parent,
233 | view = this.view,
234 | node = this.node,
235 | i,
236 | children = this.children.concat(),
237 | name = this.get('name'),
238 | id = this.get('id'),
239 | marker,
240 | parentChildren;
241 |
242 | if (!params.onlyChildren) {
243 | if (params.remove) {
244 | view.remove();
245 | }
246 |
247 | if (parent && (parentChildren = parent.children)) {
248 | i = parentChildren.indexOf(this);
249 | i !== -1 && parentChildren.splice(i, 1);
250 | parentChildren[name] = null;
251 |
252 | parentChildren.forEach(function(child, index) {
253 | child.index = index;
254 | });
255 | }
256 |
257 | if (id) {
258 | elements[id] = null;
259 | }
260 |
261 | if ((marker = this.get('_attachMarker')) && marker.parentNode) {
262 | marker.parentNode.removeChild(marker);
263 | }
264 |
265 | view && events.clean(view);
266 | node && events.clean(node);
267 |
268 | uiCache(view, null);
269 | uiCache(node, null);
270 |
271 | uiControl(view, null);
272 |
273 | this.view =
274 | this.node =
275 | this.parent =
276 | this.children = null;
277 |
278 | this.zombie = true;
279 | // Object.freeze(this);
280 | }
281 |
282 | children.forEach(function(child) {
283 | child.destroy();
284 | });
285 | },
286 | getControl = function(type, callback, byInstance) {
287 | var compare = byInstance ? exports.is : function(control, type) {
288 | return control.type === type;
289 | };
290 |
291 | if (typeof callback !== 'function') {
292 | return this.children.filter(function(child) {
293 | return compare(child, type);
294 | });
295 | } else if (this.view.parsed) {
296 | this.children.forEach(function(child) {
297 | if (compare(child, type)) {
298 | callback(child);
299 | }
300 | });
301 | } else {
302 | events.expr(this.view, exports.events.childControl, function(e, child) {
303 | if (compare(child, type)) {
304 | callback(child);
305 | return true;
306 | }
307 | });
308 | }
309 | },
310 | generateUID = function() {
311 | return ++idInc;
312 | },
313 | accessors = function(control, accessor, args) {
314 | if (control.zombie) return;
315 |
316 | var tmp = control.constructor.properties,
317 | args = slice.call(args, 0),
318 | name = args[0].split(':'),
319 | type;
320 |
321 | if (name.length > 1) {
322 | type = name[0];
323 | args[0] = name = name[1];
324 |
325 | if (!hasOwn.call(types, type) || !hasOwn.call(types[type], accessor)) {
326 | type = DEFAULT_TYPE;
327 | }
328 |
329 | tmp = exports.type.getDefaultInstance(type);
330 | } else {
331 | name = name[0];
332 | type = tmp[name];
333 |
334 | if (type && hasOwn.call(type, accessor)) {
335 | tmp = type;
336 | } else {
337 | tmp = tmp[DEFAULT_PROP];
338 | }
339 | }
340 |
341 | // args.unshift(control);
342 | return tmp[accessor].apply(tmp, [control].concat(args));
343 | },
344 | handleProperties = function(properties) {
345 | return Object.keys(properties).reduce(function(result, key) {
346 | var val = result[key],
347 | type = '',
348 | args,
349 | accessors;
350 |
351 | if (typeof val === 'string') {
352 | type = val;
353 | } else if (isArray(val)) {
354 | type = (val[0] + '');
355 | args = val.slice(1);
356 | } else if (typeof val === 'object') {
357 | type = (val.type + '');
358 | args = val.args;
359 | accessors = {
360 | get: val.get,
361 | set: val.set
362 | };
363 | }/* else {
364 | val = null;
365 | }*/
366 |
367 | type = type.toLowerCase();
368 |
369 | if (type && hasOwn.call(types, type)) {
370 | result[key] = exports.type.create(type, args, accessors);
371 | } else {
372 | if (typeof val !== 'object' || isArray(val)) {
373 | val = null;
374 | }
375 |
376 | result[key] = val;
377 | }
378 |
379 | return result;
380 | }, properties);
381 | };
382 |
383 | exports.handleProperties = handleProperties;
384 | exports.type = {
385 | define: function(type, config) {
386 | types[type] = config;
387 | },
388 | create: function(type, args, accessors) {
389 | var config = types[type],
390 | factory = config.factory,
391 | instance;
392 |
393 | accessors || (accessors = config);
394 |
395 | instance = factory ? factory.apply(null, args) : {};
396 | instance.get = accessors.get || config.get;
397 | instance.set = accessors.set || config.set;
398 |
399 | instance.factory = factory;
400 | instance.type = type;
401 |
402 | return instance;
403 | },
404 | getDefaultInstance: function(type) {
405 | var config = types[type];
406 |
407 | return config.instance || (config.instance = exports.type.create(type));
408 | },
409 | get: function(type) {
410 | return types[type];
411 | }
412 | };
413 |
414 | exports.type.define(DEFAULT_TYPE, {
415 | get: function(control, name) {
416 | return uiCache(control.view, name);
417 | },
418 | set: function(control, name, value) {
419 | return uiCache(control.view, name, value);
420 | }
421 | });
422 |
423 | controls.element = utils.inherits({
424 | handler: function(node, params) {
425 | // Expected params
426 | // Changed to manual assignment for performance improvements
427 | if (params) {
428 | typeof params.type !== 'undefined' &&
429 | (this.type = params.type);
430 | typeof params.parent !== 'undefined' &&
431 | (this.parent = params.parent);
432 | typeof params.view !== 'undefined' &&
433 | (view = this.view = params.view);
434 |
435 | if (typeof params.index !== 'undefined') {
436 | var index = params.index;
437 | }
438 | }
439 |
440 | this.node = node;
441 | this.base = node;
442 | this.capture = params && params.capture || {};
443 |
444 | var parent = this.parent,
445 | self = this,
446 | normalPosition = true,
447 | view,
448 | children = this.children = [],
449 | contains = parent && parent.contains,
450 | properties = params && params.properties;
451 |
452 | view || (view = this.view = node);
453 |
454 | events.on(view, exports.events.destroy, function() {
455 | view = children = parent = self = node = null;
456 | });
457 |
458 | if (contains && contains.length) {
459 | normalPosition = false;
460 |
461 | var len = contains.length,
462 | i = 0;
463 |
464 | for (; i < len; i++) {
465 | if (exports.is(self, control)) {
466 | normalPosition = true;
467 | break;
468 | }
469 | }
470 | }
471 |
472 | if (properties) {
473 | lib.each(properties, function(val, key) {
474 | self.set(key, val);
475 | });
476 | }
477 |
478 | if (normalPosition) {
479 | var id = this.get('id');
480 |
481 | if (id && elements[id]) {
482 | debug('duplicates id: ', id, ' of control ', view, elements[id].view);
483 | // throw new Error();
484 | } else if (id) {
485 | elements[id] = this;
486 | // wtf here first arg
487 | events.fire(exports.events.idControl, this.node, this);
488 | } else {
489 | this.set('id', generateUID());
490 | }
491 |
492 |
493 | events.on(view, exports.events.childControl, function(e, child, index) {
494 | var name = child.get('name');
495 |
496 | // child.index = children.push(child) - 1;
497 | // child.parentControl = self;
498 |
499 | if (isFinite(index)) {
500 | child.index = index;
501 |
502 | children.forEach(function(iterChild) {
503 | if (iterChild.index >= index) {
504 | iterChild.index++;
505 | }
506 | });
507 |
508 | children.splice(index, 0, child);
509 | } else {
510 | child.index = children.push(child) - 1;
511 | }
512 |
513 | if (name && !isFinite(name)) {
514 | name = css2dom(name);
515 |
516 | if (!hasOwn.call(children, name)) {
517 | children[name] = child;
518 | } else {
519 | debug('duplicates named control ', child, ' of ',
520 | self, ' parent', child.view, children[name]);
521 | // throw new Error();
522 | }
523 | }
524 |
525 | e.stopPropagation(); // fire only for first parent
526 | });
527 |
528 | // after all call event -- new child
529 | if (parent) {
530 | events.fire(parent.view, exports.events.childControl, this, index);
531 | }
532 |
533 | uiControl(view, this);
534 | } else {
535 | debug('warning: wrong control tree position', view);
536 | // throw new Error();
537 | }
538 | }
539 | });
540 |
541 |
542 | controls.element.prototype = {
543 | type: 'element',
544 | get: function getProperty() {
545 | return accessors(this, 'get', arguments);
546 | },
547 | set: function setProperty() {
548 | return accessors(this, 'set', arguments);
549 | },
550 | detach: function() {
551 | if (this.get('_attachMarker') || !this.view.parentNode) return false;
552 |
553 | var marker = document.createComment('attach marker: ' + this.get('id'));
554 |
555 | this.view.parentNode.replaceChild(marker, this.view);
556 | events.fire(this.view, exports.events.detach);
557 |
558 | return this.set('_attachMarker', marker);
559 | },
560 | attach: function() {
561 | var marker = this.get('_attachMarker');
562 |
563 | if (!marker) return false;
564 |
565 | if (!marker.parentNode) {
566 | throw new Error('Cannot attach back control to tree without marker in');
567 | }
568 |
569 | marker.replace(this.view);
570 | events.fire(this.view, exports.events.attach);
571 |
572 | this.set('_attachMarker', null);
573 |
574 | return true;
575 | },
576 | task: function(fn, delay) {
577 | var timer,
578 | self = this,
579 | removeHandler = function() {
580 | clearTimeout(timer);
581 | };
582 |
583 | events.on(self.view, exports.events.destroy, removeHandler);
584 |
585 | timer = setTimeout(function() {
586 | if (self.zombie) {
587 | console.warn('fired control task after control became zombie');
588 | return;
589 | }
590 |
591 | events.remove(self.view, exports.events.destroy, removeHandler);
592 | fn.call(self);
593 | }, delay || 1);
594 | },
595 | frame: function(fn) {
596 | var frame = {
597 | fn: fn
598 | };
599 |
600 |
601 | },
602 | remove: function() {
603 | this.destroy({
604 | remove: true,
605 | onlyChildren: false
606 | });
607 | },
608 | destroy: function(options) {
609 | options = options || {};
610 |
611 | if (!options.onlyChildren) {
612 | events.fire(this.view, exports.events.destroy, options);
613 | } else if (!options.remove) {
614 | events.fire(this.view, exports.events.destroyChildren, options);
615 | }
616 |
617 | if (options.remove) {
618 | events.fire(this.view, exports.events.remove, options);
619 | }
620 |
621 | destroy.call(this, options);
622 | }
623 | };
624 |
625 | [
626 | 'addEventListener',
627 | 'removeEventListener',
628 | 'dispatchEvent'
629 | ].forEach(function(key) {
630 | this[key] = function(event, fn, capture) {
631 | var view = this.view;
632 |
633 | if (view) {
634 | return key === 'dispatchEvent' ?
635 | view[key].call(view, event) :
636 | view[key].call(view, event, fn, capture);
637 | }
638 | };
639 | }, controls.element.prototype);
640 |
641 | var properties = {
642 | hidden: {
643 | get: function(control, name) {
644 | /*if ((cache = lib.cache(control.view)) && name in cache) {
645 | return cache[name];
646 | }*/
647 |
648 | var display = window.getComputedStyle(control.view).display,
649 | //hiddenValue = control.view.hidden,
650 | //style = control.view.style,
651 | hidden = false;
652 |
653 | if (display === 'none') {
654 | hidden = true;
655 | }
656 |
657 | return hidden;
658 | },
659 | set: function(control, name, value) {
660 | // value = !!value; // to boolean
661 |
662 | var hidden = this.get(control, name),
663 | view = control.view,
664 | hiddenValue = view.hidden,
665 | display,
666 | style,
667 | cache = uiCache(view),
668 | computed,
669 | lastDisplay;
670 |
671 | if (value && !hidden) {
672 | cache[name + '_lastDisplay'] =
673 | display = (style = view.style).display;
674 |
675 | style.display = 'none';
676 |
677 | hidden = true;
678 |
679 | events.fire(view, exports.events.hide);
680 | } else if (!value && hidden) {
681 | display = (style = control.view.style).display;
682 | lastDisplay = cache[name + '_lastDisplay'] || '';
683 |
684 | if (display !== 'none' && hiddenValue) {
685 | view.hidden = false;
686 | } else if (display === 'none') {
687 | style.display = lastDisplay ? lastDisplay : '';
688 | display = '';
689 | }
690 |
691 | hidden = this.get(control, name);
692 |
693 | if (hidden) {
694 | style.display = (display ? display : 'block') + ' !important';
695 | hidden = false;
696 | }
697 |
698 | events.fire(control.view, exports.events.show);
699 | }
700 |
701 | cache[name] = hidden;
702 |
703 | return hidden;
704 | }
705 | },
706 | attached: {
707 | get: function(control) {
708 | return !control.get('_attachMarker');
709 | }
710 | },
711 | child: {
712 | get: function(control, name, type, callback) {
713 | return getControl.call(control, type, callback, 1);
714 | }
715 | },
716 | capture: {
717 | get: function(control, name, key) {
718 | var capture = control.capture;
719 |
720 | do {
721 | if (hasOwn.call(capture, key)) {
722 | return capture[key];
723 | }
724 | } while ((control = control.parent) && (capture = control.capture));
725 | },
726 | set: function(control, name, key, value) {
727 | control.capture[key] = value;
728 | }
729 | },
730 | state: {
731 | type: DEFAULT_TYPE,
732 | set: function(control, name, state, params) {
733 | control.set(this.type + ':' + name, state);
734 | control.set(DEFAULT_TYPE + ':' + name, state);
735 |
736 | if (!params || !params.silent) {
737 | events.fire(control, exports.events.changeState, params);
738 | }
739 |
740 | return state;
741 | }
742 | }
743 | };
744 |
745 | properties[DEFAULT_PROP] = DEFAULT_TYPE;
746 |
747 | extend(controls.element, {
748 | properties: properties
749 | });
--------------------------------------------------------------------------------
/shared/fw/cui/modules.js:
--------------------------------------------------------------------------------
1 | ;(function initModules(window, modules) {
2 | "use strict";
3 |
4 | if (modules.inited) return;
5 |
6 | if (typeof window.console === 'undefined') {
7 | window.console = {};
8 |
9 | window.console.log =
10 | window.console.debug =
11 | window.console.dir =
12 | window.console.inspect =
13 | window.console.info =
14 | window.console.error =
15 | window.console.time =
16 | window.console.timeEnd = function() {};
17 | }
18 |
19 | var apply = Function.prototype.apply;
20 |
21 | // window.debug = apply.bind(console.log, console);
22 | window.debug = function() {
23 | apply.call(console.log, console, arguments);
24 | };
25 |
26 | var setStorageItem = function(key, value) {
27 | if (!window.localStorage || !localStorage.setItem) {
28 | debug('warn: no local storage');
29 | return true;
30 | }
31 |
32 | try {
33 | localStorage.setItem(key, value);
34 | return true;
35 | } catch (e) {
36 | return false;
37 | }
38 | },
39 | isArray = Array.isArray,
40 | isObj = function(val) {
41 | return val && !isArray(val) &&
42 | // bad regexp checking
43 | // but better than monkey checking
44 | typeof val === 'object' && !(val instanceof RegExp);
45 | };
46 |
47 | var list = {},
48 | pages = {},
49 | loader = modules.loader,
50 | hasOwn = {}.hasOwnProperty,
51 | caching = loader.cache !== false;
52 |
53 | var callReadyHandlers = function() {
54 | var readyList = modules.readyList;
55 |
56 | modules.readyList = null;
57 | modules.ready = call;
58 |
59 | readyList.forEach(call);
60 | },
61 | call = function(fn) {
62 | fn();
63 | };
64 |
65 | modules.loader = null;
66 | modules.inited = true;
67 |
68 | modules.load = function(loader) {
69 | if (!loader) return;
70 |
71 | var packaged = loader.packaged,
72 | deps = loader.deps;
73 |
74 | var loadPackage = function(url, loadedModules) {
75 | var diffDeps = caching ? deps.filter(function(key) {
76 | return !(hasOwn.call(loadedModules, key));
77 | }) : deps.concat();
78 |
79 | var end = function(needSave) {
80 | loading.forEach(function(mod) {
81 | modules.execute(mod);
82 | });
83 |
84 | callReadyHandlers();
85 |
86 | caching && needSave && setTimeout(function() {
87 | modules.saveModules();
88 | }, 0);
89 | };
90 |
91 | if (!diffDeps.length) {
92 | end();
93 | return;
94 | }
95 |
96 | var newLoader = {
97 | deps: diffDeps
98 | };
99 |
100 | Object.keys(loader).forEach(function(key) {
101 | if (key !== 'deps') {
102 | newLoader[key] = loader[key];
103 | }
104 | });
105 |
106 | url = url.replace(modules.R_EVAL, function(input, key) {
107 | return (new Function('loader', 'with(loader) {(' +
108 | newLoader[key] + ')}'))(newLoader);
109 | });
110 |
111 | var first = document.querySelector('script'),
112 | script = document.createElement('script');
113 |
114 | script.src = url;
115 | script.async = true;
116 |
117 | setTimeout(function() {
118 | first.parentNode.insertBefore(script, first);
119 | }, 1);
120 | };
121 |
122 | if (packaged) {
123 | modules.loadModules(function(loadedModules) {
124 | loadPackage(packaged, loadedModules);
125 | });
126 |
127 | return;
128 | }
129 |
130 | if (loader.optimized) {
131 | modules.loadModules(function(loadedModules) {
132 | loadPackage(loader.url, loadedModules);
133 | });
134 |
135 | return;
136 | }
137 |
138 | var splitPath = function(path) {
139 | var split = path.match(/(?:^|\/)([^\/]+)\.\w+?(?:\?(\d*))?$/);
140 |
141 | if (!split) return {};
142 |
143 | var name = split[1],
144 | version = split[2];
145 |
146 | if (!isFinite(version)) {
147 | version = void 0;
148 | } else {
149 | version = +version;
150 | }
151 |
152 | return {
153 | name: name,
154 | version: version
155 | };
156 | },
157 | pacakgeDeps = typeof loader.package === 'function' ?
158 | loader.package : function(deps) {
159 | if (isArray(deps)) {
160 | return deps.map(function(dep) {
161 | if (isObj(dep)) {
162 | return {
163 | file: dep.file,
164 | name: dep.name,
165 | version: dep.version
166 | };
167 | } else {
168 | var split = splitPath(dep);
169 |
170 | return {
171 | file: dep,
172 | name: split.name,
173 | version: split.version
174 | };
175 | }
176 | });
177 | } else {
178 | return Object.keys(deps).map(function(key) {
179 | var dep = deps[key];
180 |
181 | return {
182 | file: key,
183 | name: dep.name,
184 | version: dep.version
185 | };
186 | });
187 | }
188 | };
189 |
190 | if (loader.debug) {
191 | (function() {
192 | var loading = pacakgeDeps(deps),
193 | first = document.querySelector('script');;
194 |
195 | var loadNext = function() {
196 | if (!loading.length) {
197 | callReadyHandlers();
198 | return;
199 | }
200 |
201 | var dep = loading.shift(),
202 | file = dep.file,
203 | script = document.createElement('script');
204 |
205 | script.src = (loader.path || '') + file;
206 | script.onload = function() {
207 | loadNext();
208 | };
209 |
210 | setTimeout(function() {
211 | first.parentNode.insertBefore(script, first);
212 | }, 1);
213 | };
214 |
215 | loadNext();
216 | }());
217 |
218 | return;
219 | }
220 |
221 | modules.loadModules(function(loadedModules) {
222 | var end = function() {
223 | loading.forEach(function(mod) {
224 | modules.execute(mod);
225 | modules.addModule(mod);
226 | });
227 |
228 | callReadyHandlers();
229 |
230 | caching && setTimeout(function() {
231 | modules.saveModules();
232 | }, 0);
233 | };
234 |
235 | var loadedLength = 0,
236 | hasPrending;
237 |
238 | var loading = pacakgeDeps(deps).map(function(dep) {
239 | var file = dep.file,
240 | name = dep.name,
241 | version = dep.version;
242 |
243 | useCache: if (caching && hasOwn.call(loadedModules, name)) {
244 | var loaded = loadedModules[name];
245 |
246 | if (loaded.version != version) {
247 | delete loadedModules[name];
248 | break useCache;
249 | }
250 |
251 | return loaded;
252 | }
253 |
254 | var xhr = new XMLHttpRequest(),
255 | mod = {
256 | name: name,
257 | version: version
258 | };
259 |
260 | if (!hasPrending) {
261 | hasPrending = true;
262 | }
263 |
264 | xhr.open('GET', (loader.path || '') + file, true);
265 | xhr.overrideMimeType('text/plain; charset="utf-8"');
266 | xhr.responseType = 'text';
267 |
268 | xhr.onload = function() {
269 | mod.code = this.responseText;
270 |
271 | if (++loadedLength >= loading.length) {
272 | end();
273 | }
274 | };
275 |
276 | setTimeout(function() {
277 | xhr.send();
278 | }, 1);
279 |
280 | return mod;
281 | });
282 |
283 | if (!hasPrending) {
284 | end();
285 | }
286 | });
287 | };
288 |
289 | var extend = {
290 | packagedCallback: function(mods) {
291 | var end = function() {
292 | callReadyHandlers();
293 |
294 | setTimeout(function() {
295 | modules.saveModules();
296 | }, 0);
297 | };
298 |
299 | if (!isArray(mods)) {
300 | end();
301 | return;
302 | }
303 |
304 | mods.forEach(function(mod) {
305 | modules.execute(mod);
306 | modules.addModule(mod);
307 | });
308 |
309 | end();
310 | },
311 | handleModule: function(name, obj) {
312 | list[name] = obj;
313 | obj.exports.__moduleName__ = name;
314 | return obj;
315 | },
316 | require: function(name) {
317 | if (typeof name !== 'string') throw new TypeError('Bad argument');
318 | return hasOwn.call(list, name) ? list[name].exports : null;
319 | },
320 | define: function(name, fn, version) {
321 | if (typeof name !== 'string' || typeof fn !== 'function') return;
322 |
323 | var module = Object.create(null, {
324 | name: {
325 | get: function() {
326 | return name;
327 | }
328 | },
329 | version: {
330 | get: function() {
331 | return version
332 | }
333 | },
334 | exports: (function() {
335 | var exports = {};
336 |
337 | return {
338 | get: function() {
339 | return exports;
340 | },
341 | set: function(val) {
342 | if (!isObj(val)) {
343 | return;
344 | }
345 |
346 | exports = val;
347 | }
348 | }
349 | }())
350 | }),
351 | exports = module.exports;
352 |
353 | modules.push();
354 |
355 | var result = fn.call(
356 | window,
357 | modules.require,
358 | modules,
359 | module,
360 | exports
361 | );
362 |
363 | // debugger;
364 |
365 | if (result && result !== exports &&
366 | module.exports === exports && isObj(result)) {
367 | module.exports = result;
368 | }
369 |
370 | exports = result = null;
371 |
372 | modules.handleModule(name, module);
373 | modules.pop();
374 |
375 | return module;
376 | },
377 | getList: function() {
378 | return list;
379 | },
380 | execute: function(mod) {
381 | var name = mod && mod.name,
382 | code = mod && mod.code,
383 | version = mod && mod.version;
384 |
385 | if (!mod || !code || hasOwn.call(list, mod.name)) {
386 | return false;
387 | }
388 |
389 | var args = [
390 | 'require',
391 | 'modules',
392 | 'module',
393 | 'exports'
394 | ].join(','),
395 | code = [
396 | '"use strict";',
397 | modules.evalGlobalRequire(),
398 | code,
399 | ';\rreturn exports;'
400 | ].join('');
401 |
402 | if (modules.evalScriptTag) {
403 | var script = document.createElement('script'),
404 | body = [
405 | '(function() {',
406 | 'var fn = function(' + args + ') {' + code + '};',
407 | 'modules.define("' + mod.name + '", fn, ' + version + ');',
408 | '}());'
409 | ].join('');
410 |
411 | script.textContent = body;
412 | document.head.appendChild(script);
413 | } else {
414 | var fn = new Function(args, code);
415 | modules.define(mod.name, fn, version);
416 | }
417 |
418 | return true;
419 | },
420 | getModule: function(name) {
421 | return hasOwn.call(list, name) ? list[name] : null;
422 | },
423 | addModule: function(mod, callback) {
424 | modules.loadModules(function(loadedModules) {
425 | if (!hasOwn.call(loadedModules, mod.name)) {
426 | loadedModules[mod.name] = mod;
427 | }
428 |
429 | if (callback) {
430 | callback();
431 | }
432 | });
433 | },
434 | loadModules: function(callback) {
435 | var loadedModules = modules.loadedModules;
436 |
437 | if (loadedModules) {
438 | callback(loadedModules);
439 | return;
440 | }
441 |
442 | var error = function() {
443 | callback(modules.loadedModules = {});
444 | };
445 |
446 | storage.get(modules.STORAGE_VERSION_KEY, function(version) {
447 | if (+loader.version !== +version) {
448 | storage.remove(modules.STORAGE_VERSION_KEY);
449 | storage.remove(modules.STORAGE_CODE_KEY);
450 | error();
451 | return;
452 | }
453 |
454 | storage.get(modules.STORAGE_CODE_KEY, function(mods) {
455 | if (isObj(mods)) {
456 | modules.loadedModules = mods;
457 | callback(mods);
458 | } else {
459 | error();
460 | }
461 | }, error);
462 | }, error);
463 | },
464 | saveModules: function(callback, errback) {
465 | storage.set(modules.STORAGE_VERSION_KEY, loader.version);
466 |
467 | storage.set(
468 | modules.STORAGE_CODE_KEY,
469 | modules.loadedModules,
470 | callback,
471 | errback
472 | );
473 | },
474 | push: function() {},
475 | pop: function() {},
476 | clearCache: function() {
477 | localStorage.removeItem(modules.LOADER_MODULES);
478 | localStorage.removeItem(modules.LOADER_VERSION);
479 | storage.remove(modules.STORAGE_VERSION_KEY);
480 | storage.remove(modules.STORAGE_CODE_KEY);
481 | },
482 | useGlobals: function() {
483 | var global = modules.globalRequire,
484 | keys = Object.keys(global);
485 |
486 | if (keys.length) {
487 | keys.forEach(function(key) {
488 | if (modules.globalsUsed[key]) return;
489 | modules.globalsUsed[key] = window[key] = modules.require(global[key]);
490 | });
491 | }
492 | },
493 | evalGlobalRequire: function() {
494 | var global = modules.globalRequire,
495 | keys = Object.keys(global),
496 | code = ';';
497 |
498 | if (keys.length) {
499 | keys.forEach(function(key) {
500 | code += 'var ' + key + ' = require("' + global[key] + '");';
501 | });
502 | }
503 |
504 | return code;
505 | },
506 |
507 | globalsUsed: {},
508 | globalRequire: {},
509 | loadedModules: null,
510 | STORAGE_CODE_KEY: '_storage_modules_code_',
511 | STORAGE_VERSION_KEY: '_storage_modules_version_'
512 | };
513 |
514 | for (var prop in extend) {
515 | if (hasOwn.call(extend, prop)) {
516 | modules[prop] = extend[prop];
517 | }
518 | }
519 |
520 | var source = 'modules.fromCache = true; (' + initModules + '(this, modules))';
521 |
522 | caching && setTimeout(function() {
523 | setStorageItem(modules.LOADER_MODULES, source);
524 | setStorageItem(modules.LOADER_VERSION, loader.version);
525 | });
526 |
527 | modules.define('_storage', defineStorage);
528 | var storage = modules.require('_storage');
529 |
530 | if (loader.optimized) {
531 | window[modules.PACKAGED_CALLBACK] = function(mods) {
532 | window[modules.PACKAGED_CALLBACK] = null;
533 | modules.packagedCallback(mods);
534 | };
535 | }
536 |
537 | if (loader && !loader.optimized || modules.fromCache) {
538 | modules.load(loader);
539 | }
540 |
541 | // Code from LocalForge library
542 | // https://github.com/mozilla/localForage/blob/master/LICENSE
543 | // Copyright 2014 Mozilla
544 | // Licensed under the Apache License, Version 2.0
545 |
546 | function defineStorage(require, modules, module, exports) {
547 | // Initialize IndexedDB; fall back to vendor-prefixed versions if needed.
548 | var indexedDB = window.indexedDB || window.webkitIndexedDB ||
549 | window.mozIndexedDB || window.msIndexedDB;
550 |
551 | module.exports = indexedDB ? initIDBStorage(indexedDB) : initLocalStorage();
552 | }
553 |
554 | function initIDBStorage(indexedDB) {
555 | // Originally found in https://github.com/mozilla-b2g/gaia/blob/e8f624e4cc9ea945727278039b3bc9bcb9f8667a/shared/js/async_storage.js
556 |
557 | var db = null,
558 | exports = {};
559 |
560 | var DBNAME = '_mod_storage_',
561 | DBVERSION = 1,
562 | STORENAME = 'keyvaluepairs';
563 |
564 | function withStore(type, f, reject) {
565 | if (db) {
566 | f(db.transaction(STORENAME, type).objectStore(STORENAME));
567 | } else {
568 | var openreq = indexedDB.open(DBNAME, DBVERSION);
569 |
570 | if (reject) {
571 | openreq.onerror = function withStoreOnError() {
572 | reject(openreq.error);
573 | };
574 | }
575 |
576 | openreq.onupgradeneeded = function withStoreOnUpgradeNeeded() {
577 | // First time setup: create an empty object store
578 | openreq.result.createObjectStore(STORENAME);
579 | };
580 |
581 | openreq.onsuccess = function withStoreOnSuccess() {
582 | db = openreq.result;
583 | f(db.transaction(STORENAME, type).objectStore(STORENAME));
584 | };
585 | }
586 | }
587 |
588 | function getItem(key, callback, errback) {
589 | withStore('readonly', function getItemBody(store) {
590 | var req = store.get(key);
591 |
592 | req.onsuccess = function getItemOnSuccess() {
593 | var value = req.result;
594 |
595 | if (value === undefined) {
596 | value = null;
597 | }
598 |
599 | if (callback) {
600 | callback(value);
601 | }
602 | };
603 |
604 | if (errback) {
605 | req.onerror = function getItemOnError() {
606 | errback(req.error);
607 | };
608 | }
609 | }, errback);
610 | }
611 |
612 | function setItem(key, value, callback, errback) {
613 | withStore('readwrite', function setItemBody(store) {
614 | // Cast to undefined so the value passed to callback/promise is
615 | // the same as what one would get out of `getItem()` later.
616 | // This leads to some weirdness (setItem('foo', undefined) will
617 | // return "null"), but it's not my fault localStorage is our
618 | // baseline and that it's weird.
619 | if (value === undefined) {
620 | value = null;
621 | }
622 |
623 | var req = store.put(value, key);
624 |
625 | req.onsuccess = function setItemOnSuccess() {
626 | if (callback) {
627 | callback(value);
628 | }
629 | };
630 |
631 | if (errback) {
632 | req.onerror = function setItemOnError() {
633 | errback(req.error);
634 | };
635 | }
636 | }, errback);
637 | }
638 |
639 | function removeItem(key, callback, errback) {
640 | withStore('readwrite', function removeItemBody(store) {
641 | var req = store.delete(key);
642 |
643 | req.onsuccess = function removeItemOnSuccess() {
644 | if (callback) {
645 | callback();
646 | }
647 | };
648 |
649 | if (errback) {
650 | req.onerror = function removeItemOnError() {
651 | errback(req.error);
652 | };
653 | }
654 | });
655 | }
656 |
657 | return {
658 | get: getItem,
659 | set: setItem,
660 | remove: removeItem
661 | };
662 | }
663 |
664 | function initLocalStorage() {
665 | var localStorage = null,
666 | exports = {};
667 |
668 | // If the app is running inside a Google Chrome packaged webapp, or some
669 | // other context where localStorage isn't available, we don't use
670 | // localStorage. This feature detection is preferred over the old
671 | // `if (window.chrome && window.chrome.runtime)` code.
672 | // See: https://github.com/mozilla/localForage/issues/68
673 | try {
674 | // Initialize localStorage and create a variable to use throughout
675 | // the code.
676 | localStorage = window.localStorage;
677 | } catch (e) {
678 | var noop = function() {};
679 | return {
680 | get: noop,
681 | set: noop,
682 | remove: noop
683 | };
684 | }
685 |
686 | // Retrieve an item from the store. Unlike the original async_storage
687 | // library in Gaia, we don't modify return values at all. If a key's value
688 | // is `undefined`, we pass that value to the callback function.
689 | function getItem(key, callback, errback) {
690 | try {
691 | var result = localStorage.getItem(key);
692 |
693 | // If a result was found, parse it from serialized JSON into a
694 | // JS object. If result isn't truthy, the key is likely
695 | // undefined and we'll pass it straight to the callback.
696 | if (result) {
697 | result = JSON.parse(result);
698 | }
699 | } catch (e) {
700 | errback(e);
701 | return;
702 | }
703 |
704 | if (callback) {
705 | callback(result);
706 | }
707 | }
708 |
709 | // Remove an item from the store, nice and simple.
710 | function removeItem(key, callback) {
711 | localStorage.removeItem(key);
712 |
713 | if (callback) {
714 | callback();
715 | }
716 | }
717 |
718 | // Set a key's value and run an optional callback once the value is set.
719 | // Unlike Gaia's implementation, the callback function is passed the value,
720 | // in case you want to operate on that value only after you're sure it
721 | // saved, or something like that.
722 | function setItem(key, value, callback, errback) {
723 | // Convert undefined values to null.
724 | // https://github.com/mozilla/localForage/pull/42
725 | if (value === undefined) {
726 | value = null;
727 | }
728 |
729 | // Save the original value to pass to the callback.
730 | var originalValue = value;
731 |
732 | try {
733 | value = JSON.stringify(value);
734 | } catch (e) {
735 | errback(e);
736 | }
737 |
738 | localStorage.setItem(key, value);
739 |
740 | if (callback) {
741 | callback(originalValue);
742 | }
743 | }
744 |
745 | return {
746 | get: getItem,
747 | set: setItem,
748 | remove: removeItem
749 | };
750 | }
751 | }(this, modules));
--------------------------------------------------------------------------------
/shared/promises-panel.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | var reloadButton = document.getElementById('reload'),
3 | attachButton = document.getElementById('attach'),
4 | clearButton = document.getElementById('clear'),
5 | toggleAttach = document.getElementById('toggle-attach'),
6 | settingsButton = document.getElementById('settings-button');
7 |
8 | var isChrome = typeof chrome !== 'undefined';
9 |
10 | reloadButton.addEventListener('click', function() {
11 | sendServiceAction('reload_and_attach');
12 | toggleAttach.setAttribute('selected', '');
13 | });
14 |
15 | attachButton.addEventListener('click', function() {
16 | doAttach();
17 | });
18 |
19 | clearButton.addEventListener('click', function() {
20 | doClear();
21 | });
22 |
23 | toggleAttach.addEventListener('click', function() {
24 | var selected = this.hasAttribute('selected');
25 |
26 | if (!selected) {
27 | doAttach();
28 | } else {
29 | doDetach();
30 | }
31 | });
32 |
33 | settingsButton.addEventListener('click', function() {
34 | var settings = document.getElementById('settings');
35 |
36 | settings.hidden = false;
37 | settings.querySelector('.close').onclick = function() {
38 | this.onclick = null;
39 | settings.hidden = true;
40 | };
41 | });
42 |
43 | var doAttach = function() {
44 | sendServiceAction('attach');
45 | toggleAttach.setAttribute('selected', '');
46 | },
47 | doDetach = function() {
48 | sendServiceAction('detach');
49 | toggleAttach.removeAttribute('selected');
50 | };
51 |
52 | var createPromiseRow = function() {
53 | var item = document.createElement('div'),
54 | cont = document.createElement('div'),
55 | name = document.createElement('div'),
56 | status = document.createElement('div'),
57 | value = document.createElement('div'),
58 | id = document.createElement('div'),
59 | extend = document.createElement('div'),
60 | chain = document.createElement('div');
61 |
62 | item.className = 'pd-table-row';
63 | cont.className = 'pd-table-row-cont';
64 |
65 | name.className = 'pd-table-cell';
66 | id.className = 'pd-table-cell';
67 | status.className = 'pd-table-cell';
68 | value.className = 'pd-table-cell';
69 | chain.className = 'pd-table-cell';
70 |
71 | extend.className = 'pd-table-extend';
72 |
73 | id.classList.add('cell-id');
74 |
75 | item.appendChild(cont);
76 | item.appendChild(extend);
77 |
78 | cont.appendChild(id);
79 | cont.appendChild(name);
80 | cont.appendChild(status);
81 | cont.appendChild(value);
82 | cont.appendChild(chain);
83 |
84 | return {
85 | chain: chain,
86 | extend: extend,
87 | cont: cont,
88 | item: item,
89 | name: name,
90 | status: status,
91 | value: value,
92 | id: id
93 | };
94 | },
95 | toggleExtendBlock = function(extend, block) {
96 | var currentBlock = extend.currentBlock;
97 |
98 | if (currentBlock) {
99 | extend.removeChild(currentBlock);
100 | }
101 |
102 | if (currentBlock !== block) {
103 | extend.appendChild(block);
104 | extend.currentBlock = block;
105 | } else {
106 | extend.currentBlock = null;
107 | }
108 | },
109 | checkTbody = function(tbody) {
110 | if (tbody.childElementCount) {
111 | tbody.hidden = false;
112 | } else {
113 | tbody.hidden = true;
114 | }
115 | },
116 | extractUrl = function(input) {
117 | var R_URL = /((?:\w+?\:\/\/)[\s\S]*?):(\d+):(\d+)/g;
118 | var R_FX_ANONYMOUR_URL = /((?:\w+?\:\/\/)[\s\S]*?) line (\d+) > (?:[\s\S]*)/g;
119 |
120 | var urlMatch,
121 | usedReg;
122 |
123 | while (urlMatch = R_FX_ANONYMOUR_URL.exec(input)) {
124 | usedReg = R_FX_ANONYMOUR_URL;
125 | break;
126 | }
127 |
128 | if (!urlMatch) {
129 | while (urlMatch = R_URL.exec(input)) {
130 | usedReg = R_URL;
131 | break;
132 | }
133 | }
134 |
135 | if (urlMatch) {
136 | return {
137 | match: urlMatch,
138 | usedReg: usedReg
139 | };
140 | } else {
141 | return null;
142 | }
143 | },
144 | parseAndGerRerouceLink = function(input, url) {
145 | if (!url) {
146 | url = extractUrl(input);
147 | }
148 |
149 | var urlMatch = url && url.match,
150 | usedReg = url && url.usedReg;
151 |
152 | if (urlMatch) {
153 | var a = document.createElement('a'),
154 | url = urlMatch[0],
155 | prefix = input.slice(0, usedReg.lastIndex - url.length),
156 | postfix = input.slice(usedReg.lastIndex);
157 |
158 | a.className = 'resource-link';
159 | a.textContent = url;
160 | a.href = url;
161 | a.addEventListener('click', function(e) {
162 | e.preventDefault();
163 | e.stopPropagation();
164 |
165 | sendServiceAction('open_resource', {
166 | file: urlMatch[1],
167 | line: urlMatch[2],
168 | col: urlMatch[3]
169 | });
170 | });
171 | }
172 |
173 | var span = document.createElement('span');
174 |
175 | if (urlMatch) {
176 | span.appendChild(document.createTextNode(prefix));
177 | span.appendChild(a);
178 | span.appendChild(document.createTextNode(postfix));
179 | } else {
180 | span.textContent = input;
181 | }
182 |
183 | return span;
184 | },
185 | getNameFromStackOld = function(stack, i) {
186 | var lines = stack.split(/(?:\n+|\->)/),
187 | name,
188 | url;
189 |
190 | while (
191 | (name = lines[i]) && (name.indexOf('(native)') !== -1 ||
192 | name.indexOf('(:') !== -1) &&
193 | i < lines.length
194 | ) {
195 | ++i;
196 | }
197 |
198 | var resourceLink = parseAndGerRerouceLink(name);
199 |
200 | return resourceLink;
201 | },
202 | getNameFromStack = function(handledStack, i, name) {
203 | var stackName = handledStack.lines[0],
204 | url = extractUrl(stackName),
205 | urlMatch = url && url.match;
206 |
207 | if (name) {
208 | stackName += ' with ' + name;
209 | }
210 |
211 | var resourceLink = parseAndGerRerouceLink(stackName);
212 |
213 | return resourceLink;
214 | },
215 | handleStack = function(stack) {
216 | return handleEverStack(stack);
217 |
218 | if (isChrome) {
219 | return handleChromeStack(stack);
220 | } else {
221 | return handleFxStack(stack);
222 | }
223 | },
224 | handleEverStack = function(stack) {
225 | var lines = stack.split(/(?:\n+|\->)/),
226 | line,
227 | i = 0,
228 | newLines = [],
229 | firstLine = lines[0],
230 | message;
231 |
232 | if (isChrome && firstLine &&
233 | firstLine.search(/\bat\b/) === -1 && firstLine.search(/error/i) !== -1) {
234 | message = firstLine;
235 | lines = lines.slice(1);
236 | }
237 |
238 | if (!PromisesPanel.settings.show_full_stack) {
239 | while (i < lines.length) {
240 | line = lines[i];
241 | ++i;
242 |
243 | if (
244 | line && (
245 | line.indexOf('(native)') !== -1 ||
246 | line.indexOf('(:') !== -1 ||
247 | line.indexOf('resource://') !== -1 ||
248 | line.indexOf('jar:file://') !== -1
249 | )
250 | ) {
251 | continue;
252 | }
253 |
254 | if (line) {
255 | newLines.push(line);
256 | }
257 | }
258 | } else {
259 | newLines = lines;
260 | }
261 |
262 | if (!newLines.length) {
263 | return null;
264 | }
265 |
266 | return {
267 | lines: newLines,
268 | message: message
269 | };
270 | },
271 | prepend = function(container, child) {
272 | if (container.firstChild) {
273 | container.insertBefore(child, container.firstChild);
274 | } else {
275 | container.appendChild(child);
276 | }
277 | },
278 | doClear = function(force) {
279 | if (!force) {
280 | // stack not used promises for future use
281 | Object.keys(promises).forEach(function(key) {
282 | var promiseRecord = promisesStash[key] = promises[key];
283 |
284 | promiseRecord.row = null;
285 | });
286 | } else {
287 | promisesStash = {};
288 | }
289 |
290 | promises = {};
291 |
292 | [].slice.call(table.querySelectorAll('.pd-table-body')).forEach(function(tbody) {
293 | tbody.innerHTML = '';
294 | });
295 | },
296 | getTopLevelParent = function(promiseRecord) {
297 | while (promiseRecord.parent) {
298 | promiseRecord = promiseRecord.parent;
299 | }
300 |
301 | return promiseRecord;
302 | },
303 | sendServiceAction = function(action, message) {
304 | window.postMessage({
305 | serviceAction: action,
306 | message: message
307 | }, '*');
308 | };
309 |
310 | var table = document.getElementById('promises-table'),
311 | tBodies = table.querySelectorAll('.pd-table-body'),
312 | tbodyErrors = table.querySelector('.tbody-errors'),
313 | tbodyChainErrors = table.querySelector('.tbody-chain-errors'),
314 | tbodyPending = table.querySelector('.tbody-pending'),
315 | tbodySuccess = table.querySelector('.tbody-success');
316 |
317 | var promises = {},
318 | promisesStash = {};
319 |
320 | var actions = {
321 | show_need_reload: function() {
322 | var needReload = document.getElementById('need-reload'),
323 | content = document.getElementById('content');
324 |
325 | toggleAttach.removeAttribute('selected');
326 |
327 | needReload.hidden = false;
328 | content.hidden = true;
329 | },
330 | show_not_attached: function() {
331 | toggleAttach.removeAttribute('selected');
332 | },
333 | show_main: function() {
334 | var needReload = document.getElementById('need-reload'),
335 | content = document.getElementById('content');
336 |
337 | needReload.hidden = true;
338 | content.hidden = false;
339 | },
340 | update_data: function(message) {
341 | var event = message.event;
342 |
343 | if (dataUpdates.hasOwnProperty(event)) {
344 | dataUpdates[event](message);
345 | }
346 | },
347 | reload: function() {
348 | doClear(true);
349 | }
350 | },
351 | dataUpdates = {
352 | create: function(message) {
353 | var data = message.data;
354 |
355 | var topLevel = !!data.topLevel;
356 |
357 | var handledStack = data.handledStack = handleStack(data.stack);
358 |
359 | if (!handledStack) {
360 | // this is due this bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1085124
361 | // in short firefox calls Promise.then from native code with native
362 | // functions in the end promises chain (for debug?)
363 | return;
364 | }
365 |
366 | var row = createPromiseRow(),
367 | name = getNameFromStack(data.handledStack, 2, data.name),
368 | stackCont = document.createElement('div'),
369 | chainCont = document.createElement('div');
370 |
371 | var promiseRecord = promises[data.id] = {
372 | id: data.id,
373 | row: row,
374 | data: data,
375 | topLevel: topLevel,
376 | branches: [],
377 | _chaingLength: 0,
378 | get chaingLength() {
379 | return this._chaingLength;
380 | },
381 | set chaingLength(val) {
382 | var parentRecord = this.parent;
383 |
384 | this._chaingLength = val;
385 |
386 | if (parentRecord && parentRecord.chaingLength < val + 1) {
387 | parentRecord.chaingLength = val + 1;
388 | parentRecord.mostChaing = this;
389 | }
390 |
391 | if (this.branches.length > 1) {
392 | val = val + ' [' + this.branches.length + ']';
393 | }
394 |
395 | this.row.chain.textContent = val;
396 | },
397 | _mostChaing: null,
398 | set mostChaing(val) {
399 | this._mostChaing = val;
400 | },
401 | get mostChaing() {
402 | return this._mostChaing || this.branches[0] || null;
403 | }
404 | };
405 |
406 | if (!topLevel) {
407 | var parentRecord = promiseRecord.parent = promises[data.parentPromise];
408 |
409 | if (parentRecord) {
410 | parentRecord.branches.push(promiseRecord);
411 |
412 | if (!parentRecord.chaingLength) {
413 | parentRecord.chaingLength = 1;
414 | } else if (parentRecord.branches.length > 1) {
415 | parentRecord.row.chain.textContent = parentRecord.chaingLength +
416 | ' [' + parentRecord.branches.length + ']';
417 | }
418 | }
419 | }
420 |
421 | // chainCont.hidden = true;
422 | // row.extend.appendChild(chainCont)
423 |
424 | row.chain.style.cursor = 'pointer';
425 | row.chain.addEventListener('click', function(e) {
426 | if (!promiseRecord.chaingLength) return;
427 |
428 | e.preventDefault();
429 | e.stopPropagation();
430 |
431 | chainCont.innerHTML = '';
432 |
433 | var wrap = document.createElement('div');
434 |
435 | wrap.className = 'ui segment';
436 |
437 | var branches = document.createElement('div');
438 | branches.className = 'ui menu pd-branches';
439 |
440 | var branchesTitle = document.createElement('a');
441 | branchesTitle.className = 'item pd-branch-item pd-branches-title disabled';
442 | branchesTitle.textContent = 'Branches';
443 |
444 | branches.appendChild(branchesTitle);
445 |
446 | var lastActiveItem;
447 |
448 | promiseRecord.branches.forEach(function(promise, i) {
449 | var item = document.createElement('a');
450 | item.className = 'item pd-branch-item' +
451 | (promise === promiseRecord.mostChaing ? ' active' : '');
452 | item.textContent = (promise.chaingLength | 0) + 1;
453 | branches.appendChild(item);
454 |
455 | if (promise === promiseRecord.mostChaing) {
456 | lastActiveItem = item;
457 | }
458 |
459 | item.addEventListener('click', function() {
460 | if (item.classList.contains('active')) return;
461 |
462 | lastActiveItem.classList.remove('active');
463 | lastActiveItem = item;
464 | item.classList.add('active');
465 |
466 | drawBranch(promise);
467 | });
468 | });
469 |
470 | wrap.appendChild(branches);
471 |
472 | var branchTarget = document.createElement('div');
473 | wrap.appendChild(branchTarget);
474 |
475 | var drawBranch = function(useRecord) {
476 | branchTarget.innerHTML = '';
477 |
478 | do {
479 | branchTarget.appendChild(useRecord.row.item);
480 | } while (useRecord = useRecord.mostChaing);
481 | };
482 |
483 | drawBranch(promiseRecord.mostChaing);
484 |
485 | chainCont.appendChild(wrap);
486 |
487 | toggleExtendBlock(row.extend, chainCont);
488 | });
489 |
490 | // stackCont.hidden = true;
491 | stackCont.innerHTML = '';
492 | (function(cont) {
493 | // var stack = data.stack.split(/\n/).slice(1),
494 | var fragment = document.createDocumentFragment();
495 |
496 | handledStack.lines.forEach(function(line) {
497 | var resource = parseAndGerRerouceLink(line),
498 | div = document.createElement('div');
499 |
500 | div.appendChild(resource);
501 |
502 | fragment.appendChild(div);
503 | });
504 |
505 | cont.appendChild(fragment);
506 | }(stackCont.firstChild));
507 |
508 | // row.extend.appendChild(stackCont);
509 |
510 | row.name.style.cursor = 'pointer';
511 | row.name.addEventListener('click', function(e) {
512 | e.preventDefault();
513 | e.stopPropagation();
514 |
515 | toggleExtendBlock(row.extend, stackCont);
516 | // stackCont.hidden = !stackCont.hidden;
517 | });
518 |
519 | row.id.textContent = data.id;
520 | row.name.appendChild(name);
521 | row.status.textContent = 'pending';
522 | row.value.textContent = 'none'
523 | // row.chain.textContent = promiseRecord.chaingLength;
524 |
525 | // if (topLevel) {
526 | prepend(tbodyPending, row.item);
527 | checkTbody(tbodyPending);
528 | // }
529 | },
530 | value: function(message) {
531 | var data = message.data;
532 |
533 | var promise = promises[data.id];
534 |
535 | if (!promise || !promise.row) return;
536 |
537 | if (data.state === 'error') {
538 | promise.row.cont.classList.add('negative');
539 | promise.row.status.textContent = 'rejected';
540 |
541 | if (promise.topLevel) {
542 | prepend(tbodyErrors, promise.row.item);
543 | checkTbody(tbodyErrors);
544 | } else {
545 | var topLevelParent = getTopLevelParent(promise);
546 |
547 | if (topLevelParent.state !== 'error') {
548 | topLevelParent.row.cont.classList.remove('positive');
549 | topLevelParent.row.cont.classList.add('warning');
550 | prepend(tbodyChainErrors, topLevelParent.row.item);
551 | checkTbody(tbodyChainErrors);
552 | }
553 | }
554 | } else {
555 | promise.row.cont.classList.add('positive');
556 | promise.row.status.textContent = 'fullfiled';
557 |
558 | if (promise.topLevel) {
559 | prepend(tbodySuccess, promise.row.item);
560 | checkTbody(tbodySuccess);
561 | }
562 | }
563 |
564 | if (!promise.topLevel) {
565 | try {
566 | tbodyPending.removeChild(promise.row.item);
567 | checkTbody(tbodyPending);
568 | } catch (e) {}
569 | }
570 |
571 | promise.value = data.value;
572 | promise.state = data.state;
573 |
574 | var textVal,
575 | htmlVal;
576 |
577 | switch (data.value.type) {
578 | case 'primitive': {
579 | textVal = data.value.primitive + ': ' + data.value.value;
580 |
581 | var div = document.createElement('div');
582 |
583 | div.className = 'primitive-value';
584 | div.textContent = textVal;
585 |
586 | promise.row.value.innerHTML = '';
587 | promise.row.value.appendChild(div);
588 | }; break;
589 | case 'keys': {
590 | var keys = data.value.allKeys;
591 |
592 | textVal = 'Object: { ' + keys.join(', ') + ' }';
593 |
594 | var div = document.createElement('div');
595 |
596 | div.className = 'keys-value';
597 | div.textContent = textVal;
598 |
599 | promise.row.value.innerHTML = '';
600 | promise.row.value.appendChild(div);
601 | }; break;
602 | case 'object': {
603 | textVal = data.value.object;
604 | promise.row.value.textContent = textVal;
605 | }; break;
606 | case 'error': (function() {
607 | var handledStack = handleStack(data.value.error.stack),
608 | errMessage = (handledStack.message || data.value.error.message || 'Error:');
609 |
610 | var val = ' ' + errMessage + ' ',
611 | wrap = document.createElement('div'),
612 | errorCont = document.createElement('div');
613 |
614 | wrap.role = 'button';
615 | wrap.className = 'pd-show-error';
616 | wrap.innerHTML = val;
617 |
618 | wrap.appendChild(getNameFromStack(handledStack, 1));
619 |
620 | wrap.style.cursor = 'pointer';
621 | wrap.addEventListener('click', function(e) {
622 | e.preventDefault();
623 | e.stopPropagation();
624 |
625 | // errorCont.hidden = !errorCont.hidden;
626 | toggleExtendBlock(promise.row.extend, errorCont);
627 | });
628 |
629 | // errorCont.hidden = true;
630 | errorCont.innerHTML = '';
631 |
632 | (function(cont) {
633 | var fragment = document.createDocumentFragment();
634 |
635 | var firstDiv = document.createElement('div');
636 |
637 | firstDiv.textContent = errMessage;
638 | fragment.appendChild(firstDiv);
639 |
640 | handledStack.lines.forEach(function(line) {
641 | var resource = parseAndGerRerouceLink(line),
642 | div = document.createElement('div');
643 |
644 | div.style.marginLeft = '20px';
645 | div.appendChild(resource);
646 |
647 | fragment.appendChild(div);
648 | });
649 |
650 | cont.appendChild(fragment);
651 | }(errorCont.firstChild));
652 |
653 | // promise.row.extend.appendChild(errorCont);
654 |
655 | promise.row.value.innerHTML = '';
656 | promise.row.value.appendChild(wrap);
657 |
658 | promise.row.value.classList.add('error');
659 | }()); break;
660 | case 'function': {
661 | textVal = data.value.function;
662 | promise.row.value.textContent = textVal;
663 | }; break;
664 | default: {
665 | // textVal = JSON.stringify(data.value);
666 | textVal = data.value.type;
667 | promise.row.value.textContent = textVal;
668 | }
669 | }
670 | },
671 | shoot_toplevel: function(message) {
672 | var data = message.data;
673 | var promise = promises[data.id];
674 |
675 | console.log('shoot_toplevel', promise.topLevel);
676 |
677 | if (!promise || !promise.topLevel) return;
678 |
679 | promise.topLevel = false;
680 |
681 | var parentElement = promise.row.item.parentElement;
682 |
683 | if (parentElement) {
684 | parentElement.removeChild(promise.row.item);
685 | checkTbody(parentElement);
686 | }
687 | }
688 | };
689 |
690 | window.addEventListener('message', function(e) {
691 | var data = e.data;
692 |
693 | if (data && data.action && actions[data.action]) {
694 | actions[data.action](data.message);
695 | }
696 | });
697 |
698 | window.PromisesPanel = {
699 | updateSetting: function(setting, value) {
700 | var settingsActors = PromisesPanel.settingsActors;
701 |
702 | if (settingsActors.hasOwnProperty(setting)) {
703 | settingsActors[setting](value);
704 | }
705 | },
706 | settingsActors: {
707 | show_full_stack: function(value) {
708 | PromisesPanel.settings.show_full_stack = !!value;
709 | }
710 | },
711 | settings: {
712 | show_full_stack: false
713 | }
714 | };
715 | }());
--------------------------------------------------------------------------------