Mercurial > pub > ImplabJs
changeset 29:acdcdf1a8d21
repository reorganized
author | cin |
---|---|
date | Tue, 26 Jun 2018 19:35:44 +0300 |
parents | d796bbbe558c |
children | 2dfba21cd879 40d2e49a7219 |
files | .hgignore .project .settings/org.eclipse.buildship.core.prefs core/.project core/.settings/org.eclipse.buildship.core.prefs core/build.gradle core/history.md core/license core/package.json core/readme.md core/src/js/Deferred.js core/src/js/Uri.js core/src/js/Uuid.js core/src/js/components/ActivationController.js core/src/js/components/StateMachine.js core/src/js/components/_ActivatableMixin.js core/src/js/data/DataContext.js core/src/js/data/MapSchema.js core/src/js/data/ObjectStore.js core/src/js/data/RestStore.js core/src/js/data/StatefullStoreAdapter.js core/src/js/data/StoreAdapter.js core/src/js/data/_ModelBase.js core/src/js/data/_StatefulModelMixin.js core/src/js/data/declare-model.js core/src/js/declare.js core/src/js/declare/_load.js core/src/js/declare/override.js core/src/js/di/ActivationContext.js core/src/js/di/ActivationError.js core/src/js/di/Container.js core/src/js/di/Descriptor.js core/src/js/di/ReferenceDescriptor.js core/src/js/di/ServiceDescriptor.js core/src/js/di/ValueDescriptor.js core/src/js/log/ConsoleLogChannel.js core/src/js/log/_LogMixin.js core/src/js/log/listeners/console.js core/src/js/log/trace.js core/src/js/main.js core/src/js/messaging/Client.js core/src/js/messaging/Destination.js core/src/js/messaging/Listener.js core/src/js/messaging/Session.js core/src/js/safe.js core/src/js/text/format-compile.js core/src/js/text/format.js core/src/js/text/template-compile.js dom/.project dom/.settings/org.eclipse.buildship.core.prefs dom/build.gradle dom/package.json dom/src/js/css.js dom/src/js/inject.js npm/implab/index.js npm/implab/package.json settings.gradle src/djol/BaseLayer.js src/djol/ClearTool.js src/djol/CoordPickerTool.js src/djol/DeactivationTool.js src/djol/DistanceMeasureTool.js src/djol/DynamicStyle.js src/djol/IdentificationTool.js src/djol/IdentifyGroup.js src/djol/IdentifyItem.js src/djol/ImageLayer.js src/djol/ImageWMSSource.js src/djol/LayerCheckBox.js src/djol/LayerRadioButton.js src/djol/LayerSwitcher.js src/djol/Map.js src/djol/MeasureToolBase.js src/djol/OSMSource.js src/djol/OlTool.js src/djol/PopupContainer.js src/djol/SquareMeasureTool.js src/djol/TileLayer.js src/djol/TileWMSSource.js src/djol/ToolBoxController.js src/djol/ToolType.js src/djol/VectorLayer.js src/djol/VectorStore.js src/djol/VectorStoreQuery.js src/djol/WFSSource.js src/djol/_OneshotTool.js src/djol/_ToolBase.js src/djol/declare-style.js src/djol/format/coords.js src/djol/format/nls/coords.js src/djol/format/nls/ru/coords.js src/djol/format/nls/ru/units.js src/djol/format/nls/units.js src/djol/interaction/FeatureDrag.js src/djol/listen.js src/djol/main.js src/djol/ol-stub.js src/djol/resources/LayerCheckBoxTemplate.html src/djol/resources/LayerRadioButtonTemplate.html src/djol/resources/LayerSwitcherTemplate.html src/djol/resources/PopupContainerTemplate.html src/djol/resources/mapToolCheckBox.html src/implab/Deferred.js src/implab/Uri.js src/implab/Uuid.js src/implab/components/ActivationController.js src/implab/components/StateMachine.js src/implab/components/_ActivatableMixin.js src/implab/data/DataContext.js src/implab/data/MapSchema.js src/implab/data/ObjectStore.js src/implab/data/RestStore.js src/implab/data/StatefullStoreAdapter.js src/implab/data/StoreAdapter.js src/implab/data/_ModelBase.js src/implab/data/_StatefulModelMixin.js src/implab/data/declare-model.js src/implab/declare.js src/implab/declare/_load.js src/implab/declare/override.js src/implab/di/ActivationContext.js src/implab/di/ActivationError.js src/implab/di/Container.js src/implab/di/Descriptor.js src/implab/di/ReferenceDescriptor.js src/implab/di/ServiceDescriptor.js src/implab/di/ValueDescriptor.js src/implab/dom/css.js src/implab/dom/inject.js src/implab/guard.js src/implab/log/ConsoleLogChannel.js src/implab/log/_LogMixin.js src/implab/log/listeners/console.js src/implab/log/trace.js src/implab/messaging/Client.js src/implab/messaging/Destination.js src/implab/messaging/Listener.js src/implab/messaging/Session.js src/implab/safe.js src/implab/text/format-compile.js src/implab/text/format.js src/implab/text/template-compile.js src/utest/store/mock.js utest/src/js/utest/store/mock.js |
diffstat | 142 files changed, 4088 insertions(+), 6440 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Sat Jun 23 21:50:11 2018 +0300 +++ b/.hgignore Tue Jun 26 19:35:44 2018 +0300 @@ -1,2 +1,5 @@ .git/ .gitignore/ +syntax: glob +core/build/ +.gradle/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.project Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>implab</name> + <comment>Project implab created by Buildship.</comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.buildship.core.gradleprojectbuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.buildship.core.gradleprojectnature</nature> + </natures> +</projectDescription>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.settings/org.eclipse.buildship.core.prefs Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,2 @@ +connection.project.dir= +eclipse.preferences.version=1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/.project Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>core</name> + <comment>Project core created by Buildship.</comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.buildship.core.gradleprojectbuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.buildship.core.gradleprojectnature</nature> + </natures> +</projectDescription>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/.settings/org.eclipse.buildship.core.prefs Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,2 @@ +connection.project.dir=.. +eclipse.preferences.version=1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/build.gradle Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,19 @@ + +println "version: $version" + +task prepare(type: Copy) { + from('src') + from('.') { + include 'readme.md', 'license', 'history.md', 'package.json' + } + into(buildDir) +} + +task build(dependsOn: prepare) { +} + +task pack(dependsOn: build, type: Exec) { + workingDir = buildDir + + commandLine 'npm', 'pack' +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/history.md Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,12 @@ +HISTORY +======= + +1.0.1 +----- + +First release, intorduces the followinf features + +- `di` - dependency injection conyainer +- `log` - log4 style logging system +- `text` - simple and fast text templating and formatting +- `Uuid` - uuid generation traits \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/package.json Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,18 @@ +{ + "name": "@implab/core", + "version": "1.0.1", + "description": "Dependency injection, logging, simple and fast text template engine", + "main": "main.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "di", + "ioc", + "logging", + "template engine", + "dependency injection" + ], + "author": "Sergey Smirnov", + "license": "MIT" +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/Deferred.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,3 @@ +define(["dojo/Deferred"], function(Deferred) { + return Deferred; +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/Uri.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,232 @@ +define( + [ "./declare" ], + function(declare) { + function parseURI(uri) { + var schema, host, port, path, query, hash, i; + if (typeof (uri) == "string") { + if ((i = uri.indexOf(":")) >= 0 && + uri.substr(0, i).match(/^\w+$/)) { + schema = uri.substr(0, i); + uri = uri.substr(i + 1); + } + + if (uri.indexOf("//") === 0) { + uri = uri.substr(2); + if ((i = uri.indexOf("/")) >= 0) { + host = uri.substr(0, i); + uri = uri.substr(i); + } else { + host = uri; + uri = ""; + } + } + + if ((i = uri.indexOf("?")) >= 0) { + path = uri.substr(0, i); + uri = uri.substr(i + 1); + + } else { + path = uri; + uri = ""; + + if ((i = path.indexOf("#")) >= 0) { + hash = path.substr(i + 1); + path = path.substr(0, i); + } + } + + if ((i = uri.indexOf("#")) >= 0) { + query = uri.substr(0, i); + hash = uri.substr(i + 1); + } else { + query = uri; + } + } + + if (host && (i = host.lastIndexOf(":")) >= 0) { + port = host.substr(i + 1); + host = host.substr(0, i); + } + + return { + schema : schema, + host : host, + port : port, + path : path, + query : query, + hash : hash + }; + } + + function makeURI(options) { + var uri = []; + + if (options.schema) + uri.push(options.schema, ":"); + if (options.host) + uri.push("//", options.host); + if (options.host && options.port) + uri.push(":", options.port); + + if (options.path) { + if (options.host && options.path[0] != "/") + uri.push("/"); + uri.push(options.path); + } else if (options.host) { + uri.push("/"); + } + + if (options.query) + uri.push("?", options.query); + if (options.hash) + uri.push("#", options.hash); + + return uri.join(""); + } + + function reducePath(parts) { + var balance = 0, result = [], isRoot; + + for (var i = 0; i < parts.length; i++) { + var part = parts[i]; + switch (part) { + case "..": + if (balance > 0) { + result.pop(); + } else { + if (isRoot) + throw new Error("Unbalanced path: " + parts); + + result.push(part); + } + balance--; + break; + case ".": + break; + case "": + if (i === 0) { + isRoot = true; + result.push(part); + } + break; + default: + result.push(part); + balance++; + break; + } + } + + return result.join("/"); + } + + var meta = { + schema : null, + host : null, + port : null, + path : null, + query : null, + hash : null + }; + + var URI = declare(null, { + constructor : function(opts) { + if (typeof (opts) == "string") + opts = parseURI(opts); + for ( var p in meta) + if (p in opts) + this[p] = opts[p]; + }, + + clone : function() { + return new URI(this); + }, + + combine : function(rel) { + var me = this; + + if (typeof (rel) === "string") + rel = new URI(rel); + else + rel = rel.clone(); + + // //some.host:123/path?q=a#123 + if (rel.host) + return rel; + + // /abs/path?q=a#123 + if (rel.path && rel.path[0] == "/") { + if (me.host) { + rel.schema = me.schema; + rel.host = me.host; + rel.port = me.port; + } + return rel; + } + + var base = me.clone(); + + // rel/path?a=b#cd + if (rel.path) { + var segments = base.getSegments(); + segments.pop(); + segments.push.apply(segments, rel.getSegments()); + + base.path = reducePath(segments); + } + + // ?q=a#123 + if (rel.query) + base.query = rel.query; + if (rel.hash) + base.hase = rel.hash; + + return base; + }, + + optimize : function() { + this.path = reducePath(this.getSegments()); + }, + + getSegments : function() { + if (typeof (this.path) === "string") + return this.path.split("/"); + else + return []; + }, + + toString : function() { + var uri = [], me = this; + + if (me.schema) + uri.push(me.schema, ":"); + if (me.host) + uri.push("//", me.host); + if (me.host && me.port) + uri.push(":", me.port); + + if (me.path) { + if (me.host && me.path[0] != "/") + uri.push("/"); + uri.push(me.path); + } else if (me.host) { + uri.push("/"); + } + + if (me.query) + uri.push("?", me.query); + if (me.hash) + uri.push("#", me.hash); + + return uri.join(""); + } + + }); + + URI.combine = function(base, rel) { + if (typeof (base) === "string") + base = new URI(base); + return base.combine(rel).toString(); + }; + + return URI; + }); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/Uuid.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,278 @@ +// uuid.js +// +// Copyright (c) 2010-2012 Robert Kieffer +// MIT License - http://opensource.org/licenses/mit-license.php +define([], function () { + 'use strict'; + + var _window = 'undefined' !== typeof window ? window : null; + + // Unique ID creation requires a high quality random # generator. We + // feature + // detect to determine the best RNG source, normalizing to a function + // that + // returns 128-bits of randomness, since that's what's usually required + var _rng, _mathRNG, _nodeRNG, _whatwgRNG, _previousRoot; + + function setupBrowser() { + // Allow for MSIE11 msCrypto + var _crypto = _window.crypto || _window.msCrypto; + + if (!_rng && _crypto && _crypto.getRandomValues) { + // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto + // + // Moderately fast, high quality + try { + var _rnds8 = new Uint8Array(16); + _whatwgRNG = _rng = function whatwgRNG() { + _crypto.getRandomValues(_rnds8); + return _rnds8; + }; + _rng(); + } catch (e) { /**/ } + } + + if (!_rng) { + // Math.random()-based (RNG) + // + // If all else fails, use Math.random(). It's fast, but is of + // unspecified + // quality. + var _rnds = new Array(16); + _mathRNG = _rng = function () { + for (var i = 0, r; i < 16; i++) { + if ((i & 0x03) === 0) { + r = Math.random() * 0x100000000; + } + _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; + } + + return _rnds; + }; + if ('undefined' !== typeof console && console.warn) { + console + .warn("[SECURITY] node-uuid: crypto not usable, falling back to insecure Math.random()"); + } + } + } + + function setupNode() { + // Node.js crypto-based RNG - + // http://nodejs.org/docs/v0.6.2/api/crypto.html + // + // Moderately fast, high quality + if ('function' === typeof require) { + try { + var _rb = require('crypto').randomBytes; + _nodeRNG = _rng = _rb && function () { + return _rb(16); + }; + _rng(); + } catch (e) { /**/ } + } + } + + if (_window) { + setupBrowser(); + } else { + setupNode(); + } + + // Buffer class to use + var BufferClass = ('function' === typeof Buffer) ? Buffer : Array; + + // Maps for number <-> hex string conversion + var _byteToHex = []; + var _hexToByte = {}; + for (var i = 0; i < 256; i++) { + _byteToHex[i] = (i + 0x100).toString(16).substr(1); + _hexToByte[_byteToHex[i]] = i; + } + + // **`parse()` - Parse a UUID into it's component bytes** + function parse(s, buf, offset) { + var i = (buf && offset) || 0, + ii = 0; + + buf = buf || []; + s.toLowerCase().replace(/[0-9a-f]{2}/g, function (oct) { + if (ii < 16) { // Don't overflow! + buf[i + ii++] = _hexToByte[oct]; + } + }); + + // Zero out remaining bytes if string was short + while (ii < 16) { + buf[i + ii++] = 0; + } + + return buf; + } + + // **`unparse()` - Convert UUID byte array (ala parse()) into a string** + function unparse(buf, offset) { + var i = offset || 0, + bth = _byteToHex; + return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]]; + } + + // **`v1()` - Generate time-based UUID** + // + // Inspired by https://github.com/LiosK/UUID.js + // and http://docs.python.org/library/uuid.html + + // random #'s we need to init node and clockseq + var _seedBytes = _rng(); + + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = + // 1) + var _nodeId = [ + _seedBytes[0] | 0x01, + _seedBytes[1], + _seedBytes[2], + _seedBytes[3], + _seedBytes[4], + _seedBytes[5] + ]; + + // Per 4.2.2, randomize (14 bit) clockseq + var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff; + + // Previous uuid creation time + var _lastMSecs = 0, + _lastNSecs = 0; + + // See https://github.com/broofa/node-uuid for API details + function v1(options, buf, offset) { + var i = buf && offset || 0; + var b = buf || []; + + options = options || {}; + + var clockseq = (options.clockseq != null) ? options.clockseq : _clockseq; + + // UUID timestamps are 100 nano-second units since the Gregorian + // epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and + // 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 + // 00:00. + var msecs = (options.msecs != null) ? options.msecs : new Date() + .getTime(); + + // Per 4.2.1.2, use count of uuid's generated during the current + // clock + // cycle to simulate higher resolution clock + var nsecs = (options.nsecs != null) ? options.nsecs : _lastNSecs + 1; + + // Time since last uuid creation (in msecs) + var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs) / 10000; + + // Per 4.2.1.2, Bump clockseq on clock regression + if (dt < 0 && options.clockseq == null) { + clockseq = clockseq + 1 & 0x3fff; + } + + // Reset nsecs if clock regresses (new clockseq) or we've moved onto + // a new + // time interval + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) { + nsecs = 0; + } + + // Per 4.2.1.2 Throw error if too many uuids are requested + if (nsecs >= 10000) { + throw new Error( + 'uuid.v1(): Can\'t create more than 10M uuids/sec'); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; + + // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + msecs += 12219292800000; + + // `time_low` + var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; + + // `time_mid` + var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; + + // `time_high_and_version` + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + b[i++] = tmh >>> 16 & 0xff; + + // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + b[i++] = clockseq >>> 8 | 0x80; + + // `clock_seq_low` + b[i++] = clockseq & 0xff; + + // `node` + var node = options.node || _nodeId; + for (var n = 0; n < 6; n++) { + b[i + n] = node[n]; + } + + return buf ? buf : unparse(b); + } + + // **`v4()` - Generate random UUID** + + // See https://github.com/broofa/node-uuid for API details + function v4(options, buf, offset) { + // Deprecated - 'format' argument, as supported in v1.2 + var i = buf && offset || 0; + + if (typeof (options) === 'string') { + buf = (options === 'binary') ? new BufferClass(16) : null; + options = null; + } + options = options || {}; + + var rnds = options.random || (options.rng || _rng)(); + + // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + rnds[6] = (rnds[6] & 0x0f) | 0x40; + rnds[8] = (rnds[8] & 0x3f) | 0x80; + + // Copy bytes to buffer, if provided + if (buf) { + for (var ii = 0; ii < 16; ii++) { + buf[i + ii] = rnds[ii]; + } + } + + return buf || unparse(rnds); + } + + // Export public API + var uuid = function () { + return new String(v4()); + }; + uuid.v1 = v1; + uuid.v4 = v4; + uuid.create = v4; + uuid.empty = "00000000-0000-0000-0000-000000000000"; + uuid.parse = parse; + uuid.unparse = unparse; + uuid.BufferClass = BufferClass; + uuid._rng = _rng; + uuid._mathRNG = _mathRNG; + uuid._nodeRNG = _nodeRNG; + uuid._whatwgRNG = _whatwgRNG; + + return uuid; +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/components/ActivationController.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,120 @@ +define(["dojo/_base/declare", "../guard", "../safe", "../log/_LogMixin"], function (declare, guard, safe, _LogMixin) { + "use strict"; + return declare([_LogMixin], { + + _current: null, + + _pending: false, + + getCurrent: function () { + return this._current; + }, + + _start: function () { + if (this._pending) + throw new Error("The activation/decativation is already pending"); + this._pending = true; + }, + + _await: function (d) { + var me = this; + return d.then(function (x) { + me._pending = false; + return x; + }, function (e) { + me._pending = false; + throw e; + }); + }, + + activate: function (component) { + safe.argumentNotNull(component, "component"); + var me = this; + if (component.getController() !== this) + throw new Error("The specified component doesn't belong to this controller"); + + return me._await(guard(me, "_start").then(function () { + me._activate(component); + })); + }, + + _activate: function (component) { + var me = this; + if (me._current === component) + return guard(false); + + // before activation hook + return guard(me, "onActivating", [component]).then(function () { + // deactivate curent + if (me._current) + return me._current.deactivate(true).then(function () { + try { + me._current.onDeactivated(); + } catch (err) { + me.error(err); + } + // HACK raise deactivated event + try { + me.onDeactivated(me._current, component); + } catch (err) { + // deactivated shouldn't affect the process + me.error(err); + } + me._current = null; + + }); + }).then(function () { + return component.activate(true); + }).then(function () { + me._current = component; + try { + me.onActivated(component); + } catch (err) { + me.error(err); + } + + }); + + }, + + /** + * Деактивирует текущую компоненту. + * + * @async + * @returns true - компонента была деактивирована, либо нет активной + * компоненты. false - запрос на деактивацию - отклонен. + */ + deactivate: function () { + var me = this; + return me._await(guard(me, "_start").then(function () { + return me._deactivate(); + })); + }, + + _deactivate: function () { + var me = this; + if (!me._current) + return guard(false); + + return guard(me, "onDeactivating").then(function () { + return me._current.deactivate(true); + }).then(function () { + // HACK raise deactivated event + try { + me.onDeactivated(me._current); + } catch (err) { + me.error(err); + } + me._current = null; + }); + }, + + onActivating: function (component) {}, + + onDeactivating: function (component) {}, + + onDeactivated: function (component, next) {}, + + onActivated: function (component) {} + }); +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/components/StateMachine.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,34 @@ +define([ "dojo/_base/declare", "../safe", "../text/format" ], function(declare, safe, format) { + return declare(null, { + states : null, + + current : null, + + constructor : function(opts) { + safe.argumentNotNull(opts, "opts"); + safe.argumentNotNull(opts.states, "opts.states"); + safe.argumentNotNull(opts.initial, "opts.initial"); + + this.states = opts.states; + this.current = opts.initial; + + if (safe.isNull(this.states[this.current])) + throw new Error("Invalid initial state " + this.current); + }, + + move : function(input, noThrow) { + safe.argumentNotNull(input, "input"); + + var next = this.states[this.current][input]; + if(safe.isNull(next)) { + if (noThrow) + return false; + else + throw new Error(format("Invalid transition {0}-{1}->?", this.current, input)); + } else { + this.current = next; + return true; + } + } + }); +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/components/_ActivatableMixin.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,153 @@ +define(["dojo/_base/declare", "../guard", "./StateMachine", "../log/_LogMixin", ], function (declare, guard, StateMachine, _LogMixin) { + + var states = { + inactive: { + activate: "activating" + }, + activating: { + success: "active", + failed: "inactive" + }, + active: { + deactivate: "deactivating" + }, + deactivating: { + success: "inactive", + failed: "active" + } + }; + + return declare([_LogMixin], { + _controller: null, + + _active: null, + + constructor: function () { + this._active = new StateMachine({ + states: states, + initial: "inactive" + }); + }, + + /** + * @returns {Object} контроллер для активации текущей компоненты + */ + getController: function () { + return this._controller; + }, + + /** + * @param {Object} + * v Контроллер для активации текущей компоненты + */ + setController: function (v) { + this._controller = v; + }, + + /** + * @returns {Boolean} текущая компонента активна + */ + isActive: function () { + return this._active.current == "active"; + }, + + assertActive: function () { + if (!this.isActive()) + throw new Error("The object must be active to perform the operation"); + }, + + /** + * Активирует текущую компоненту, если у текущей компоненты задан + * контроллер, то активация будет осуществляться через него + * + * @async + * @param{Boolean} + * direct вызов должен осуществится напрямую, без участия + * контроллера. + * @return{Boolean} успешно/неуспешно + */ + activate: function (direct) { + var me = this; + if (!direct && this._controller) + return me._controller.activate(me).then(function () { + me.onActivated(); + }); + + me._active.move("activate"); + return guard(me, "onActivating").then(function () { + me.log("Activated"); + me._active.move("success"); + if (!me._controller) + me.onActivated(); + }, function (err) { + console.error(err); + me.error("Activation failed: {0}", err); + me._active.move("failed"); + throw err; + }); + }, + + /** + * Деактивирует текущую компоненту, если у компоненты задан контроллер, + * то деактивация будет осуществляться через него. + * + * @async + * @param{Boolean} direct вызов должен осуществится напрямую, без + * участия контроллера. + * + */ + deactivate: function (direct) { + var me = this; + if (!direct && me._controller) + return me._controller.deactivate(me).then(function () { + me.onDeactivated(); + }); + + me._active.move("deactivate"); + return guard(me, "onDeactivating").then(function () { + me.log("Deactivated"); + me._active.move("success"); + if (!me._controller) + me.onDeactivated(); + }, function (err) { + console.error(err); + me.error("Deactivation failed: {0}", err); + me.move("failed"); + throw err; + }); + + }, + + toogleActive: function () { + var me = this; + return (me.isActive() ? me.deactivate() : me.activate()).then(function () { + return me.isActive(); + }); + }, + + /** + * Событие вызывается перед активацией текущей компоненты + * + * @returns{Boolean|undefined} если false - активация будет отменена + */ + onActivating: function () {}, + + /** + * Событие вызывается перед деактивацией текущей компоненты + * + * @returns {Boolean|undefined} если false - деактивация будет отменена + */ + onDeactivating: function () {}, + + /** + * Событие вызывается после активации текущей компоненты + */ + onActivated: function () {}, + + /** + * Событие вызывается после деактивации текущей компоненты + */ + onDeactivated: function () {} + + }); +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/data/DataContext.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,45 @@ +define([ "dojo/_base/declare", "../safe" ], function(declare, safe) { + return declare( + null, + { + _params : null, + + _repositories : null, + + constructor : function(opts) { + this._params = opts || {}; + this._repositories = {}; + }, + + getRepository : function(name) { + safe.argumentNotEmptyString(name, "name"); + var repo = this._repositories[name]; + if (!repo) { + repo = this._params[name]; + if (!repo) + throw new Error("The repository '" + name + + "' isn't found"); + if (repo instanceof Function) + repo = new repo(); // factory method or constructor + if (repo.initialize) { + repo.initialize({ + dataContext : this + }); + } else if (repo.setDataContext) { + repo.setDataContext(this); + } + this._repositories[name] = repo; + } + + return repo; + }, + + dispose : function() { + for( var name in this._repositories) { + var r = this._repositories[name]; + if (r.dispose) + r.dispose(); + } + } + }); +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/data/MapSchema.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,67 @@ +define([ "dojo/_base/declare", "../safe" ], function(declare, safe) { + return declare(null, { + /** + * Отображение одного типа объектов в другой. + * + * @remarks Отображения являются односторонними, т.е. позволяют + * перенести часть содержимого одного объекта в другой. Каждая + * схема отображения строится из набора примитивных + * отображений, которые будут применены в произвольном порядке. + */ + _schema : null, + + constructor : function(schema) { + this._schema = schema; + }, + + /** + * Осуществляет отображение одного объекта в другой + * + * @src{Object} Исходный объект из которого будут взяты данные + * @dst{Object} + */ + map : function(src, dst, ctx) { + safe.argumentNotNull(src, "src"); + safe.argumentNotNull(dst, "dst"); + + for ( var p in this._schema) { + var mapper = this._schema[p]; + if (mapper instanceof Function) { + dst[p] = mapper(src[p]); + } else if (mapper && mapper.map) { + mapper.map(src, dst, p, ctx); + } else { + this._defaultMapper(src, dst, p, mapper, ctx); + } + } + }, + + _defaultMapper : function(src, dst, prop, opts) { + if (typeof (opts) == "string") { + if (opts in src) + dst[prop] = src[opts]; + } else if (opts && opts.type instanceof Function) { + if (src[prop] instanceof opts.type) + dst[prop] = src[prop]; + else + dst[prop] = this._isPrimitiveType(opts.type) ? opts.type + .call(null, src[prop]) : new opts.type(src[prop]); + + } else { + if (!(prop in src)) + if (opts && opts.required) + throw new Error("The " + prop + "is missing"); + else + return; + dst[prop] = src[prop]; + } + }, + + _isPrimitiveType : function(type) { + return (type === String || type === Number || type === Boolean + || type === Number || type === Date); + } + + }); + +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/data/ObjectStore.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,174 @@ +define([ "dojo/_base/declare", "dojo/_base/lang", "dojo/_base/array", + "../safe", "dojo/when", "dojo/Deferred", "dojo/store/util/QueryResults" ], function(declare, + lang, array, safe, when, Deferred, QueryResults) { + /** + * @module implab/data/RestStore + * + * Реализует шаблон репозитария dojo/store над уже имеющимся хранилищем. При получении и + * отправке данных в нижележащие хранилище используется implab/data/MapSchema для преобразования + * данных. + */ + return declare(null, { + + model: null, + + mapping: null, + + _dataContext: null, + + _store : null, // backing store + + _cache : null, + + constructor : function(options) { + options = options || {}; + + if (options.store) + this._store = options.store; + + if (options.dataContext) { + this._dataContext = options.dataContext; + } + + if (options.cache === false) { + // no cache at all + } else if (options.cache === "string" && options.dataContext) { + this._cache = this._dataContext.getCache(options.cache); + } else { + this._cache = {}; + } + }, + + getDataContext : function() { + return this._dataContext; + }, + + // READ + get : function(id) { + var me = this; + var cache = me.getCacheEntry(id); + if (cache) + return cache; + else + return when(me._store.get(id), function(data) { + return me._mapToObject(id, data); + }); + }, + + query : function(query, options) { + var me = this; + var d = me._store.query(query, options); + var result = QueryResults(when(d, function(data) { + return array.map(data, function(item) { + return me._mapToObject(me._store.getIdentity(item), item); + }); + })); + result.total = d.total; + return result; + }, + + getIdentity : function(object) { + return object.getId(); + }, + + // UPDATE + put : function(object, directives) { + return this._store.put(this._mapFromObject(object), directives); + }, + + // INSERT + add : function(object, directives) { + var me = this; + // добавляем в хранилище данные, сохраняем в кеше объект с + // полученным идентификатором + return when( + me._store.add(this._mapFromObject(object), directives), + function(id) { + object.attach(id, me); + me.storeCacheEntry(id, object); + return id; + }); + }, + + // DELETE + remove : function(id) { + var me = this; + return when(me._store.remove(id), function() { + me.removeCacheEntry(id); + }); + }, + + _mapToObject : function(id, data) { + var instance = this.createInstance(id); + this.populateInstance(instance, data); + return instance; + }, + + _mapFromObject : function(object) { + return this.serializeInstance(object); + }, + + getCacheEntry : function(id) { + safe.argumentNotNull(id, "id"); + id = id.toString(); + + return this._cache[id]; + }, + + storeCacheEntry : function(id, object) { + safe.argumentNotNull(id, "id"); + id = id.toString(); + + this._cache[id] = object; + }, + + removeCacheEntry : function(id) { + safe.argumentNotNull(id, "id"); + id = id.toString(); + delete this._cache[id]; + }, + + /** Создает экземпляр сущности с указанным идентификатором, либо извлекает из кеша, если таковая уже имеется. + * @remarks + * Технически сюда можно было бы дополнительно передать данные для ининциализации объекта, + * но концептуально это не верно, поскольку процесс чтения объекта состоит из двух этапов: + * 1. Создание пустого объекта (createInstance) + * 2. Заполнение объекта при помощи схемы отображения (populateInstance) + * при этом первый этап может быть выполнен за долго до второго, например, + * при создании заглушек в процессе установления ссылок между объектами. + */ + createInstance : function(id) { + var instance = this.getCacheEntry(id); + if (!instance) { + instance = this.createInstanceImpl(id); + this.storeCacheEntry(id, instance); + } + return instance; + }, + + /** Непосредственно создает экземпляр сущнсти, т.е. является фабричным методом. + * @param {String} id идентификатор создаваемого экземпляра. + */ + createInstanceImpl : function(id) { + var opts = { + dataContext : this.getDataContext(), + id : id + }; + + return new this.itemsType(opts); + }, + + populateInstance : function(instance, data) { + this.mapping.readData(instance, data,this.getDataContext()); + if (instance.onPopulate) + instance.onPopulate(); + }, + + serializeInstance : function(instance) { + var data = {}; + this.mapping.writeData(instance, data, this.getDataContext()); + return data; + } + + }); +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/data/RestStore.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,166 @@ +define([ "dojo/_base/declare", "dojo/_base/lang", "dojo/_base/array", + "../safe", "dojo/when", "dojo/Deferred", "dojo/store/util/QueryResults" ], function(declare, + lang, array, safe, when, Deferred, QueryResults) { + /** + * @module implab/data/RestStore + * + * Реализует шаблон репозитария dojo/store над уже имеющимся хранилищем. При получении и + * отправке данных в нижележащие хранилище используется implab/data/MapSchema для преобразования + * данных. + */ + return declare(null, { + + itemsType : null, + + _dataContext : null, + + _store : null, // backing store + _cache : null, + + constructor : function(options) { + options = options || {}; + + this._cache = {}; + if (options.store) + this._store = options.store; + if (options.dataContext) + this._dataContext = options.dataContext; + }, + + setDataContext : function(v) { + this._dataContext = v; + }, + + getDataContext : function() { + return this._dataContext; + }, + + // READ + get : function(id) { + var me = this; + var cache = me.getCacheEntry(id); + if (cache) + return cache; + else + return when(me._store.get(id), function(data) { + return me._mapToObject(id, data); + }); + }, + + query : function(query, options) { + var me = this; + var d = me._store.query(query, options); + var result = QueryResults(when(d, function(data) { + return array.map(data, function(item) { + return me._mapToObject(me._store.getIdentity(item), item); + }); + })); + result.total = d.total; + return result; + }, + + getIdentity : function(object) { + return object.getId(); + }, + + // UPDATE + put : function(object, directives) { + return this._store.put(this._mapFromObject(object), directives); + }, + + // INSERT + add : function(object, directives) { + var me = this; + // добавляем в хранилище данные, сохраняем в кеше объект с + // полученным идентификатором + return when( + me._store.add(this._mapFromObject(object), directives), + function(id) { + object.attach(id, me); + me.storeCacheEntry(id, object); + return id; + }); + }, + + // DELETE + remove : function(id) { + var me = this; + return when(me._store.remove(id), function() { + me.removeCacheEntry(id); + }); + }, + + _mapToObject : function(id, data) { + var instance = this.createInstance(id); + this.populateInstance(instance, data); + return instance; + }, + + _mapFromObject : function(object) { + return this.serializeInstance(object); + }, + + getCacheEntry : function(id) { + safe.argumentNotNull(id, "id"); + id = id.toString(); + + return this._cache[id]; + }, + + storeCacheEntry : function(id, object) { + safe.argumentNotNull(id, "id"); + id = id.toString(); + + this._cache[id] = object; + }, + + removeCacheEntry : function(id) { + safe.argumentNotNull(id, "id"); + id = id.toString(); + delete this._cache[id]; + }, + + /** Создает экземпляр сущности с указанным идентификатором, либо извлекает из кеша, если таковая уже имеется. + * @remarks + * Технически сюда можно было бы дополнительно передать данные для ининциализации объекта, + * но концептуально это не верно, поскольку процесс чтения объекта состоит из двух этапов: + * 1. Создание пустого объекта (createInstance) + * 2. Заполнение объекта при помощи схемы отображения (populateInstance) + * при этом первый этап может быть выполнен за долго до второго, например, + * при создании заглушек в процессе установления ссылок между объектами. + */ + createInstance : function(id) { + var instance = this.getCacheEntry(id); + if (!instance) { + instance = this.createInstanceImpl(id); + this.storeCacheEntry(id, instance); + } + return instance; + }, + + /** Непосредственно создает экземпляр сущнсти, т.е. является фабричным методом. + * @param {String} id идентификатор создаваемого экземпляра. + */ + createInstanceImpl : function(id) { + var opts = { + dataContext : this.getDataContext(), + id : id + }; + + return new this.itemsType(opts); + }, + + populateInstance : function(instance, data) { + this.itemsType.readData(instance, data,this.getDataContext()); + if (instance.onPopulate) + instance.onPopulate(); + }, + + serializeInstance : function(instance) { + var data = {}; + this.itemsType.writeData(instance, data, this.getDataContext()); + return data; + } + + }); +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/data/StatefullStoreAdapter.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,19 @@ +define(["dojo/_base/declare", "dojo/_base/array", "../safe", "./StoreAdapter"], function(declare, array, safe ,AdapterStore){ + return declare([AdapterStore], { + _attrs : null, + + constructor : function(opts) { + safe.argumentNotEmptyArray(opts.attrs, "opts.attrs"); + this._attrs = opts.attrs; + }, + + mapItem : function(item) { + var result = {}; + array.forEach(this._attrs, function(p) { + result[p] = item.get(p); + }); + return result; + } + }); + +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/data/StoreAdapter.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,110 @@ +define([ + "dojo/_base/declare", + "../safe", + "dojo/when", + "dojo/store/util/QueryResults" ], + +function(declare, safe, when, QueryResults) { + + "use strict"; + + /** + * Обертка вокруг произвольного хранилища, только для чтения. Используется + * для преобразования данных, например, отображения в списках элементов + * пространственных данных. + */ + return declare(null, { + /** + * @type{String} Свойство, хранящее идентификатор + */ + idProperty : null, + + _store : null, + + /** + * @param{String} opts.idProperty Имя свойства, в которое будет записан + * идентификатор, если не указан, то идентификатор будет + * взят из родительского хранилища или использоваться + * строка <code>id</code> + * @param{dojo.store} opts.store Родительское хранилище + */ + constructor : function(opts) { + safe.argumentNotNull(opts, "opts"); + safe.argumentNotNull(opts.store, "opts.store"); + + this._store = opts.store; + delete opts.store; + declare.safeMixin(this, opts); + this.idProperty = opts.idProperty || this._store.idProperty || "id"; + }, + + getParentStore : function() { + return this._store; + }, + + get : function(id) { + var me = this; + return when(me._store.get(id), function(x) { + var m = me.mapItem(x); + if (!(me.idProperty in m)) + m[me.idProperty] = id; + return m; + }); + }, + + /** + * Выполняет запрос в родительском хранилище, для этого используется + * <code>translateQuery</code> для подготовки запроса, затем, + * <code>mapItem</code> для преобразования результатов. + */ + query : function(q, options) { + var me = this, store = this._store; + return when(store.query(me.translateQuery(q), me + .translateOptions(options)), function(res) { + var total = res.total; + var mapped = res.map(function(x) { + var m = me.mapItem(x); + if (!(me.idProperty in m)) + m[me.idProperty] = store.getIdentity && + store.getIdentity(x); + return m; + }); + mapped.total = total; + var results = new QueryResults(mapped); + console.log(results); + return results; + }); + }, + + getIdentity : function(obj) { + return obj && obj[this.idProperty]; + }, + + /** + * Преобразование запроса в формат родительского хранилища. + * + * @param{Object} q Запрос в формате текущего хранилища + * @returns{Object} Запрос в формате родительского хранилища + */ + translateQuery : function(q) { + return q; + }, + + translateOptions : function(options) { + return options; + }, + + /** + * Преобразование объекта из родительского хранилища. При преобразовании + * в объекте можно задать идентификатор, иначе идентификатор будет + * автоматически получен и присвоен из родительского хранилища + * + * @param{Object} item Объект из родительского хранилища + * @returns{Object} результат преобразования + */ + mapItem : function(item) { + return item; + } + }); + +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/data/_ModelBase.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,37 @@ +define(["dojo/_base/declare"], function(declare) { + + return declare(null, { + dataContext : null, + idField : "id", + loaded : false, + + constructor : function(opts){ + if (opts) { + if(opts.dataContext) + this.dataContext = opts.dataContext; + if(opts.id) + this[this.idField] = opts.id; + } + }, + + getId : function() { + return this[this.idField]; + }, + + attach : function(id, dc) { + if (this.dataContext) + throw new Error("The object is already attached"); + this[this.idField] = id; + this.dataContext = dc; + }, + + isAttached : function() { + return this.dataContext ? true : false; + }, + + onPopulate : function() { + this.loaded = true; + } + + }); +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/data/_StatefulModelMixin.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,5 @@ +define(["dojo/_base/declare", "dojo/Stateful"], function(declare, Stateful) { + return declare([Stateful], { + + }); +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/data/declare-model.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,72 @@ +define([ "dojo/_base/declare", "./_ModelBase", "./MapSchema" ], function( + declare, _ModelBase, MapSchema) { + /** + * Создает новый класс, унаследованный от ./ModelBase, с указанной схемой + * отображения данных. + * + * @details Модель представляет собой объект, живущий в рамках контекста + * данных, также имеющий две схемы отображения: из модели хранения + * в источнике данных (toObjectMap) и наооборот в модель хранения в + * источнике данных (fromObjectMap). + * + * Описание схемы выглядит следующим образом + * <pre> + * { + * name : null, // отображение в обе стороны без преобразования + * + * age : Number, // при преобразоваении к объекту поле будет преобразовано dst.age = Number(src.age) + * // обратное преобразование отсутстсвует + * + * age : [Number, null] // тоже самое что и age : Number + * + * date : [Date, function(v) { return v.toString() }] // указывается преобразование в одну и в другую сторону + * } + * <pre> + */ + return function(schema, mixins, opts) { + var fromObjectSchema = {}, toObjectSchema = {}; + if (schema !== null && schema !== undefined) { + for ( var p in schema) { + var mapper = schema[p]; + + if (mapper instanceof Array) { + toObjectSchema[p] = mapper[0]; + fromObjectSchema[p] = mapper[1]; + } else { + toObjectSchema[p] = mapper; + fromObjectSchema[p] = null; + } + } + } + + if (arguments.length < 3) { + opts = mixins; + mixins = undefined; + } + + var base = [ _ModelBase ]; + if (mixins) { + if (mixins instanceof Array) + base = base.concat(mixins); + else + base.push(mixins); + } + + var model = declare(base, opts); + + model.toObjectMap = new MapSchema(toObjectSchema); + + model.fromObjectMap = new MapSchema(fromObjectSchema); + + model.readData = function(that, data, context) { + model.toObjectMap.map(data, that, context); + }; + + model.writeData = function(that, data, context) { + data = data || {}; + model.fromObjectMap.map(that, data, context); + }; + + return model; + }; +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/declare.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,6 @@ +define([ + './declare/_load!' +], function(declare) { + 'use strict'; + return declare; +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/declare/_load.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,12 @@ +define([], function () { + 'use strict'; + + return { + load: function (id, require, callback) { + require(['dojo/_base/declare'], function (declare) { + callback(declare); + }); + } + }; + +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/declare/override.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,73 @@ +"use strict"; +define([], function () { + var slice = Array.prototype.slice; + var override = function (method) { + var proxy; + + /** @this target object */ + proxy = function () { + var me = this; + var inherited = (this.getInherited && this.getInherited(proxy.nom, { + callee: proxy + })) || function () {}; + + return method.apply(me, [function () { + return inherited.apply(me, arguments); + }].concat(slice.apply(arguments))); + }; + + proxy.method = method; + proxy.overrides = true; + + return proxy; + }; + + override.before = function (method) { + var proxy; + + /** @this target object */ + proxy = function () { + var me = this; + var inherited = (this.getInherited && this.getInherited(proxy.nom, { + callee: proxy + })) || function () {}; + + + method.apply(me, arguments); + return inherited.apply(me, arguments); + }; + + proxy.method = method; + proxy.overrides = true; + + return proxy; + }; + + override.after = function (method) { + var proxy; + + /** @this target object */ + proxy = function () { + var me = this; + var inherited = (this.getInherited && this.getInherited(proxy.nom, { + callee: proxy + })) || function () {}; + + inherited.apply(me, arguments); + + return method.apply(me, arguments); + }; + + proxy.method = method; + proxy.overrides = true; + + return proxy; + }; + + override.hide = function (method) { + method.overrides = false; + return method; + }; + + return override; +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/di/ActivationContext.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,138 @@ +define([ + "../declare", + "../safe", + "./Descriptor", + "./ValueDescriptor", + "../log/trace!" +], function (declare, safe, Descriptor, Value, trace) { + var Context = declare(null, { + + _cache: null, + + _services: null, + + _stack: null, + + _visited: null, + + container: null, + + _trace: true, + + constructor: function (container, services, cache, visited) { + safe.argumentNotNull(container, "container"); + safe.argumentNotNull(services, "services"); + + this._visited = visited || {}; + this._stack = []; + this._cache = cache || {}; + this._services = services; + this.container = container; + }, + + getService: function (name, def) { + var d = this._services[name]; + + if (!d) + if (arguments.length > 1) + return def; + else + throw new Error("Service '" + name + "' not found"); + + return d.activate(this, name); + }, + + /** + * registers services local to the the activation context + * + * @name{string} the name of the service + * @service{string} the service descriptor to register + */ + register: function (name, service) { + safe.argumentNotEmptyString(name, "name"); + + if (!(service instanceof Descriptor)) + service = new Value(service, true); + this._services[name] = service; + }, + + clone: function () { + return new Context( + this.container, + Object.create(this._services), + this._cache, + this._visited + ); + + }, + + has: function (id) { + return id in this._cache; + }, + + get: function (id) { + return this._cache[id]; + }, + + store: function (id, value) { + return (this._cache[id] = value); + }, + + parse: function (data, name) { + var me = this; + if (safe.isPrimitive(data)) + return data; + + if (data instanceof Descriptor) { + return data.activate(this, name); + } else if (data instanceof Array) { + me.enter(name); + var v = data.map(function (x, i) { + return me.parse(x, "." + i); + }); + me.leave(); + return v; + } else { + me.enter(name); + var result = {}; + for (var p in data) + result[p] = me.parse(data[p], "." + p); + me.leave(); + return result; + } + }, + + visit: function (id) { + var count = this._visited[id] || 0; + this._visited[id] = count + 1; + return count; + }, + + getStack: function () { + return this._stack.slice().reverse(); + }, + + enter: function (name, d, localize) { + if (this._trace) + trace.log("enter " + name + " " + (d || "") + + (localize ? " localize" : "")); + this._stack.push({ + name: name, + service: d, + scope: this._services + }); + if (localize) + this._services = Object.create(this._services); + }, + + leave: function () { + var ctx = this._stack.pop(); + this._services = ctx.scope; + + if (this._trace) + trace.log("leave " + ctx.name + " " + (ctx.service || "")); + } + }); + + return Context; +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/di/ActivationError.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,39 @@ +define([ + "../declare" +], function (declare) { + return declare(null, { + activationStack: null, + + service: null, + + innerException: null, + + message: null, + + constructor: function (service, activationStack, innerException) { + this.message = "Failed to activate the service"; + this.activationStack = activationStack; + this.service = service; + this.innerException = innerException; + }, + + toString: function () { + var parts = [this.message]; + if (this.service) + parts.push("when activating: " + this.service.toString()); + + if (this.innerException) + parts.push("caused by: " + this.innerException.toString()); + + if (this.activationStack) { + parts.push("at"); + this.activationStack.forEach(function (x) { + parts.push(" " + x.name + " " + + (x.service ? x.service.toString() : "")); + }); + } + + return parts.join("\n"); + } + }); +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/di/Container.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,299 @@ +define([ + "../declare", + "../safe", + "../Uuid", + "../Deferred", + "./ActivationContext", + "./Descriptor", + "./ValueDescriptor", + "./ReferenceDescriptor", + "./ServiceDescriptor", + "./ActivationError" +], function ( + declare, + safe, + Uuid, + Deferred, + ActivationContext, + Descriptor, + Value, + Reference, + Service, + ActivationError) { + var Container = declare(null, { + _services: null, + _cache: null, + _cleanup: null, + _root: null, + _parent: null, + + constructor: function (parent) { + this._parent = parent; + this._services = parent ? Object.create(parent._services) : {}; + this._cache = {}; + this._cleanup = []; + this._root = parent ? parent.getRootContainer() : this; + this._services.container = new Value(this, true); + }, + + getRootContainer: function () { + return this._root; + }, + + getParent: function () { + return this._parent; + }, + + /** + * + */ + getService: function (name, def) { + var d = this._services[name]; + if (!d) + if (arguments.length > 1) + return def; + else + throw new Error("Service '" + name + "' isn't found"); + if (d.isInstanceCreated()) + return d.getInstance(); + + var context = new ActivationContext(this, this._services); + + try { + return d.activate(context, name); + } catch (error) { + throw new ActivationError(name, context.getStack(), error); + } + }, + + register: function (name, service) { + if (arguments.length == 1) { + var data = name; + for (name in data) + this.register(name, data[name]); + } else { + if (!(service instanceof Descriptor)) + service = new Value(service, true); + this._services[name] = service; + } + return this; + }, + + onDispose: function (callback) { + if (!(callback instanceof Function)) + throw new Error("The callback must be a function"); + this._cleanup.push(callback); + }, + + dispose: function () { + if (this._cleanup) { + for (var i = 0; i < this._cleanup.length; i++) + this._cleanup[i].call(null); + this._cleanup = null; + } + }, + + /** + * @param{String|Object} config + * The configuration of the contaier. Can be either a string or an object, + * if the configuration is an object it's treated as a collection of + * services which will be registed in the contaier. + * + * @param{Function} opts.contextRequire + * The function which will be used to load a configuration or types for services. + * + */ + configure: function (config, opts) { + var p, me = this, + contextRequire = (opts && opts.contextRequire); + + if (typeof (config) === "string") { + p = new Deferred(); + if (!contextRequire) { + var shim = [config, new Uuid()].join(config.indexOf("/") != -1 ? "-" : "/"); + define(shim, ["require", config], function (ctx, data) { + p.resolve([data, { + contextRequire: ctx + }]); + }); + require([shim]); + } else { + // TODO how to get correct contextRequire for the relative config module? + contextRequire([config], function (data) { + p.resolve([data, { + contextRequire: contextRequire + }]); + }); + } + + return p.then(function (args) { + return me._configure.apply(me, args); + }); + } else { + return me._configure(config, opts); + } + }, + + createChildContainer: function () { + return new Container(this); + }, + + has: function (id) { + return id in this._cache; + }, + + get: function (id) { + return this._cache[id]; + }, + + store: function (id, value) { + return (this._cache[id] = value); + }, + + _configure: function (data, opts) { + var typemap = {}, + d = new Deferred(), + me = this, + p, + contextRequire = (opts && opts.contextRequire) || require; + + var services = {}; + + for (p in data) { + var service = me._parse(data[p], typemap); + if (!(service instanceof Descriptor)) + service = new Value(service, false); + services[p] = service; + } + + me.register(services); + + var names = []; + + for (p in typemap) + names.push(p); + + if (names.length) { + contextRequire(names, function () { + for (var i = 0; i < names.length; i++) + typemap[names[i]] = arguments[i]; + d.resolve(me); + }); + } else { + d.resolve(me); + } + return d.promise; + }, + + _parse: function (data, typemap) { + if (safe.isPrimitive(data) || data instanceof Descriptor) + return data; + if (data.$dependency) + return new Reference( + data.$dependency, + data.lazy, + data.optional, + data["default"], + data.services && this._parseObject(data.services, typemap)); + if (data.$value) { + var raw = !data.parse; + return new Value(raw ? data.$value : this._parse( + data.$value, + typemap), raw); + } + if (data.$type || data.$factory) + return this._parseService(data, typemap); + if (data instanceof Array) + return this._parseArray(data, typemap); + + return this._parseObject(data, typemap); + }, + + _parseService: function (data, typemap) { + var me = this, + opts = { + owner: this + }; + if (data.$type) { + + opts.type = data.$type; + + if (typeof (data.$type) === "string") { + typemap[data.$type] = null; + opts.typeMap = typemap; + } + } + + if (data.$factory) + opts.factory = data.$factory; + + if (data.services) + opts.services = me._parseObject(data.services, typemap); + if (data.inject) + opts.inject = data.inject instanceof Array ? data.inject.map(function (x) { + return me._parseObject(x, typemap); + }) : me._parseObject(data.inject, typemap); + if (data.params) + opts.params = me._parse(data.params, typemap); + + if (data.activation) { + if (typeof (data.activation) === "string") { + switch (data.activation.toLowerCase()) { + case "singleton": + opts.activation = Service.SINGLETON; + break; + case "container": + opts.activation = Service.CONTAINER; + break; + case "hierarchy": + opts.activation = Service.HIERARCHY; + break; + case "context": + opts.activation = Service.CONTEXT; + break; + case "call": + opts.activation = Service.CALL; + break; + default: + throw new Error("Unknown activation type: " + + data.activation); + } + } else { + opts.activation = Number(data.activation); + } + } + + if (data.cleanup) + opts.cleanup = data.cleanup; + + return new Service(opts); + }, + + _parseObject: function (data, typemap) { + if (data.constructor && + data.constructor.prototype !== Object.prototype) + return new Value(data, true); + + var o = {}; + + for (var p in data) + o[p] = this._parse(data[p], typemap); + + return o; + }, + + _parseArray: function (data, typemap) { + if (data.constructor && + data.constructor.prototype !== Array.prototype) + return new Value(data, true); + + var me = this; + return data.map(function (x) { + return me._parse(x, typemap); + }); + } + + }); + + return Container; +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/di/Descriptor.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,4 @@ +define([], function() { + // abstract base type for descriptros + return function() {}; +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/di/ReferenceDescriptor.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,90 @@ +define([ + "../declare", "../safe", "./Descriptor", "./ActivationError", "./ValueDescriptor" +], + +function(declare, safe, Descriptor, ActivationError, Value) { + return declare(Descriptor, { + _name : null, + _lazy : false, + _optional : false, + _default : undefined, + + constructor : function(name, lazy, optional, def, services) { + safe.argumentNotEmptyString(name, "name"); + this._name = name; + this._lazy = Boolean(lazy); + this._optional = Boolean(optional); + this._default = def; + this._services = services; + }, + + activate : function(context, name) { + var me = this; + + context.enter(name, this, true); + + // добавляем сервисы + if (me._services) { + for ( var p in me._services) { + var sv = me._services[p]; + context.register(p, sv instanceof Descriptor ? sv : new Value(sv, false)); + } + } + + if (me._lazy) { + // сохраняем контекст активации + context = context.clone(); + return function(cfg) { + // защищаем контекст на случай исключения в процессе + // активации + var ct = context.clone(); + try { + if (cfg) + safe.each(cfg, function(v, k) { + ct.register(k, v instanceof Descriptor ? v : new Value(v, false)); + }); + return me._optional ? ct.getService(me._name, me._default) : ct + .getService(me._name); + } catch (error) { + throw new ActivationError(me._name, ct.getStack(), error); + } + }; + } + + var v = me._optional ? context.getService(me._name, me._default) : context + .getService(me._name); + context.leave(me); + return v; + }, + + isInstanceCreated : function() { + return false; + }, + + toString : function() { + var opts = []; + if (this._optional) + opts.push("optional"); + if (this._lazy) + opts.push("lazy"); + + var parts = [ + "@ref " + ]; + if (opts.length) { + parts.push("{"); + parts.push(opts.join()); + parts.push("} "); + } + + parts.push(this._name); + + if (!safe.isNull(this._default)) { + parts.push(" = "); + parts.push(this._default); + } + + return parts.join(""); + } + }); +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/di/ServiceDescriptor.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,289 @@ +define( + [ + "../declare", + "../safe", + "./Descriptor", + "./ValueDescriptor" + ], + + function (declare, safe, Descriptor, Value) { + var SINGLETON_ACTIVATION = 1, + CONTAINER_ACTIVATION = 2, + CONTEXT_ACTIVATION = 3, + CALL_ACTIVATION = 4, + HIERARCHY_ACTIVATION = 5; + + var injectMethod = function (target, method, context, args) { + var m = target[method]; + if (!m) + throw new Error("Method '" + method + "' not found"); + + if (args instanceof Array) + m.apply(target, context.parse(args, "." + method)); + else + m.call(target, context.parse(args, "." + method)); + }; + + var makeClenupCallback = function (target, method) { + if (typeof (method) === "string") { + return function () { + target[method](); + }; + } else { + return function () { + method(target); + }; + } + }; + + var cacheId = 0; + + var cls = declare( + Descriptor, { + _instance: null, + _hasInstance: false, + _activationType: CALL_ACTIVATION, + _services: null, + _type: null, + _typeMap: null, + _factory: null, + _params: undefined, + _inject: null, + _cleanup: null, + _cacheId: null, + _owner: null, + + constructor: function (opts) { + safe.argumentNotNull(opts, "opts"); + safe.argumentNotNull(opts.owner, "opts.owner"); + + this._owner = opts.owner; + + if (!(opts.type || opts.factory)) + throw new Error( + "Either a type or a factory must be specified"); + + if (typeof (opts.type) === "string" && !opts.typeMap) + throw new Error( + "The typeMap is required when the type is specified by its name"); + + if (opts.activation) + this._activationType = opts.activation; + if (opts.type) + this._type = opts.type; + if (opts.params) + this._params = opts.params; + if (opts.inject) + this._inject = opts.inject instanceof Array ? opts.inject : [opts.inject]; + if (opts.services) + this._services = opts.services; + if (opts.factory) + this._factory = opts.factory; + if (opts.typeMap) + this._typeMap = opts.typeMap; + if (opts.cleanup) { + if (!(typeof (opts.cleanup) === "string" || opts.cleanup instanceof Function)) + throw new Error( + "The cleanup parameter must be either a function or a function name"); + + this._cleanup = opts.cleanup; + } + + this._cacheId = ++cacheId; + }, + + activate: function (context, name) { + + // if we have a local service records, register them first + + var instance; + + switch (this._activationType) { + case 1: // SINGLETON + // if the value is cached return it + if (this._hasInstance) + return this._instance; + + var tof = this._type || this._factory; + + // create the persistent cache identifier for the type + if (safe.isPrimitive(tof)) + this._cacheId = this._type; + else + this._cacheId = safe.oid(tof); + + // singletons are bound to the root container + var container = context.container.getRootContainer(); + + if (container.has(this._cacheId)) { + instance = container.get(this._cacheId); + } else { + instance = this._create(context, name); + container.store(this._cacheId, instance); + if (this._cleanup) + container.onDispose( + makeClenupCallback(instance, this._cleanup)); + } + + this._hasInstance = true; + return (this._instance = instance); + + case 2: // CONTAINER + //return a cached value + if (this._hasInstance) + return this._instance; + + // create an instance + instance = this._create(context, name); + + // the instance is bound to the container + if (this._cleanup) + this._owner.onDispose( + makeClenupCallback(instance, this._cleanup)); + + // cache and return the instance + this._hasInstance = true; + return (this._instance = instance); + case 3: // CONTEXT + //return a cached value if one exists + if (context.has(this._cacheId)) + return context.get(this._cacheId); + // context context activated instances are controlled by callers + return context.store(this._cacheId, this._create( + context, + name)); + case 4: // CALL + // per-call created instances are controlled by callers + return this._create(context, name); + case 5: // HIERARCHY + // hierarchy activated instances are behave much like container activated + // except they are created and bound to the child container + + // return a cached value + if (context.container.has(this._cacheId)) + return context.container.get(this._cacheId); + + instance = this._create(context, name); + + if (this._cleanup) + context.container.onDispose(makeClenupCallback( + instance, + this._cleanup)); + + return context.container.store(this._cacheId, instance); + default: + throw "Invalid activation type: " + this._activationType; + } + }, + + isInstanceCreated: function () { + return this._hasInstance; + }, + + getInstance: function () { + return this._instance; + }, + + _create: function (context, name) { + context.enter(name, this, Boolean(this._services)); + + if (this._activationType != CALL_ACTIVATION && + context.visit(this._cacheId) > 0) + throw new Error("Recursion detected"); + + if (this._services) { + for (var p in this._services) { + var sv = this._services[p]; + context.register(p, sv instanceof Descriptor ? sv : new Value(sv, false)); + } + } + + var instance; + + if (!this._factory) { + var ctor, type = this._type; + + if (typeof (type) === "string") { + ctor = this._typeMap[type]; + if (!ctor) + throw new Error("Failed to resolve the type '" + + type + "'"); + } else { + ctor = type; + } + + if (this._params === undefined) { + this._factory = function () { + return new ctor(); + }; + } else if (this._params instanceof Array) { + this._factory = function () { + var inst = Object.create(ctor.prototype); + var ret = ctor.apply(inst, arguments); + return typeof (ret) === "object" ? ret : inst; + }; + } else { + this._factory = function (param) { + return new ctor(param); + }; + } + } + + if (this._params === undefined) { + instance = this._factory(); + } else if (this._params instanceof Array) { + instance = this._factory.apply(this, context.parse( + this._params, + ".params")); + } else { + instance = this._factory(context.parse( + this._params, + ".params")); + } + + if (this._inject) { + this._inject.forEach(function (spec) { + for (var m in spec) + injectMethod(instance, m, context, spec[m]); + }); + } + + context.leave(); + + return instance; + }, + + // @constructor {singleton} foo/bar/Baz + // @factory {singleton} + toString: function () { + var parts = []; + + parts.push(this._type ? "@constructor" : "@factory"); + + parts.push(activationNames[this._activationType]); + + if (typeof (this._type) === "string") + parts.push(this._type); + + return parts.join(" "); + } + + }); + + cls.SINGLETON = SINGLETON_ACTIVATION; + cls.CONTAINER = CONTAINER_ACTIVATION; + cls.CONTEXT = CONTEXT_ACTIVATION; + cls.CALL = CALL_ACTIVATION; + cls.HIERARCHY = HIERARCHY_ACTIVATION; + + var activationNames = [ + "", + "{singleton}", + "{container}", + "{context}", + "{call}", + "{hierarchy}" + ]; + + return cls; + }); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/di/ValueDescriptor.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,38 @@ +define([ "../declare", "./Descriptor", "../safe" ], + +function(declare, Descriptor, safe) { + return declare(Descriptor, { + _value : undefined, + _raw : false, + constructor : function(value, raw) { + this._value = value; + this._raw = Boolean(raw); + }, + + activate : function(context, name) { + context.enter(name, this); + var v = this._raw ? this._value : context.parse( + this._value, + ".params"); + context.leave(this); + return v; + }, + + isInstanceCreated : function() { + return this._raw; + }, + + getInstance : function() { + if (!this._raw) + throw new Error("The instance isn't constructed"); + return this._value; + }, + + toString : function() { + if (this._raw) + return "@value {raw}"; + else + return safe.isNull(this._value) ? "@value <null>" : "@value"; + } + }); +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/log/ConsoleLogChannel.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,30 @@ +define( + [ "dojo/_base/declare", "../text/format" ], + function(declare, format) { + return declare( + null, + { + name : null, + + constructor : function(name) { + this.name = name; + }, + + log : function() { + console.log(this._makeMsg(arguments)); + }, + + warn : function() { + console.warn(this._makeMsg(arguments)); + }, + + error : function() { + console.error(this._makeMsg(arguments)); + }, + + _makeMsg : function(args) { + return this.name ? this.name + " " + + format.apply(null, args) : format.apply(null, args); + } + }); + }); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/log/_LogMixin.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,67 @@ +define([ "dojo/_base/declare" ], + +function(declare) { + var cls = declare(null, { + _logChannel : null, + + _logLevel : 1, + + constructor : function(opts) { + if (typeof opts == "object") { + if ("logChannel" in opts) + this._logChannel = opts.logChannel; + if ("logLevel" in opts) + this._logLevel = opts.logLevel; + } + }, + + getLogChannel : function() { + return this._logChannel; + }, + + setLogChannel : function(v) { + this._logChannel = v; + }, + + getLogLevel : function() { + return this._logLevel; + }, + + setLogLevel : function(v) { + this._logLevel = v; + }, + + log : function(format) { + if (this._logChannel && this._logLevel > 2) + this._logChannel.log.apply(this._logChannel, arguments); + }, + warn : function(format) { + if (this._logChannel && this._logLevel > 1) + this._logChannel.warn.apply(this._logChannel, arguments); + }, + error : function(format) { + if (this._logChannel && this._logLevel > 0) + this._logChannel.error.apply(this._logChannel, arguments); + }, + + /** + * Used to by widgets + */ + startup : function() { + var me = this, parent; + if (!me.getLogChannel()) { + parent = me; + while (parent = parent.getParent()) { + if (parent.getLogChannel) { + me.setLogChannel(parent.getLogChannel()); + if(parent.getLogLevel) + me.setLogLevel(parent.getLogLevel()); + break; + } + } + } + this.inherited(arguments); + } + }); + return cls; +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/log/listeners/console.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,25 @@ +define([], function () { + if (console && console.log) + return function (ch, name, msg) { + + var args = [ch + ":"]; + + switch (name) { + case "warn": + case "error": + case "log": + break; + default: + args.push(name + ":"); + name = "log"; + } + + + if (msg instanceof Array) + args.push.apply(args, msg); + else + args.push(msg); + + console[name].apply(console, args); + }; +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/log/trace.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,116 @@ +define(["../text/format"], function (format) { + 'use strict'; + + var listeners = []; + var channels = {}; + + var Trace = function (name) { + this.name = name; + this._subscribers = []; + }; + + Trace.prototype.debug = function () { + if (Trace.level >= 4) + this.notify("debug", format.apply(null, arguments)); + }; + + Trace.prototype.log = function () { + if (Trace.level >= 3) + this.notify("log", format.apply(null, arguments)); + }; + + Trace.prototype.warn = function () { + if (Trace.level >= 2) + this.notify("warn", format.apply(null, arguments)); + + }; + + Trace.prototype.error = function () { + if (Trace.level >= 1) + this.notify("error", format.apply(null, arguments)); + }; + + Trace.prototype.notify = function (name, msg) { + var me = this; + me._subscribers.forEach(function (cb) { + cb(me, name, msg); + }); + }; + + Trace.prototype.subscribe = function (cb) { + this._subscribers.push(cb); + }; + + Trace.prototype.toString = function () { + return this.name; + }; + + Trace.createChannel = function (type, name, cb) { + var chId = name; + if (channels[chId]) + return channels[chId]; + + var channel = new type(chId); + channels[chId] = channel; + + Trace._onNewChannel(chId, channel); + cb(channel); + }; + + Trace._onNewChannel = function (chId, ch) { + listeners.forEach(function (listener) { + listener(chId, ch); + }); + }; + + Trace.on = function (filter, cb) { + if (arguments.length == 1) { + cb = filter; + filter = undefined; + } + var d, test; + if (filter instanceof RegExp) { + test = function (chId) { + return filter.test(chId); + }; + } else if (filter instanceof Function) { + test = filter; + } else if (filter) { + test = function (chId) { + return chId == filter; + }; + } + + if (test) { + d = function(chId, ch) { + if(test(chId)) + ch.subscribe(cb); + }; + } else { + d = function(chId, ch) { + ch.subscribe(cb); + }; + } + listeners.push(d); + + for(var chId in channels) + d(chId,channels[chId]); + }; + + Trace.load = function (id, require, cb) { + if (id) + Trace.createChannel(Trace, id, cb); + else if (require.module && require.module.mid) + Trace.createChannel(Trace, require.module.mid, cb); + else + require(['module'], function (module) { + Trace.createChannel(Trace, module && module.id, cb); + }); + }; + + Trace.dynamic = true; + + Trace.level = 4; + + return Trace; +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/main.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,3 @@ +declare([], function(){ + // does nothing yet... +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/messaging/Client.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,61 @@ +define( + [ "dojo/_base/declare", "dojo/_base/lang", "dojo/Evented", "../log/_LogMixin" ], + + function(declare, lang, Evented, _LogMixin) { + return declare([ Evented, _LogMixin ], { + _session : null, + _destination : null, + _id : null, + + constructor : function(session, destination, options) { + this._destination = destination; + this._session = session; + }, + + getDestination : function() { + return this._destination; + }, + + start : function() { + var me = this; + return me._session.createClient(me.prepareOptions({})).then( + function(id) { + me._id = id; + return me; + }); + }, + + prepareOptions : function(options) { + var me = this; + options.mode = me.getMode(); + options.destination = me.getDestination(); + options.client = function(msg) { + me.process(msg); + }; + return options; + }, + + process : function(msg) { + this.warn("Messages are not acceped by this client"); + }, + + stop : function() { + var me = this; + if (me._id) { + me.log("stop"); + return me._session.deleteClient({'clientId': me._id}).then(function() { + me._id = null; + return me; + }); + } + }, + + toString : function() { + return "[" + + [ + this.getMode().toUpperCase(), + this.getDestination(), + this._id ].join(',') + "]"; + } + }); + }); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/messaging/Destination.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,34 @@ +define([ "dojo/_base/declare", "./Listener" ], + +function(declare, Listener) { + return declare(null, { + _session : null, + _destination : null, + _listenerClass : null, + + constructor : function(session, destination, options) { + if (!session) + throw new Error("A session is required"); + if (!destination) + throw new Error("A destination is required"); + + this._session = session; + this._destination = destination; + if (options) { + if (options.listenerClass) + this._listenerClass = options.listenerClass; + } + }, + + listen : function(callback) { + var factory = this._listenerClass || Listener; + var listener = new factory(this._session, this._destination, { + listener : callback + }); + listener.start(); + + return listener; + } + + }); +});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/messaging/Listener.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,64 @@ +define([ "dojo/_base/declare", "dojo/_base/lang", "./Client" ], + +function(declare, lang, Client) { + return declare([ Client ], { + _listener : null, + + constructor : function(session, destination, options) { + if (!options || !options.listener) + throw new Error("A listener is required"); + this._listener = options.listener; + if (options.transform) + this._transform = options.transform; + }, + + getMode : function() { + return "listener"; + }, + + process : function(result) { + switch (result.type) { + case "message": + try { + this._handleMessage(result.message); + } catch (ex) { + var err = new Error("Failed to handle message"); + err.envelope = result.message; + err.innerException = ex; + this._handleError(err); + } + break; + case "error": + this._handleError(result.error); + break; + } + + }, + + _transform : function(envelope) { + return envelope; + }, + + _handleMessage : function(envelope) { + this.log( + "MESSAGE type = ${0}, headers = ${2}: ${1}", + envelope.bodyType, + envelope.body, + JSON.stringify(envelope.headers)); + var data = this._transform(envelope); + this._listener(data); + this.emit("message", data); + }, + + _handleError : function(ex) { + if (ex.innerException) + this.error( + "ERROR: ${0} -> ${1}", + ex.message, + ex.innerException.message); + else + this.error("ERROR: ${0}", ex.message); + this.emit("error", ex); + } + }); +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/messaging/Session.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,217 @@ +define( + [ + "dojo/_base/declare", + "dojo/_base/lang", + "dojo/request", + "./Destination", + "dojo/Evented", + "dojo/Deferred", + "../log/_LogMixin" ], + + function(declare, lang, request, Destination, Evented, Deferred, _LogMixin) { + + var cls = declare( + [ Evented, _LogMixin ], + { + _id : null, + _baseUrl : null, + _destinations : null, + _timeout : 100000, + _clients : null, + _started : null, + _starting : false, + + constructor : function(baseUrl, options) { + if (!baseUrl) + throw new Error("baseUrl is required"); + options = options || {}; + + this._baseUrl = baseUrl.replace(/\/*$/, ""); + this._destinations = {}; + this._pending = []; + this._clients = {}; + if (options.timeout) + this._timeout = options.timeout; + + this._started = new Deferred(); + }, + + start : function() { + if (this._starting) + return this._started; + this._starting = true; + + var me = this; + me.log("START"); + request(this._baseUrl, { + method : "POST", + handleAs : "json" + }).then(function(result) { + me._id = result; + me._emitConnected(); + me._poll(); + me._started.resolve(me); + }, function(error) { + me._emitError(error); + me._started.reject(me); + }); + return me._started.promise; + }, + + createClient : function(options) { + if (!options || !options.destination || !options.mode) + throw new Error("Invalid argument"); + + var me = this; + + return me._started + .then(function() { + var url = me._makeUrl(me._id); + me.log( + "CREATE mode=${0}, destination=${1}", + options.mode, + options.destination); + + return request(url, { + method : "POST", + data : { + mode : options.mode, + destination : options.destination + }, + handleAs : 'json' + }) + .then( + function(id) { + me + .log( + "CLIENT id=${0}, mode=${1}, destination=${2}", + id, + options.mode, + options.destination); + me._clients[id] = options.client + ? options.client + : function(msg) { + me + .warn( + "The client id=${0}, mode=${1}, destination=${2} isn't accepting mesages", + id, + options.mode, + options.destination); + }; + return id; + }); + }); + + }, + + deleteClient : function(options) { + if (!options || !options.clientId) + throw new Error("Invalid argument"); + + var me = this, id = options.clientId; + + return me._started.then(function() { + var url = me._makeUrl(me._id, options.clientId); + + me.log("DELETE CLIENT ${0}", options.clientId); + + return request(url, { + method : "DELETE", + handleAs : 'json' + }).then(function() { + me.log("CLIENT DELETED ${0}", options.clientId); + me._clients[id] = undefined; + }); + }); + }, + + _poll : function() { + var me = this, url = this._makeUrl(this._id); + me.log("POLL timeout=${0}", me._timeout); + request(url, { + method : "GET", + handleAs : "json", + query : { + timeout : me._timeout + } + }).then(function(response) { + me._handlePoll(response); + me._poll(); + }, function(err) { + me.error("POLL faield with ${0}", err); + me._emitError(err); + }); + }, + + _handlePoll : function(response) { + if (!response) { + this.log("POLL response undefined, looks like a bug"); + return; + } + if (!response.results || !response.results.length) { + this.log("POLL response is empty"); + return; + } + + var results = response.results; + this.log("POLL got ${0} results", results.length); + + for (var i = 0; i < results.length; i++) { + var result = results[i]; + var client = this._clients[result.clientId]; + if (!client) { + // TODO this could happen due to client isn't + // registered yet + this.error("Unknown client ${0}", result.clientId); + continue; + } + client.call(this, result); + } + }, + + _emitError : function(err) { + this.emit("error", err); + }, + + _emitConnected : function() { + var me = this; + me.log("CONNECTED"); + me.emit("connected"); + }, + + _makeUrl : function() { + var parts = [ this._baseUrl ]; + for (var i = 0; i < arguments.length; i++) + parts.push(arguments[i].replace(/\/*$/, "")); + return parts.join('/'); + }, + + queue : function(name) { + return this._getDestination("queue://" + name); + }, + + topic : function(name) { + return this._getDestination("topic://" + name); + }, + + _getDestination : function(uri) { + if (uri in this._destinations) + return this._destinations[uri]; + + var dest = new Destination(this, uri); + this._destinations[uri] = dest; + return dest; + }, + + toString : function() { + return [ "[", "SESSION ", this._id, "]" ].join(" "); + } + }); + + cls.connect = function(url, options) { + var session = new cls(url, options); + return session.start(); + }; + + return cls; + });
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/safe.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,323 @@ +define([], + + function () { + var _create = Object.create, + _keys = Object.keys; + + var safe = null; + safe = { + argumentNotNull: function (arg, name) { + if (arg === null || arg === undefined) + throw new Error("The argument " + name + " can't be null or undefined"); + }, + + argumentNotEmptyString: function (arg, name) { + if (typeof (arg) !== "string" || !arg.length) + throw new Error("The argument '" + name + "' must be a not empty string"); + }, + + argumentNotEmptyArray: function (arg, name) { + if (!(arg instanceof Array) || !arg.length) + throw new Error("The argument '" + name + "' must be a not empty array"); + }, + + argumentOfType: function (arg, type, name) { + if (!(arg instanceof type)) + throw new Error("The argument '" + name + "' type doesn't match"); + }, + + isNull: function (arg) { + return (arg === null || arg === undefined); + }, + + isPrimitive: function (arg) { + return (arg === null || arg === undefined || typeof (arg) === "string" || + typeof (arg) === "number" || typeof (arg) === "boolean"); + }, + + isInteger: function (arg) { + return parseInt(arg) == arg; + }, + + isNumber: function (arg) { + return parseFloat(arg) == arg; + }, + + isString: function (val) { + return typeof (val) == "string" || val instanceof String; + }, + + isNullOrEmptyString: function (str) { + if (str === null || str === undefined || + ((typeof (str) == "string" || str instanceof String) && str.length === 0)) + return true; + }, + + isNotEmptyArray: function (arg) { + return (arg instanceof Array && arg.length > 0); + }, + + /** + * Выполняет метод для каждого элемента массива, останавливается, когда + * либо достигнут конец массива, либо функция <c>cb</c> вернула + * значение. + * + * @param{Array | Object} obj массив элементов для просмотра + * @param{Function} cb функция, вызываемая для каждого элемента + * @param{Object} thisArg значение, которое будет передано в качестве + * <c>this</c> в <c>cb</c>. + * @returns Результат вызова функции <c>cb</c>, либо <c>undefined</c> + * если достигнут конец массива. + */ + each: function (obj, cb, thisArg) { + safe.argumentNotNull(cb, "cb"); + var i, x; + if (obj instanceof Array) { + for (i = 0; i < obj.length; i++) { + x = cb.call(thisArg, obj[i], i); + if (x !== undefined) + return x; + } + } else { + var keys = _keys(obj); + for (i = 0; i < keys.length; i++) { + var k = keys[i]; + x = cb.call(thisArg, obj[k], k); + if (x !== undefined) + return x; + } + } + }, + + /** + * Копирует свойства одного объекта в другой. + * + * @param{Any} dest объект в который нужно скопировать значения + * @param{Any} src источник из которого будут копироваться значения + * @tmpl{Object|Array} tmpl шаблон по которому будет происходить + * копирование. Если шаблон является массивом + * (список свойств), тогда значения этого массива + * являются именами свойсвт которые будут + * скопированы. Если шаблон является объектом (карта + * преобразования имен свойств src->dst), тогда + * копирование будет осуществляться только + * собственных свойств источника, присутсвующих в + * шаблоне, при этом значение свойства шаблона + * является именем свойства в которое будет + * произведено коприрование + */ + mixin: function (dest, src, tmpl) { + safe.argumentNotNull(dest, "dest"); + if (!src) + return dest; + + var keys, i, p; + if (arguments.length < 3) { + keys = _keys(src); + for (i = 0; i < keys.length; i++) { + p = keys[i]; + dest[p] = src[p]; + } + } else { + if (tmpl instanceof Array) { + for (i = 0; i < tmpl.length; i++) { + p = tmpl[i]; + if (p in src) + dest[p] = src[p]; + } + + } else { + keys = _keys(src); + for (i = 0; i < keys.length; i++) { + p = keys[i]; + if (p in tmpl) + dest[tmpl[p]] = src[p]; + } + } + } + return dest; + }, + + /** Wraps the specified function to emulate an asynchronous execution. + * @param{Object} thisArg [Optional] Object which will be passed as 'this' to the function. + * @param{Function|String} fn [Required] Function wich will be wrapped. + */ + async: function (fn, thisArg) { + if (arguments.length == 2 && !(fn instanceof Function)) + fn = thisArg[fn]; + + if (fn == null) + throw new Error("The function must be specified"); + + function wrapresult(x, e) { + if (e) { + return { + then: function (cb, eb) { + try { + return eb ? wrapresult(eb(e)) : this; + } catch (e2) { + return wrapresult(null, e2); + } + } + }; + } else { + if (x && x.then) + return x; + return { + then : function(cb) { + try { + return cb ? wrapresult(cb(x)) : this; + } catch(e2) { + return wrapresult(e2); + } + } + }; + } + } + + try { + return wrapresult(fn.apply(thisArg, arguments)); + } catch (e) { + return wrapresult(null, e); + }; + }, + + create: function () { + if (console && console.warn) + console.warn("implab/safe::create is deprecated use Object.create instead"); + _create.apply(this, arguments); + }, + + delegate: function (target, method) { + if (!(method instanceof Function)) { + this.argumentNotNull(target, "target"); + method = target[method]; + } + + if (!(method instanceof Function)) + throw new Error("'method' argument must be a Function or a method name"); + + return function () { + return method.apply(target, arguments); + }; + }, + + /** + * Для каждого элемента массива вызывает указанную функцию и сохраняет + * возвращенное значение в массиве результатов. + * + * @remarks cb может выполняться асинхронно, при этом одновременно будет + * только одна операция. + * + * @async + */ + pmap: function (items, cb) { + safe.argumentNotNull(cb, "cb"); + + if (items && items.then instanceof Function) + return items.then(function (data) { + return safe.pmap(data, cb); + }); + + if (safe.isNull(items) || !items.length) + return items; + + var i = 0, + result = []; + + function next() { + var r, ri; + + function chain(x) { + result[ri] = x; + return next(); + } + + while (i < items.length) { + r = cb(items[i], i); + ri = i; + i++; + if (r && r.then) { + return r.then(chain); + } else { + result[ri] = r; + } + } + return result; + } + + return next(); + }, + + /** + * Для каждого элемента массива вызывает указанную функцию, результаты + * не сохраняются + * + * @remarks cb может выполняться асинхронно, при этом одновременно будет + * только одна операция. + * @async + */ + pfor: function (items, cb) { + safe.argumentNotNull(cb, "cb"); + + if (items && items.then instanceof Function) + return items.then(function (data) { + return safe.pmap(data, cb); + }); + + if (safe.isNull(items) || !items.length) + return items; + + var i = 0; + + function next() { + while (i < items.length) { + var r = cb(items[i], i); + i++; + if (r && r.then) + return r.then(next); + } + } + + return next(); + }, + + /** + * Выбирает первый элемент из последовательности, или обещания, если в + * качестве параметра используется обещание, оно должно вернуть массив. + * + * @param{Function} cb обработчик результата, ему будет передан первый + * элемент последовательности в случае успеха + * @param{Fucntion} err обработчик исключения, если массив пустой, либо + * не массив + * + * @remarks Если не указаны ни cb ни err, тогда функция вернет либо + * обещание, либо первый элемент. + * @async + */ + first: function (sequence, cb, err) { + if (sequence) { + if (sequence.then instanceof Function) { + return sequence.then(function (res) { + return safe.first(res, cb, err); + }, err); + } else if (sequence && "length" in sequence) { + if (sequence.length === 0) { + if (err) + return err(new Error("The sequence is empty")); + else + throw new Error("The sequence is empty"); + } + return cb ? cb(sequence[0]) : sequence[0]; + } + } + + if (err) + return err(new Error("The sequence is required")); + else + throw new Error("The sequence is required"); + } + }; + + return safe; + }); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/text/format-compile.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,101 @@ +define( + [], + function() { + var map = { + "\\{" : "&curlopen;", + "\\}" : "&curlclose;", + "&" : "&", + "\\:" : ":" + }; + + var rev = { + curlopen : "{", + curlclose : "}", + amp : "&", + colon : ":" + }; + + var espaceString = function(s) { + if (!s) + return s; + return "'" + s.replace(/('|\\)/g, "\\$1") + "'"; + }; + + var encode = function(s) { + if (!s) + return s; + return s.replace(/\\{|\\}|&|\\:/g, function(m) { + return map[m] || m; + }); + }; + + var decode = function(s) { + if (!s) + return s; + return s.replace(/&(\w+);/g, function(m, $1) { + return rev[$1] || m; + }); + }; + + var subst = function(s) { + var i = s.indexOf(":"), name, pattern; + if (i >= 0) { + name = s.substr(0, i); + pattern = s.substr(i + 1); + } else { + name = s; + } + + if (pattern) + return [ + espaceString(decode(name)), + espaceString(decode(pattern)) ]; + else + return [ espaceString(decode(name)) ]; + }; + + var compile = function(str) { + if (!str) + return function() {}; + + var chunks = encode(str).split("{"), chunk; + + var code = [ "var result=[];" ]; + + for (var i = 0; i < chunks.length; i++) { + chunk = chunks[i]; + + if (i === 0) { + if (chunk) + code.push("result.push(" + espaceString(decode(chunk)) + + ");"); + } else { + var len = chunk.indexOf("}"); + if (len < 0) + throw new Error("Unbalanced substitution #" + i); + + code.push("result.push(subst(" + + subst(chunk.substr(0, len)).join(",") + "));"); + if (chunk.length > len + 1) + code.push("result.push(" + + espaceString(decode(chunk.substr(len + 1))) + ");"); + } + } + + code.push("return result.join('');"); + + /* jshint -W054 */ + return new Function("subst", code.join("\n")); + }; + + var cache = {}; + + return function(template) { + var compiled = cache[template]; + if (!compiled) { + compiled = compile(template); + cache[template] = compiled; + } + return compiled; + }; + }); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/text/format.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,87 @@ +define([ + "../safe", + "./format-compile", + "dojo/number", + "dojo/date/locale", + "dojo/_base/array" ], function(safe, compile, number, date, array) { + + // {short,medium,full,long}-{date,time} + var convert = function(value, pattern) { + if (!pattern) + return value.toString(); + + if (pattern.toLocaleLowerCase() == "json") { + var cache = []; + return JSON.stringify(value, function(k, v) { + if (!safe.isPrimitive(v)) { + var id = array.indexOf(cache, v); + if (id >= 0) + return "@ref-" + id; + else + return v; + } else { + return v; + } + },2); + } + + if (safe.isNumber(value)) { + var nopt = {}; + if (pattern.indexOf("!") === 0) { + nopt.round = -1; + pattern = pattern.substr(1); + } + nopt.pattern = pattern; + return number.format(value, nopt); + } else if (value instanceof Date) { + var m = pattern.match(/^(\w+)-(\w+)$/); + if (m) + return date.format(value, { + selector : m[2], + formatLength : m[1] + }); + else if (pattern == "iso") + return value.toISOString(); + else + return date.format(value, { + selector : "date", + datePattern : pattern + }); + } else { + return value.toString(pattern); + } + }; + + function formatter(format) { + var data; + + if (arguments.length <= 1) + return format; + + data = Array.prototype.slice.call(arguments, 1); + + var template = compile(format); + + return template(function(name, pattern) { + var value = data[name]; + return !safe.isNull(value) ? convert(value, pattern) : ""; + }); + } + + formatter.compile = function(format) { + var template = compile(format); + + return function() { + var data = arguments; + + return template(function(name, pattern) { + var value = data[name]; + return !safe.isNull(value) ? convert(value, pattern) : ""; + }); + }; + }; + + formatter.convert = convert; + + return formatter; +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/js/text/template-compile.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,134 @@ +define( + ["dojo/request", "./format", "../log/trace!"], + function (request, format, trace) { + + // разбивает строку шаблона на токены, возвращает контекст для + // дальнейшей обработки в visitTemplate + var parseTemplate = function (str) { + var tokens = str.split(/(<%=|\[%=|<%|\[%|%\]|%>)/); + var pos = -1; + var data = [], + code = []; + + return { + next: function () { + pos++; + return pos < tokens.length; + }, + token: function () { + return tokens[pos]; + }, + pushData: function () { + var i = data.length; + data.push.apply(data, arguments); + return i; + }, + pushCode : function() { + var i = code.length; + code.push.apply(code, arguments); + return i; + }, + compile: function () { + var text = "var $p = [];\n" + + "var print = function(){\n" + + " $p.push(format.apply(null,arguments));\n" + + "};\n" + + // Introduce the data as local variables using with(){} + "with(obj){\n" + + code.join("\n") + + "}\n" + + "return $p.join('');"; + + try { + var compiled = new Function("obj, format, $data", text); + /** + * Функция форматирования по шаблону + * + * @type{Function} + * @param{Object} obj объект с параметрами для подстановки + */ + return function (obj) { + return compiled(obj || {}, format, data); + }; + } catch (e) { + trace.error([e]); + trace.log([text, data]); + throw e; + } + } + } + }; + + function visitTemplate(context) { + while (context.next()) { + switch (context.token()) { + case "<%": + case "[%": + visitCode(context); + break; + case "<%=": + case "[%=": + visitInline(context); + break; + default: + visitTextFragment(context); + break; + } + } + } + + function visitInline(context) { + var code = ["$p.push("]; + while (context.next()) { + if (context.token() == "%>" || context.token() == "%]") + break; + code.push(context.token()); + } + code.push(");"); + context.pushCode(code.join('')); + } + + function visitCode(context) { + var code = []; + while (context.next()) { + if (context.token() == "%>" || context.token() == "%]") + break; + code.push(context.token()); + } + context.pushCode(code.join('')); + } + + function visitTextFragment(context) { + var i = context.pushData(context.token()); + context.pushCode("$p.push($data["+i+"]);"); + } + + var compile = function (str) { + if (!str) + return function() { return "";}; + + var ctx = parseTemplate(str); + visitTemplate(ctx); + return ctx.compile(); + }; + + var cache = {}; + + compile.load = function (id, require, callback) { + var url = require.toUrl(id); + if (url in cache) { + callback(cache[url]); + } else { + request(url).then(compile).then(function (tc) { + callback(cache[url] = tc); + }, function (err) { + require.signal("error", [{ + error: err, + src: 'implab/text/template-compile' + }]); + }); + } + }; + + return compile; + }); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/.project Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>dom</name> + <comment>Project dom created by Buildship.</comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.buildship.core.gradleprojectbuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.buildship.core.gradleprojectnature</nature> + </natures> +</projectDescription>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/.settings/org.eclipse.buildship.core.prefs Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,2 @@ +connection.project.dir=.. +eclipse.preferences.version=1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/build.gradle Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,2 @@ +task build(type: Copy) { +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/package.json Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,18 @@ +{ + "name": "@implab/dom", + "version": "1.0.1", + "description": "Dependency injection, logging, simple and fast text template engine", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "di", + "ioc", + "logging", + "template engine", + "dependency injection" + ], + "author": "Sergey Smirnov", + "license": "MIT" +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/src/js/css.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,10 @@ +define(["./inject"], function (inject) { + return { + load: function (id, require, cb) { + var url = require.toUrl(id); + inject.injectStylesheet(url).then(function () { + cb(); + }); + } + }; +}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/src/js/inject.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,86 @@ +define(["../Deferred", "../log/trace!"], function (Deferred, trace) { + function on(node, eventName, handler) { + // Add an event listener to a DOM node + node.addEventListener(eventName, handler, false); + + return function () { + node.removeEventListener(eventName, handler, false); + }; + } + + return { + injectionPoint: document.head, + injectBefore: document.head.firstChild, + + _map: {}, + + _inject: function (name, attr) { + var node = document.createElement(name), + d = new Deferred(), + + cleanup = function () { + noerr(); + noload(); + }, + + noload = on(node, "load", function () { + d.resolve({ + node: node + }); + cleanup(); + }, true), + + noerr = on(node, "error", function (e) { + d.reject({ + erorr: e, + node: node + }); + cleanup(); + }, true); + + for (var p in attr) + node[p] = attr[p]; + + this.injectionPoint.insertBefore(node, this.injectBefore); + return d; + }, + + injectScript: function (url) { + var d = this._map[url]; + if (!d) { + trace.log("js {0}", url); + d = this._inject("script", { + type: "text/javascript", + charset: "utf-8", + src: url + }); + d.then(function () { + trace.log("done {0}", url); + }, function (e) { + trace.err([url, e]); + }); + this._map[url] = d; + } + return d; + }, + + injectStylesheet: function (url) { + var d = this._map[url]; + if (!d) { + trace.log("css {0}", url); + d = this._inject("link", { + type: "text/css", + rel: "stylesheet", + href: url + }); + d.then(function () { + trace.log("done {0}", url); + }, function (e) { + trace.error([url, e]); + }); + this._map[url] = d; + } + return d; + } + }; +}); \ No newline at end of file
--- a/npm/implab/index.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -/** - * Created by internet on 6/21/16. - */ -'user strict'; -/*===== - return { - // summary: - // The implab package main module; implab package is somewhat unusual in that the main module currently just provides an empty object. - // Apps should require modules from the implab packages directly, rather than loading this module. - }; - =====*/ - -/** - The entry point - @module implab - */ - -module.exports = {}; \ No newline at end of file
--- a/npm/implab/package.json Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -{ - "name": "implab", - "version": "1.0.1", - "description": "Dependency injection, logging, simple and fast text template engine", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "di", - "ioc", - "logging", - "template engine", - "dependency injection" - ], - "author": "Sergey Smirnov", - "license": "MIT" -}
--- a/settings.gradle Sat Jun 23 21:50:11 2018 +0300 +++ b/settings.gradle Tue Jun 26 19:35:44 2018 +0300 @@ -12,4 +12,7 @@ //include 'sub-project-name' +include 'core' +include 'dom' + rootProject.name = 'implab' \ No newline at end of file
--- a/src/djol/BaseLayer.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -define([ - "implab/text/template-compile", - "dojo/_base/declare", - "dojo/_base/lang", - "ol"], - function (compile, declare, lang, ol) { - return declare([ol.layer.Layer], { - - name: null, - - displayName: null, - - identifyResultTemplate: null, - - searchResultTemplate: null, - - constructor: function () { - lang.mixin(this, arguments[0]); - var identifyCompiledTemplate = null, searchCompiledTemplate = null; - if (this.identifyResultTemplate) { - identifyCompiledTemplate = compile(this.identifyResultTemplate); - } - if (this.searchResultTemplate) { - searchCompiledTemplate = compile(this.searchResultTemplate); - } - }, - - /** Возвращает массив строк, каждая строка - результат поиска приведенный к шаблонному виду - @options {Object} - @str {String} поисковая строка - @bbox {Object} bound box, в рамках которого осуществлять поиск - */ - getSearchResult: function (options) { - console.warn("Метод необходимо переопределить для для слоя конкретного типа!"); - }, - /** Возвращает массив строк, каждая строка - результат идентификации приведенный к шаблонному виду - @options {Object} - @coordinates {Array} массив описывающий координаты точки идентификации - */ - getItentifyResult: function (coordinates) { - console.warn("Метод необходимо переопределить для для слоя конкретного типа!"); - } - }); - }) \ No newline at end of file
--- a/src/djol/ClearTool.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -define (["dojo/_base/declare", "./_OneshotTool", "implab/safe"] , function(declare, _OneshotTool, safe) { - return declare([_OneshotTool], { - tools : null, - - constructor : function(opts) { - safe.mixin(this,opts, ["tools"]); - }, - - invoke : function() { - if (this.tools) { - this.log("Clear {0} tools", this.tools.length); - safe.each(this.tools, function(tool) { - if (tool.clear) - tool.clear(); - }); - } - } - }); -}); \ No newline at end of file
--- a/src/djol/CoordPickerTool.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -define (["dojo/_base/declare", "./_OneshotTool", "implab/safe", "dojo/when"] , function(declare, _OneshotTool, safe, when) { - return declare([_OneshotTool], { - _map : null, - _proj : null, - - constructor : function(opts) { - safe.argumentNotNull(opts && opts.map, "opts.map"); - - this._map = opts.map; - this._proj = opts.proj; - }, - - invoke : function() { - var me = this; - - return when(me._map.awaitMapEvent('singleclick'), function(evt){ - if (me._proj) { - // тут можно преобразовать проекции - } - return evt; - }); - } - }); -}); \ No newline at end of file
--- a/src/djol/DeactivationTool.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -define(["dojo/_base/declare", "./_ToolBase"],function(declare, _ToolBase) { - - // Инструмент, выключает текущий активный инструмент - // Данный инструмент ничго не делает, но при его активации будет - // деактивирован предыдущий инструмент - return declare([_ToolBase], { - - // данный инструмент не может быть активным, поэтому данный метод - // переопределяется и возвращает всегда false - onActivating : function() { - return false; - } - }); -}); \ No newline at end of file
--- a/src/djol/DistanceMeasureTool.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -define([ - "dojo/_base/declare", - "implab/safe", - "./MeasureToolBase", - "implab/text/format", - "dojo/i18n!./format/nls/units", - "ol" ], - -function(declare, safe, MeasureToolBase, format, units, ol) { - return declare([ MeasureToolBase ], { - - isGeodesic : true, - - units : 'metric', - - constructor : function(opts) { - if (opts) - safe.mixin(this,opts,["isGeodesic", "units"]); - }, - - _createDraw : function(source) { - return new ol.interaction.Draw( - { - source : source, - type : "LineString", - style : this.drawStyle - }); - }, - - _formatTooltip : function(sketch, proj) { - var length = 0; - if (this.isGeodesic) { - var points = sketch.getGeometry().getCoordinates(); - var t = ol.proj.getTransform(proj, "EPSG:4326"); - for (var i = 0; i < points.length - 1; i++) { - length += this.wgs84Sphere.haversineDistance( - t(points[i]), - t(points[i + 1])); - } - } else { - length = sketch.getGeometry().getLength(); - } - - var mpu, unitName; - switch (this.units) { - case "nautical": - mpu = 1852; - unitName = units.nmiles; - break; - default: - mpu = 1000; - unitName = units.kilometers; - } - - if (length >= mpu) { - return format("{0:#.0#}{1}", length / mpu, unitName); - } else { - return format("{0:#0.0#}{1}", length, units.meters); - } - } - - }); -}); \ No newline at end of file
--- a/src/djol/DynamicStyle.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -define([ "./declare-style", "dojo/_base/declare", "ol", "implab/safe" ], - -function(declare, dojoDeclare, ol, safe) { - return declare([], { - _cache : null, - _getKey : null, - _getZoom : null, - - defaultStyle : null, - - style : null, - - styleFunction : null, - - filter : null, - - constructor : function(opts) { - if (opts) - dojoDeclare.safeMixin(this, opts); - - this._cache = {}; - - if (this.zoom) { - if (this.zoom instanceof Function) { - this._getZoom = this.zoom; - } else { - var levels = [], max = "max"; - for ( var p in this.zoom) { - if (safe.isNumber(this.zoom[p])) - levels.push({ - name : p, - zoom : Number(this.zoom[p]) - }); - else if (this.zoom[p] == "max") - max = p; - } - - levels.sort(function(x, y) { - return x.zoom - y.zoom; - }); - - this.zoomMax = max; - this.zoomLevels = levels; - - this._getZoom = function(z) { - for (var i = 0; i < levels.length; i++) { - if (z <= levels[i].zoom) - return levels[i].name; - } - return max; - }; - } - } else { - this._getZoom = function(z) { - return "max"; - }; - } - - if (this.key) { - if (this.key instanceof Function) { - this._getKey = this.key; - } else if (typeof this.key === "string") { - this._getKey = function(ft) { - return ft.get(this.key); - }; - } else { - this._getKey = function(ft, z) { - var k = this.key[z]; - if (k instanceof Function) - return k.call(this, ft, z); - else if (typeof k == "string") - return ft.get(k); - else - return this.defaultStyle; - }; - } - } else { - this._getKey = function() { - return this.defaultStyle; - }; - } - - if (this.style) { - if (this.style instanceof Function) { - this._style = this.style; - } else { - this._style = function(ft, res, key, zoom) { - var s = this.style[zoom]; - return s && (s instanceof Function) ? s.apply( - this, - arguments) : s; - }; - } - } - }, - - getFeatureStyle : function(ft, res) { - safe.argumentNotNull(ft, "ft"); - - if (this.filter && this.filter(ft) === false) - return null; - - var z = this._getZoom(res); - var k = this._getKey(ft, z); - - var cid = [ k, z ].join('-'); - - var style = this._cache[cid]; - if (!style) { - style = this._style ? this._style(ft, res, k, z) : null; - this._cache[cid] = style; - } - - - return safe.isNull(style) || style instanceof Array ? style : [ style ]; - } - - }); -}); \ No newline at end of file
--- a/src/djol/IdentificationTool.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,246 +0,0 @@ -define([ - "dijit/layout/ContentPane", - "dojo/_base/declare", - "dojo/Deferred", - "dojo/dom-construct", - "dojo/dom-class", - "dojo/on", - "dojo/promise/all", - "dojo/when", - "implab/safe", - "ol", - "./listen", - "./IdentifyGroup", - "./_ToolBase", - "./PopupContainer" - ], - - function ( - ContentPane, - declare, - Deffered, - domConstruct, - domClass, - on, - promiseAll, - when, - safe, - ol, - listen, - IdentifyGroup, - _ToolBase, - PopupContainer) { - return declare([_ToolBase], { - /** - * массив обработчиков openLayers, которые необходимо удалить при - * деактивации - */ - _handlers: null, - /** - * widget карты - */ - _map: null, - /** - * openLayers map - */ - _olMap: null, - /** - * Массив overlays содержащих popupContainers - */ - _popupOverlays: null, - /** - * Массив popups контейнеров - */ - _popupContainers: null, - /** - * Режим работы инструмента идентификации - * - * @value {String} "single"||"multiple" - */ - mode: null, - /** - * Режимы - */ - appManager: null, - - constructor: function (options) { - safe.argumentNotNull(options, "options"); - safe.argumentNotNull(options.map, "options.map"); - safe.argumentNotNull(options.appManager, "options.appManager"); - - this._map = options.map; - this._olMap = options.map.olMap; - this._popupContainers = []; - this._popupOverlays = []; - this._handlers = []; - - this.appManager = options.appManager; - this.mode = options.mode || "single"; - }, - /** - */ - createPopupContent: function (groupWidgets) { - var contentWidget = new ContentPane(); - groupWidgets.forEach(function (groupWidget) { - if (groupWidget && !groupWidget.isEmpty()) { - contentWidget.addChild(groupWidget); - } - }); - return contentWidget; - }, - - /** - * Возвращает обещание на получение объекта с результатом идентификации - * по всем видимым режимам и информационным слоям @ options {Object} @ pixel - * {Object} - информация о точке идентификации @ coordinate {Array} - - * координаты точки иденификации - */ - getGroupsFromVisibleModules: function (options) { - var promises = []; - var modules = this.appManager.getVisibleModules(); - modules.forEach(function (module) { - promises.push.apply(promises, module - .getIdentifyResult(options)); - }); - - return promiseAll(promises).then( - function (results) { - console.log("promise all groups = ", results); - return results; - }); - }, - - identifyPosition: function (position) { - var me = this, i; - var popupContainer = null, - popupOverlay = null; - if (me.mode == "multiple") { - // TODO: создать popupContainer и popupOverlay - popupContainer = new PopupContainer({ - map: me._olMap - }); - on(popupContainer, "close", function () { - var index = me._popupContainers.indexOf(me); - me._popupContainers.splice(index, 1); - - }); - me._popupContainers.push(popupContainer); - - popupOverlay = new ol.Overlay({ - element: popupContainer.domNode, - autoPan: true, - autoPanAnimation: { - duration: 250 - } - }); - me._popupOverlays.push(popupOverlay); - me._olMap.addOverlay(popupOverlay); - - } else { - if (me._popupContainers.length > 0) { - // Берем первый - popupContainer = me._popupContainers[0]; - // Все остальные удалить - if (me._popupContainers.length > 1) { - for (i = 1; i < me._popupContainers.length; i++) { - me._popupContainers[i].destroyRecursive(); - } - me._popupContainers.splice( - 1, - me._popupContainers.length - 1); - } - } else { - // Создаем новый - popupContainer = new PopupContainer({ - map: me._olMap - }); - on(popupContainer, "close", function () { - var index = me._popupContainers.indexOf(me); - me._popupContainers.splice(index, 1); - - }); - me._popupContainers.push(popupContainer); - } - if (me._popupOverlays.length > 0) { - // Берем первый и помещаем в него popup - popupOverlay = me._popupOverlays[0]; - popupOverlay.setElement(popupContainer.domNode); - // Все остальные удалить - if (me._popupOverlays.length > 1) { - for (i = 1; i < me._popupOverlays.length; i++) { - me._olMap.removeOverlay(me._popupOverlays[i]); - } - me._popupOverlays.splice( - 1, - me._popupOverlays.length - 1) - } - } else { - // Создаем новый и помещаем в него popup - popupOverlay = new ol.Overlay({ - element: popupContainer.domNode, - autoPan: true, - autoPanAnimation: { - duration: 250 - } - }); - me._popupOverlays.push(popupOverlay); - me._olMap.addOverlay(popupOverlay); - } - } - - popupContainer.destroyDescendants(); - - popupOverlay.setPosition(position.coordinate); - - popupContainer.showOverlay(); - - when(me.getGroupsFromVisibleModules(position), function (data) { - var contentWidget = me.createPopupContent(data); - popupContainer.show(contentWidget, "only"); - popupContainer.hideOverlay(); - }); - }, - /** - * Скрыть все popups - */ - hideAllPopups: function () { - var me = this, i; - for (i = 0; i < this._popupContainers.length; i++) { - this._popupContainers[i].destroyRecursive(); - } - this._popupContainers.splice(0, this._popupContainers.length); - - for (i = 0; i < this._popupOverlays.length; i++) { - this._olMap.removeOverlay(this._popupOverlays[i]); - } - this._popupOverlays.splice(0, this._popupOverlays.length) - }, - - onActivating: function () { - var me = this; - // Обработчик для события "singleclick" по карте - var handler = listen(this._olMap, 'singleclick', function (evt) { - if (evt.originalEvent.ctrlKey) { - me.mode = "multiple"; - } else { - me.mode = "single"; - } - me.identifyPosition({ - pixel: evt.pixel, - coordinate: evt.coordinate - }); - }); - this._handlers.push(handler); - }, - - onDeactivating: function () { - var me = this; - me._handlers.forEach(function (handler) { - if (handler.remove) - handler.remove(); - - }); - this.hideAllPopups(); - }, - }) - }); \ No newline at end of file
--- a/src/djol/IdentifyGroup.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -define( - [ - "implab/safe", - 'dijit/_WidgetBase', - 'dijit/_TemplatedMixin', - "dijit/_WidgetsInTemplateMixin", - "dijit/layout/_LayoutWidget", - "dijit/layout/ContentPane", - "dojo/_base/declare", - "dojo/dom-construct", - "dojo/on", - "ol3/IdentifyItem" ], - function( - safe, - _WidgetBase, - _TemplatedMixin, - _WidgetsInTemplateMixin, - _LayoutWidget, - ContentPane, - declare, - domConstruct, - on, - IdentifyItem) { - - return declare( - [ _LayoutWidget, _TemplatedMixin, _WidgetsInTemplateMixin ], - { - - /** - */ - _empty : true, - /** - */ - layerName : null, - /** - * Шаблон всего widget - */ - templateString : "<div class='identify-item-group'><div data-dojo-attach-point='identifyItemGroupTitle' class='identify-item-group-title'></div><div class='identify-item-group-content-container' data-dojo-attach-point='containerNode'></div></div>", - - itemTemplate : "", - - title : null, - - /** - * Метод из widget.lifecycle - */ - postCreate : function() { - var me = this; - if (typeof this.title == "string") { - this.identifyItemGroupTitle.innerHTML = me.title; - } else if (me.title && me.title.placeAt) { - me.title.placeAt(me.identifyItemGroupTitle, "only"); - } else { - domConstruct.place( - me.title, - me.identifyItemGroupTitle, - "only"); - } - on(this.domNode, "click", function() { - if ("function" == typeof me.callback) { - me.callback(); - } - }); - }, - - addItem : function(options) { - safe.argumentNotNull(options, "options"); - safe.argumentNotNull(options.model, "options.model"); - - if (options.model) { - - var item = new IdentifyItem({ - title : options.title || this.itemTemplate, - model : options.model, - callback : options.callback - }); - this.addChild(item); - this._empty = false; - } else { - console - .error("Не задано необходимое свойство layerFeature"); - } - }, - - isEmpty : function() { - return this._empty; - } - }); - }); \ No newline at end of file
--- a/src/djol/IdentifyItem.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -define([ - 'dijit/_WidgetBase', - 'dijit/_TemplatedMixin', - "dijit/Tooltip", - "dojo/_base/declare", - "dojo/date/locale", - "dojo/dom-construct", - "dojo/on" ], function(_WidgetBase, _TemplatedMixin, Tooltip, declare, - dateLocale, domConstruct, on) { - var empty = {}; - return declare([ _WidgetBase, _TemplatedMixin ], { - - callback : null, - - dateLocale : dateLocale, - - baseClass : 'identify-item', - - feature : null, - - model : empty, - - title : null, - - templateString : "<div class='identify-item'></div>", - - constructor : function(options) { - option = options || {}; - if (options.title) - this.title = options.title; - if (options.model) - this.model = options.model; - if (options.callback) - this.callback = options.callback; - - }, - - /** - * Метод из widget.lifecycle - */ - postCreate : function() { - var me = this; - - var content = me.title instanceof Function ? me.title(me) - : me.title; - - if (typeof content == "string") { - me.domNode.innerHTML = content; - } else if (content && content.placeAt) { - content.placeAt(me.domNode, "only"); - } else { - domConstruct.place(content, me.domNode, "only"); - } - - on(me.domNode, "click", function() { - if (typeof me.callback == "function") { - me.callback(me.model); - } - }); - }, - }); -}); \ No newline at end of file
--- a/src/djol/ImageLayer.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -define(["ol"], function(ol) { - return ol.layer.Image -}) \ No newline at end of file
--- a/src/djol/ImageWMSSource.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -define(["ol"], function(ol) { - return ol.source.ImageWMS; -}) \ No newline at end of file
--- a/src/djol/LayerCheckBox.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -define([ - "dojo/_base/declare", - "dijit/_WidgetBase", - "dijit/_TemplatedMixin", - "dijit/_WidgetsInTemplateMixin", - "dojo/text!./resources/LayerCheckBoxTemplate.html", - "dijit/form/CheckBox" ], function(declare, _WidgetBase, _TemplatedMixin, - _WidgetsInTemplateMixin, templateString) { - return declare([ _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin ], { - templateString : templateString, - labelNode : null, - checkBox : null, - - label : "", - _setLabelAttr : { - node : "labelNode", - type : "innerHTML" - }, - - name : "layer", - - _layer : null, - - constructor : function(options) { - options = options || {}; - - if (!options.layer) - throw new Error("The layer is required"); - - this._layer = options.layer; - this.label = options.layer.get("label") || "unnamed"; - }, - - postCreate : function() { - var me = this; - me.inherited(arguments); - - me.checkBox.set('name', me.name); - me.checkBox.set('value', me._layer.getVisible()); - this.checkBox.on("change", function(value) { - me._changed(value); - }); - }, - - _changed : function(visible) { - this._layer.setVisible(visible); - } - }); -}); \ No newline at end of file
--- a/src/djol/LayerRadioButton.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -define([ - "dojo/_base/declare", - "dijit/_WidgetBase", - "dijit/_TemplatedMixin", - "dijit/_WidgetsInTemplateMixin", - "dojo/text!./resources/LayerRadioButtonTemplate.html", - "dijit/form/RadioButton" ], function(declare, _WidgetBase, _TemplatedMixin, - _WidgetsInTemplateMixin, templateString) { - return declare([ _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin ], { - templateString : templateString, - - labelNode : null, - radioButton : null, - - label : "", - _setLabelAttr : { - node : "labelNode", - type : "innerHTML" - }, - - name : "layers", - - _layer : null, - - constructor : function(options) { - options = options || {}; - - if (!options.layer) - throw new Error("The layer is required"); - - this._layer = options.layer; - this.label = options.layer.get("label") || "unnamed"; - }, - - postCreate : function() { - var me = this; - me.inherited(arguments); - - me.radioButton.set('name', me.name); - me.radioButton.set('value', me._layer.getVisible()); - this.radioButton.on("change", function(value) { - me._changed(value); - }); - }, - - _changed : function(visible) { - this._layer.setVisible(visible); - } - }); -}); \ No newline at end of file
--- a/src/djol/LayerSwitcher.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -define([ - "dojo/_base/declare", - "require", - "dijit/_WidgetBase", - "dijit/_TemplatedMixin", - "dijit/_WidgetsInTemplateMixin", - "dojo/text!./resources/LayerSwitcherTemplate.html", - "./LayerCheckBox", - "./LayerRadioButton", - "app/view/Container" ], - -function(declare, require, _WidgetBase, _TemplatedMixin, - _WidgetsInTemplateMixin, templateString, LayerCheckBox, LayerRadioButton) { - - return declare([ _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin ], { - templateString : templateString, - requireScope : require, - _layers : null, - _map : null, - - infoLayersLabel : "Layers", - _setInfoLayersLabelAttr : { - node : "infoLayersLabelNode", - type : "innerHTML" - }, - - baseLayersLabel : "Base", - _setBaseLayersLabelAttr : { - node : "baseLayersLabelNode", - type : "innerHTML" - }, - - constructor : function(options) { - options = options || {}; - - if (!options.map) - throw new Error("The map is required"); - - this._map = options.map; - - if (options.layers && options.layers instanceof Array) - this._layers = options.layers; - else - this._layers = []; - - // this.baseLayersLabel = "Base"; - - }, - - postCreate : function() { - this.inherited(arguments); - - var pending = []; - - for ( var i in this._layers) { - if (this._layers[i].get("layerType") != "base") - pending.push(this._layers[i]); - else - this._addLayer(this._layers[i]); - } - - for ( var i in pending) - this._addLayer(pending[i]); - }, - - _addLayer : function(layer) { - this._map.addLayer(layer); - - if (layer.get("layerType") === "base") { - this.baseLayersContainer.addChild(new LayerRadioButton({ - layer : layer - })); - } else { - this.infoLayersContainer.addChild(new LayerCheckBox({ - layer : layer - })); - } - }, - - }); -}); \ No newline at end of file
--- a/src/djol/Map.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,176 +0,0 @@ -define([ - "dijit/registry", - "dojo/_base/declare", - "dijit/_WidgetBase", - "dojo/dom-construct", - "./PopupContainer", - "dojo/_base/array", - "ol", - "ol3/listen", - "dojo/Deferred", - "implab/safe" -], function (registry, declare, _WidgetBase, dom, PopupContainer, array, ol, listen, Deferred, safe) { - - return declare([_WidgetBase], { - popupOverlays: null, - olMap: null, - - _pending: null, - - constructor: function () { - this._pending = {}; - }, - - buildRendering: function () { - this.domNode = dom.create("div"); - }, - - postCreate: function () { - this.inherited(arguments); - this.popupOverlays = {}; - this.olMap = new ol.Map({ - target: this.domNode, - layers: this.layers, - view: this.view, - controls: this.controls || [], - }); - }, - - getProjection : function() { - return this.view.getProjection(); - }, - - addInteraction: function (value) { - this.olMap.addInteraction(value); - }, - - addLayer: function (layer) { - if (layer) { - if (layer.get("layerType") == "base") - this.olMap.getLayers().insertAt(0, layer); - else - this.olMap.addLayer(layer); - } - }, - - removeLayer: function(layer) { - this.olMap.removeLayer(layer); - }, - - startup: function () { - this.inherited(arguments); - - this.olMap.updateSize(); - }, - - showPopup: function (contentWidget, position, opts) { - // Скрыть popups указанной в opts.role роли, если (opts.hint == - // "replace") - // Если не задан opts или opta.hint скрывать все popup - - var me = this; - - if ((!opts) || (!opts.hint)) { - this.closeAllPopups(); - } else if ((opts.hint) && (opts.hint == "replace")) { - if (opts.role) { - this.closePopupsByRole(opts.role); - } else { - this.closeAllPopups(); - } - } - var overlay = new ol.Overlay({}); - - if (opts && (opts.role)) { - if (this.popupOverlays[opts.role]) { - this.popupOverlays[opts.role].push(overlay); - } else { - this.popupOverlays[opts.role] = [overlay]; - } - } - - // Отображение popUp start - this.olMap.addOverlay(overlay); - var popup = new PopupContainer({ - overlay: overlay, - map: this.olMap, - onClose: function () { - // registry.byNode(overlay.getElement()).destroyRecursive(); - array.forEach(me.popupOverlays[opts.role], function (o) { - if (o === overlay) { - var index = me.popupOverlays[opts.role].indexOf(o); - if (index > -1) { - me.popupOverlays[opts.role].splice(index, 1); - } - } - }); - } - }); - overlay.setElement(popup.domNode); - popup.show(contentWidget); - overlay.setPosition(position); - popup.hideOverlay(); - // end - return popup; - }, - - closeAllPopups: function () { - var overlays = this.olMap.getOverlays(); - overlays.forEach(function (elenemt, index) { - registry.byNode(elenemt.getElement()).destroyRecursive(); - }, this); - this.popupOverlays = {}; - }, - - closePopupsByRole: function (role) { - if (this.popupOverlays[role]) { - array.forEach(this.popupOverlays[role], function (overlay) { - registry.byNode(overlay.getElement()).destroyRecursive(); - }); - this.popupOverlays[role] = []; - } - }, - - /** - * Подписывается на событие карты - * - * @param {String} - * name Имя события - * @param {function(evt)} - * filter Фильтр того, что событие нужное - * - * @returns {ol.ObjectEvent | ol.MapBroeserEvent | ol.MapEvent} Событие - * на которое подписались. - */ - awaitMapEvent: function (name, filter) { - safe.argumentNotEmptyString(name, "name"); - var map = this.olMap, - handle, d, me = this; - - if (me._pending[name]) - throw new Error("An event is already pending: " + name); - - me._pending[name] = d = new Deferred(function () { - handle.remove(); - }); - - handle = listen.once(map, name, function (evt) { - if (!filter || filter(evt)) - d.resolve(evt); - }); - - return d.then(function (evt) { - delete me._pending[name]; - return evt; - }, function (err) { - delete me._pending[name]; - throw err; - }); - }, - - cancelPendingEvents: function () { - for (var name in this._pending) - this._pending[name].cancel(); - } - }); -}); \ No newline at end of file
--- a/src/djol/MeasureToolBase.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,181 +0,0 @@ -define([ - "dojo/_base/declare", - "implab/safe", - "ol", - "./listen", - "./_ToolBase", - "dojo/dom-construct", - "dojo/dom-class" -], function (declare, safe, ol, listen, _ToolBase, dconstruct, dclass) { - return declare([_ToolBase], { - _draw: null, - - drawStyle: new ol.style.Style({ - fill: new ol.style.Fill({ - color: 'rgba(255, 255, 255, 0.2)' - }), - stroke: new ol.style.Stroke({ - color: 'rgba(230, 126, 34, 0.7)', - lineDash: [10, 10], - width: 2 - }), - image: new ol.style.Circle({ - radius: 5, - stroke: new ol.style.Stroke({ - color: 'rgba(0, 0, 0, 0.7)' - }), - fill: new ol.style.Fill({ - color: 'rgba(255, 255, 255, 0.2)' - }) - }) - }), - - vectorStyle: new ol.style.Style({ - fill: new ol.style.Fill({ - color: 'rgba(255, 255, 255, 0.2)' - }), - stroke: new ol.style.Stroke({ - color: '#ffcc33', - width: 2 - }), - image: new ol.style.Circle({ - radius: 7, - fill: new ol.style.Fill({ - color: '#ffcc33' - }) - }) - }), - - _map: null, - - _olMap: null, - - _measureTooltipElement: null, - /** - * Overlay to show the measurement. - * - * @type {ol.Overlay} - */ - _measureTooltip: null, - - _pointermoveKey: null, - - _sketch: null, - - _overlays: null, - - _vector: null, - - wgs84Sphere: new ol.Sphere(6378137), - - constructor: function (options) { - safe.argumentNotNull(options, "options"); - safe.argumentNotNull(options.map, "map"); - - this._map = options.map; - this._olMap = options.map.olMap; - this._overlays = []; - }, - - init: function () { - if (this._draw) - return; - - var source = new ol.source.Vector(); - - this._vector = new ol.layer.Vector({ - source: source, - style: this.vectorStyle - }); - this._map.addLayer(this._vector); - - this._draw = this._createDraw(source); - this._draw.on('drawstart', this._onDrawStart, this); - this._draw.on('drawend', this._onDrawEnd, this); - - }, - - onActivating: function () { - this.init(); - - this._pointermoveKey = listen(this._olMap, 'pointermove', safe.delegate(this, "_onPointerMove")); - this._olMap.addInteraction(this._draw); - - return this.inherited(arguments); - }, - - onDeactivating: function () { - // отключаем рисование и получение сообщений - if (this._pointermoveKey) - this._pointermoveKey.remove(); - this._olMap.removeInteraction(this._draw); - - // если был активен инструмент - if (this._sketch) { - // убиваем подсказку и сбрасываем текущее рисование - this._sketch = null; - this._measureTooltipElement = null; - this._olMap.removeOverlay(this._measureTooltip); - } - - return this.inherited(arguments); - }, - - clear: function () { - var me = this; - me.log("clear"); - if (me._vector) { - me._vector.getSource().clear(); - me._overlays.forEach(function (x) { - me._olMap.removeOverlay(x); - }); - } - }, - - _createMeasureTooltip: function () { - this._measureTooltipElement = dconstruct.create("div", { - "class": 'tooltip poisk-measure-tooltip' - }); - this._measureTooltip = new ol.Overlay({ - element: this._measureTooltipElement, - offset: [0, -15], - positioning: 'bottom-center' - }); - this._olMap.addOverlay(this._measureTooltip); - - }, - - _onDrawStart: function (evt) { - this._sketch = evt.feature; - this._createMeasureTooltip(); - }, - - _onDrawEnd: function (evt) { - - this._measureTooltip.setOffset([0, -7]); - - dclass.remove(this._measureTooltipElement, "tooltip"); - dclass.add(this._measureTooltipElement, "tooltip-static"); - - this._overlays.push(this._measureTooltip); - - this._sketch = null; - this._measureTooltip = null; - this._measureTooltipElement = null; - }, - - _onPointerMove: function (evt) { - if (this._sketch && !evt.dragging) { - this._measureTooltip.setPosition(evt.coordinate); - this._measureTooltipElement.innerHTML = this._formatTooltip( - this._sketch, - this._olMap.getView().getProjection()); - } - }, - - _formatTooltip: function (sketch, proj) { - - } - }); - -}); \ No newline at end of file
--- a/src/djol/OSMSource.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -define(["ol"], function(ol) { - return ol.source.OSM; -}); \ No newline at end of file
--- a/src/djol/OlTool.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -define(["dojo/_base/declare", "dojo/_base/lang", "implab/safe", "dojo/dom-class", "dojo/dom-construct", "dijit/_TemplatedMixin", "dijit/_WidgetBase"], - function (declare, lang, safe, domClass, domConstruct, _TemplatedMixin, _WidgetBase) { - return declare([_WidgetBase, _TemplatedMixin], { - map : null, - control : null, - elementName : "div", - - constructor: function () { - lang.mixin(this, arguments[0]); - safe.argumentNotNull(this.map, "map"); - safe.argumentNotNull(this.control, "control"); - }, - - buildRendering : function() { - this.domNode = domConstruct.create(this.elementName); - domClass.add(this.domNode, this.baseClass); - this.control.setTarget(this.domNode); - this.control.setMap(this.map.olMap || this.map); - } - }); -}); \ No newline at end of file
--- a/src/djol/PopupContainer.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -define([ - "dijit/_WidgetBase", - "dijit/_TemplatedMixin", - "dijit/_WidgetsInTemplateMixin", - "dijit/_Container", - "dojo/_base/declare", - "dojo/Evented", - "dojo/dom-class", - "dojo/on", - "dojo/text!./resources/PopupContainerTemplate.html", - "ol" -], - function (_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, _Container, declare, Evented, domClass, on, templateString, ol) { - return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, _Container/*, Evented*/], { - - templateString: templateString, - - overlay: null, - - map : null, - - constructor: function (options) { - options = options || {}; - }, - - postCreate: function () { - var me = this; - this.inherited(arguments); - on(this.popupCloser, "click", function () { - me.destroyRecursive(); - me.onClose(); - }); - }, - - show: function (widget, opts) { - opts = opts || "only"; - if (widget) { - widget.placeAt(this.popupContent, opts); - } - }, - - hideOverlay: function () { - domClass.add(this.popupOverlay, "hidden") - }, - - showOverlay: function () { - domClass.remove(this.popupOverlay, "hidden") - }, - - destroy : function() { - this.map.removeOverlay(this.overlay); - this.inherited(arguments); - }, - - onClose: function () { - this.emit("close"); - } - - }); - }); \ No newline at end of file
--- a/src/djol/SquareMeasureTool.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -define([ - "dojo/_base/declare", - "implab/safe", - "./MeasureToolBase", - "implab/text/format", - "dojo/i18n!./format/nls/units", - "ol" ], - -function(declare, safe, MeasureToolBase, format, units, ol) { - return declare([ MeasureToolBase ], { - - isGeodesic : true, - - units : 'metric', - - constructor : function(opts) { - if (opts) - safe.mixin(this,opts,["isGeodesic", "units"]); - }, - - _createDraw : function(source) { - return new ol.interaction.Draw({ - source : source, - type : "Polygon", - style : this.drawStyle - }); - }, - - _formatTooltip : function(sketch, proj) { - var area; - if (this.isGeodesic) { - var geom = sketch.getGeometry().clone().transform(proj, 'EPSG:4326'); - var coordinates = geom.getLinearRing(0).getCoordinates(); - area = Math.abs(this.wgs84Sphere.geodesicArea(coordinates)); - } else { - area = sketch.getGeometry().getArea(); - } - - var mpu, unitName; - switch (this.units) { - case "nautical": - mpu = 1852*1852; - unitName = units.nmiles2; - break; - default: - mpu = 1852*1852; - unitName = units.kilometers2; - } - - if (area > mpu/10) { - return format( - "{0:#0.##} {1}", - area / mpu, - unitName); - } else { - return format("{0:#0.##} {1}", area, units.meters2); - } - } - - }); -}); \ No newline at end of file
--- a/src/djol/TileLayer.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -define(["ol"], function(ol) { - return ol.layer.Tile; -}); \ No newline at end of file
--- a/src/djol/TileWMSSource.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -define(["ol"], function(ol) { - return ol.source.TileWMS; -}); \ No newline at end of file
--- a/src/djol/ToolBoxController.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -define([ - "dojo/_base/declare", - "implab/safe", - "implab/components/ActivationController", - "./ToolType" ], - -function(declare, safe, ActivationController, ToolType) { - return declare([ ActivationController ], { - _stack : null, - _tools : null, - - constructor : function() { - this._stack = new Array(); - this._tools = new Array(); - }, - - activate : function(tool) { - safe.argumentNotNull(tool, "tool"); - - var me = this, current = me.getCurrent(); - - return this.inherited(arguments).then(function(success) { - if (success) { - if (tool.toolType == ToolType.Oneshot && current) - me._stack.push(current); - else - me._stack = []; - } - return success; - }); - }, - - deactivate : function() { - var me = this; - return me.inherited(arguments).then(function(success) { - if (success && me._stack.length) - return me.activate(me._stack.pop()); - - return success; - }); - } - }); -}); \ No newline at end of file
--- a/src/djol/ToolType.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -define([], function(){ - return { - Activatable : 1, - Oneshot : 2 - }; -}); \ No newline at end of file
--- a/src/djol/VectorLayer.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -define([ - "implab/guard", - "implab/text/template-compile", - "dojo/_base/declare", - "dojo/_base/lang", - "dojo/Deferred", - "ol"], - function (guard, compile, declare, lang, Deferred, ol) { - return declare([ol.layer.Vector], { - - map: null, - - _olMap: null, - - name: null, - - displayName: null, - - identifyResultTemplate: null, - - identifyCompiledTemplate:null, - - searchResultTemplate: null, - - searchCompiledTemplate: null, - - constructor: function () { - lang.mixin(this, arguments[0]); - this._olMap = this.map.olMap; - var identifyCompiledTemplate = null, searchCompiledTemplate = null; - if (this.identifyResultTemplate) { - this.identifyCompiledTemplate = compile(this.identifyResultTemplate); - } - if (this.searchResultTemplate) { - this.searchCompiledTemplate = compile(this.searchResultTemplate); - } - }, - - /** Возвращает массив строк, каждая строка - результат поиска приведенный к шаблонному виду - @options {Object} - @str {String} поисковая строка - @bbox {Object} bound box, в рамках которого осуществлять поиск - */ - getSearchResult: function (options) { - return null; - }, - - _getIdentifyResult: function (options) { - var me = this; - var features = []; - //TODO: добавить фильтр по layer равный ему самому - this._olMap.forEachFeatureAtPixel(options.pixel, function (feature, layer) { - features.push({ feature: feature, layer: layer }); - }, null, function (layer) { - return layer == me; - }); - console.log(features); - return features; - }, - /** Возвращает массив строк, каждая строка - результат идентификации приведенный к шаблонному виду - @options {Object} - @coordinates {Array} массив описывающий координаты точки идентификации - */ - getIdentifyResult: function (coordinates) { - return guard(this, "_getIdentifyResult", [coordinates]); - } - }); - }) \ No newline at end of file
--- a/src/djol/VectorStore.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,289 +0,0 @@ -define( - [ - "dojo/_base/declare", - "dojo/_base/array", - "implab/safe", - "implab/Uuid", - "ol", - "ol3/listen", - "./VectorStoreQuery", - "dojo/store/util/QueryResults" - ], - function (declare, array, safe, UUID, ol, listen, VectorStoreQuery, QueryResults) { - function createPaginator(opts) { - return (opts.count || opts.start) && - function (results) { - var total = results.length; - results = results.slice(opts.start || 0, (opts.start || 0) + - (opts.count || Infinity)); - results.total = total; - - return results; - }; - } - - /** - * Обертка вокруг векторного источника данных ol.source.Vector, - * реализует dojo/store а также notify, что делает возможным наблюдение - * за хранилищем при помощи dojo/store/Observable. - * - * @disposable - */ - return declare( - null, { - _source: null, // ol3.source.Vector - - _projection: null, - - _subscriptions: null, - - constructor: function (opts) { - safe.argumentNotNull(opts, "opts"); - safe.argumentOfType( - opts.source, - ol.source.Vector, - "opts.source"); - - var me = this; - - me._source = opts.source; - if (opts.projection) - me._projection = ol.proj.get(opts.projection); - }, - - getSource: function () { - return this._source; - }, - - getProjection: function() { - return this._projection; - }, - - get: function (id) { - return this._source.getFeatureById(id); - }, - - /** - * @param{Object|Function} q предикат для выбора объекта - * @param{Object} opts параметры выполнения (start,count,sort) - * @return{Function} filter(data) filter.matches - * filter.matches.predicate - * filter.matches.extent filter.sort - * filter.sort.compare - */ - queryEngine: function (q, opts) { - opts = opts || {}; - - // строим функцию для фильтрации - var filter; - if (q instanceof Function) { - // если передали уже готовую функцию, испольуем ее - filter = new VectorStoreQuery(q, q.extent); - } else { - // если передали объект - var extent; - // вытаскиваем из него extent - if (q && 'extent' in q) { - extent = q.extent; - delete q.extent; - } - - // строим новую функцию фильтрации - filter = new VectorStoreQuery(q, extent); - } - - // строим функцию сортировки - var sort = opts.sort && this.sortEngine(opts.sort); - - var paginate = createPaginator(opts); - - // строим функцию выполнения запроса - var execute = function (data) { - var results = array.filter(data, filter); - - if (sort) - sort(results); - - if (paginate) - results = paginate(results); - return results; - }; - - execute.matches = filter; - execute.sort = sort; - execute.paginate = paginate; - return execute; - }, - - sortEngine: function (options) { - var cmp = function (a, b) { - for (var sort, i = 0; - (sort = options[i]); i++) { - var aValue = a.get(sort.attribute); - var bValue = b.get(sort.attribute); - if (aValue != bValue) { - return Boolean(sort.descending) == aValue > bValue ? -1 : 1; - } - } - return 0; - }; - - var execute = function (data) { - return data.sort(cmp); - }; - - execute.compare = cmp; - return execute; - }, - - /** - * Запрашивает объекты со слоя - * - * @param{object|VectorStoreQuery|Function} query - * - * <pre> - * { - * extent : ol3.Extent, - * } - * </pre> - */ - query: function (q, options) { - var me = this; - var filter = this.queryEngine(q, options); - - if (this.notify && !this.hasOwnProperty("_subscriptions")) { - me._subscriptions = []; - - var sc = function (evt, handler) { - me._subscriptions.push(listen(me._source, evt, safe.delegate(me, handler))); - } - - sc("addfeature", "_onAdd"); - sc("changefeature", "_onUpdate"); - sc("removefeature", "_onRemove"); - } - - var predicate, data, extent = filter.matches && - filter.matches.extent; - // если это запрос с указанием области - if (extent) { - predicate = filter.matches.predicate; - - data = this._source.getFeaturesInExtent(extent); - - if (predicate) - data = array.filter(data, predicate); - - if (filter.sort) - filter.sort(data); - - if (filter.paginate) - data = filter.paginate(data); - } else { - // любой другой запрос - data = filter(this._source.getFeatures()); - } - - return new QueryResults(data); - }, - - put: function (obj, options) { - safe.argumentOfType(obj, ol.Feature, "obj"); - if (!options) - options = {}; - - if (options.id) - obj.setId(options.id); - - var id = obj.getId() || new UUID(); - - var prev = this.get(id); - - if ('overwrite' in options) { - // overwrite=true указан, но перезаписывать нечего - if (!prev && options.overwrite) - throw new Error("The specified feature with id '" + - id + "' doesn't exist in the store"); - - // overwrite=false указан, но объект уже существует - if (prev && !options.overwrite) - throw new Error("The specified feature with id '" + - id + "' already exists in the store"); - } - - // ok - if (prev) { - var data = obj.getProperties(); - prev.setProperties(data); - } else { - this._source.addFeature(obj); - } - - return id; - }, - - add: function (obj, options) { - safe.argumentOfType(obj, ol.Feature, "obj"); - - if (!options) - options = {}; - - if (options.id) - obj.setId(options.id); - - var id = obj.getId() || new UUID(); - - var prev = this.get(id); - - if (prev) - throw new Error("The specified feature with id '" + id + - "' already exists in the store"); - - this._source.addFeature(obj); - }, - - remove: function (id) { - var me = this; - - var ft = me.get(id); - if (ft) - me._source.removeFeature(ft); - }, - - getIdentity: function (obj) { - if (safe.isNull(obj)) - return undefined; - if (!(obj instanceof ol.Feature)) - throw new Error("A feature is expected"); - - return obj.getId(); - }, - - _onAdd: function (ev) { - this.notify(ev.feature); - }, - - _onRemove: function (ev) { - var id = ev.feature.getId(); - if (!safe.isNull(id)) - this.notify(undefined, id); - }, - - _onUpdate: function (ev) { - var id = ev.feature.getId(); - if (!safe.isNull(id)) - this.notify(ev.feature, id); - }, - - dispose: function () { - var me = this; - if (me._subscriptions) - me._subscriptions.forEach(function (sc) { - sc.remove(); - }); - - me._source = null; - me._subscriptions = null; - } - }); - }); \ No newline at end of file
--- a/src/djol/VectorStoreQuery.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -define([ "ol" ], function(ol) { - - function buildFilter(filter) { - if (filter instanceof Function) - return filter; - if (filter) { - var match = function(str) { - return { - test : function(x) { - if (x === null || x === undefined) - return false; - return x.toString().startsWith(str); - } - }; - }; - - for ( var p in filter) { - if (typeof (filter[p]) == "string" && filter[p].endsWith("*")) - filter[p] = match(filter[p].substr(0, filter[p].length)); - } - return function(ft) { - for ( var p in filter) { - if (filter[p] && filter[p].test ? !filter[p] - .test(ft.get(p)) : ft.get(p) != filter[p]) - return false; - } - return true; - }; - } - throw new Error("Unsupported filter"); - } - - /** - * @constructor - * @example - * - * <pre> - * var store = new VectorStore({ - * source : vectorSource - * }); - * - * var req = new VectorStoreQuery({ - * city : "Moscow" - * }, [ 30, 50, 40, 60 ]); - * - * store.query(req).then(showResults); - * </pre> - */ - return function(filter, extent) { - var match = filter && buildFilter(filter); - - var query = function(ft) { - if (extent) { - var g = gt.getGeometry(); - if (!g || !ol.extent.intersects(extent, g.getExtent())) - return false; - } - - return !match || match(ft); - }; - - query.extent = extent; - query.predicate = match; - - return query; - }; -}); \ No newline at end of file
--- a/src/djol/WFSSource.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +0,0 @@ -define([ - "ol", - "dojo/request", - "dojo/_base/array", - "implab/safe", - "implab/log/trace!" -], function (ol, - request, - array, - safe, - trace -) { - return function (wfs, featurePrefix, featureType, featureNS, queryArgs) { - if (arguments.length == 1) { - featurePrefix = wfs.featurePrefix; - featureType = wfs.featureType; - featureNS = wfs.featureNS; - wfs = wfs.wfsURL; - queryArgs = wfs.queryArgs; - } - - safe.argumentNotNull(wfs, "wfsURL"); - safe.argumentNotEmptyString(featurePrefix, "featurePrefix"); - safe.argumentNotEmptyString(featureNS, "featureNS"); - safe.argumentNotEmptyString(featureType, "featureType"); - - var format = new ol.format.WFS({ - featureNS: featureNS, - featureType: featureType - }); - - var layerName = featurePrefix + ":" + featureType; - - function loader(extent, resolution, projection) { - var query = { - service: 'WFS', - version: '1.1.0', - request: 'GetFeature', - typename: layerName, - srsname: projection.getCode() - }; - safe.mixin(query, queryArgs); - - if (extent && isFinite(extent[0])) - query.bbox = extent.join(',') + "," + projection.getCode(); - - return request(wfs, { - query: query, - handleAs: 'xml' - }).then(function (data) { - // в загрузчике нельзя вызывать метод source.clear() поскольку - // это приводит к рекурсии - var features = format.readFeatures(data); - - var map = {}, - del = [], - add = []; - - array.forEach(features, function (x) { - // HACK исправляем идентификаторы, чтобы они совпадали с - // реальными - - var id = x.get("id"); - if (id) - x.setId(id); - else - id = x.getId(); - - map[id] = x; - - // нужно проверить, была ли фича на карте - var prev = source.getFeatureById(id); - if (prev) { - // если да, то обновить ее. - var data = x.getProperties(); - prev.setProperties(data); - } else { - // иначе добавить - add.push(x); - } - }); - - source.forEachFeatureInExtent(extent, function (x) { - if (!(x.getId() in map)) - del.push(x); - }); - - source.addFeatures(add); - - array.forEach(del, function (x) { - source.removeFeature(x); - }); - - //revision = revision + 1; - - source.set("revision", ++revision); - - }); - } - - var cls = ol.source.ServerVector || ol.source.Vector; - var revision = 0; - var source = new cls({ - loader: loader, - //revision: revision - wrapX: false - // , - // strategy : options.strategy || ol.loadingstrategy.all, - // projection : options.projection - }); - source.set("revision", revision); - source.reload = function (extent, resolution, projection, q) { - if (arguments.length >= 4) - queryArgs = q; - if (!extent) - extent = [-Infinity, -Infinity, Infinity, Infinity]; - return loader(extent, resolution, projection); - }; - - trace.log("{0} -> {1}", layerName, wfs); - return source; - }; -}); \ No newline at end of file
--- a/src/djol/_OneshotTool.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -define(["dojo/_base/declare", "implab/safe", "implab/guard", "ol3/_ToolBase", "ol3/ToolType"], - - function (declare, safe, guard, _ToolBase, ToolType) { - return declare([_ToolBase], { - _pending: null, - - _lastResult: null, - - toolType: ToolType.Oneshot, - - invoke: function () { - }, - - onActivating: function () { - var me = this; - - // start the operation - me._lastResult = me._pending = guard(me, "invoke"); - - return this.inherited(arguments); - }, - - onActivated: function () { - var me = this; - - // fire the activate event - this.inherited(arguments); - - me._pending.then(function () { - if (me._pending) { - me.log("Operation finished, deactivating."); - me._pending = null; - me.deactivate(); - } - }, function (ex) { - if (me._pending) { - me.error("Operation failed, deactivating: {0}", ex); - me._pending = null; - me.deactivate(); - } - }); - }, - - onDeactivated: function () { - var d = this._pending; - if (d) { - this.log("Cancelling pending operation"); - this._pending = null; - d.cancel(); - } - - return this.inherited(arguments); - }, - - run: function () { - var me = this; - - return me.activate().then(function () { - return me._lastResult; - }); - } - }); - }); \ No newline at end of file
--- a/src/djol/_ToolBase.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -define([ - "dojo/_base/declare", - "dojo/when", - "implab/safe", - "implab/guard", - "implab/components/_ActivatableMixin", - "implab/log/_LogMixin", - "dojo/Evented", - "./ToolType" ], - -function(declare, when, safe, guard, _ActivatableMixin, _LogMixin, Evented, ToolType) { - return declare([ _ActivatableMixin, Evented ], { - toolType : ToolType.Activatable, - - module : null, - - constructor : function(opts) { - if (opts) { - if (opts.controller) - this.setController(opts.controller); - } - }, - - onActivating : function() { - var me = this, inherited = this.getInherited(arguments); - if (me.module && !me.module.isActive()) - return me.module.activate().then(function(active) { - return active ? inherited.apply(me) : false; - }); - else - return inherited.apply(me); - }, - - onActivated : function() { - this.emit("active", true); - }, - - onDeactivated : function() { - this.emit("active", false); - }, - - destroy : function() { - - } - }); -}); \ No newline at end of file
--- a/src/djol/declare-style.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -define(["dojo/_base/declare","implab/safe"],function(declare, safe){ - return function(base, proto){ - var cls = declare(base,proto); - - var factory = /** @this */ function() { - var me = this; - cls.apply(me,arguments); - var fn = function() { - return me.getFeatureStyle.apply(me,arguments); - }; - fn.style = me; - fn.styleFunction = fn; - return fn; - }; - - factory.styleClass = cls; - factory.prototype = cls.prototype; - return factory; - }; -}); \ No newline at end of file
--- a/src/djol/format/coords.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -define( - [ "dojo/i18n!./nls/coords", "implab/text/format", "implab/safe" ], - - function(nls, format, safe) { - - var formatDMS = function(coord) { - return formatSD(coord, nls.dmsPattern); - }; - - var formatDM = function(coord) { - return formatSD(coord, nls.dmPattern); - }; - - var formatD = function(coord) { - return formatSD(coord, nls.dPattern); - }; - - /** - * pattern: - * - * {0} - signed floating point number - latitude - * - * {1} - positive floating point number - minutes part of latitude - * - * {2} - positive floating point number - seconds part of latitude - * - * {3} - localized hemisphere sign: north or south - * - * {4} - signed floating point number - longitude - * - * {5} - positive floating point number - minutes part of longitude - * - * {6} - positive floating point number - seconds part of longitude - * - * {7} - localized hemisphere sign: east or west - */ - var formatSD = function(coord, pattern) { - safe.argumentNotNull(coord, "coord"); - if (!pattern) - pattern = nls.sdPattern; - var x = (coord[0] % 360 + 540) % 360 - 180, y = (coord[1] % 180 + 270) % 180 - 90; - - return format(pattern, y, Math.abs((y * 60) % 60), Math - .abs((y * 3600) % 60), y >= 0 ? nls.north : nls.south, x, Math - .abs((x * 60) % 60), Math.abs((x * 3600) % 60), x >= 0 - ? nls.east - : nls.west); - }; - - var cls = function(fmt) { - switch (fmt) { - case "DMS": - return formatDMS; - case "DM": - return formatDM; - case "D": - return formatD; - case "SD": - return formatSD; - default: - if (!fmt) - return formatSD; - else - return function(coord) { - return formatSD(coord, fmt); - } - } - }; - - return cls; - }); \ No newline at end of file
--- a/src/djol/format/nls/coords.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -define({ - root : { - // lat lon - dmsPattern : "{0:!00;00}\u00b0{1:!00}\u2032{2:00}\u2033{3} {4:!000;000}\u00b0{5:!00}\u2032{6:00}\u2033{7}", - dmPattern : "{0:!00;00}\u00b0{1:00.0000}\u2032{3} {4:000;000}\u00b0{5:!00.0000}\u2032{7}", - dPattern : "{0:00.000000;00.000000}\u00b0{3} {4:000.000000;000.000000}\u00b0{7}", - sdPattern : "{0:#0.000000}, {4:#0.000000}", - north : "N", - south : "S", - west : "W", - east : "E" - }, - ru : true -}); \ No newline at end of file
--- a/src/djol/format/nls/ru/coords.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -define({ - north : "С", - south : "Ю", - west : "З", - east : "В" -}); \ No newline at end of file
--- a/src/djol/format/nls/ru/units.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -define({ - kmph : "км/ч", - mps : "м/с", - knots : "уз", - meters : "м", - kilometers : "км", - meters2 : "м<sup>2</sup>", - kilometers2 : "км<sup>2</sup>", - nmiles : "миль", - nmiles2 : "миль<sup>2</sup>" -}); \ No newline at end of file
--- a/src/djol/format/nls/units.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -define({ - root : { - kmph: "km/h", - mps: "m/s", - knots : "kn", - meters : "m", - kilometers : "km", - meters2 : "m<sup>2</sup>", - kilometers2 : "m<sup>2</sup>", - nmiles : "nmi", - nmiles2 : "nmi<sup>2</sup>" - }, - ru : true -}); \ No newline at end of file
--- a/src/djol/interaction/FeatureDrag.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +0,0 @@ -define([ "dojo/_base/declare", "ol", "dojo/Evented" ], function(declare, ol, - Evented) { - - var peekFirstFeature = function(map, coordinate, pixel) { - return map.forEachFeatureAtPixel(function(ft, layer) { - return ft; - }); - }; - - var cls = declare([ ol.interaction.Pointer ], { - "-chains-" : { - constructor : "manual" - }, - - _peek : null, - - _feature : null, - - _coordinate : null, - - cursor : "pointer", - - _oldCursor : undefined, - - /** - * Создает новый объект - * - * @param {Object} - * opts опции - * @param {Function} - * opts.peek Функция выбора фичи для перетаскивания - * function(map,coordinate,pixel), возвращает фичу - * @param {String} - * opts.cursor css курсор который будет использован при - * наведении и перетаскивании фичи - * - */ - constructor : function(opts) { - - ol.interaction.Pointer.apply(this, [{ - handleDownEvent : this.handleDownEvent, - handleDragEvent : this.handleDragEvent, - handleMoveEvent : this.handleMoveEvent, - handleUpEvent : this.handleUpEvent - }]); - Evented.apply(this); - - if (opts) { - if (opts.peek) { - this._peek = opts.peek; - } else { - this._peek = peekFirstFeature; - } - if ("cursor" in opts) - this.cursor = opts.cursor; - } - }, - - handleDownEvent : function(evt) { - var c = evt.coordinate; - - var ft = this._peek(evt.map, c, evt.pixel); - - if (ft) { - this._feature = ft; - this._coordinate = c; - this._emit("dragbegin", { feature : ft }); - return true; - } - - return false; - }, - - handleDragEvent : function(evt) { - var c1 = this._coordinate, c2 = evt.coordinate; - - var dx = c2[0] - c1[0]; - var dy = c2[1] - c1[1]; - - this._emit("dragging", { feature : this._feature, fromCoord : c1, toCoord : c2 }); - - this._feature.getGeometry().translate(dx, dy); - - this._coordinate = c2; - }, - - handleUpEvent : function(evt) { - if (this._feature) - this._emit("dragend", { feature : this._feature }); - - this._feature = null; - this._coordinate = null; - return false; - }, - - handleMoveEvent : function(evt) { - if (this.cursor) { - var ft = this._feature || this._peek(evt.map, evt.coordinate , evt.pixel); - - var element = evt.map.getTargetElement(); - if (ft) { - if (element.style.cursor != this.cursor) { - this._oldCursor = element.style.cursor; - element.style.cursor = this.cursor; - } - } else if (this._oldCursor !== undefined) { - element.style.cursor = this._oldCursor; - this._oldCursor = undefined; - } - } - }, - - _emit : function(name, data) { - var evt = new ol.source.VectorEvent(name,this); - - for(var p in data) - evt[p] = data[p]; - this.dispatchEvent(evt); - } - }); - - return cls; -}); \ No newline at end of file
--- a/src/djol/listen.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -define(["ol"], function(ol) { - - var listen = function(target, event, callback) { - var key = target.on(event, callback); - return { - remove : function() { - ol.Observable.unByKey(key); - } - }; - }; - - listen.once = function(target, event, callback) { - var key = target.once(event, callback); - return { - remove : function() { - ol.Observable.unByKey(key); - } - }; - }; - - return listen; -}); \ No newline at end of file
--- a/src/djol/main.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -define([ "ol" ], function(ol) { - // вспомогательный класс для получения ol в виде зависимости - return function() { - return ol; - }; -}); \ No newline at end of file
--- a/src/djol/ol-stub.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -var ol; -define([], function() { - return ol; -}); \ No newline at end of file
--- a/src/djol/resources/LayerCheckBoxTemplate.html Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -<div class="poisk-layer-checkbox"> - <input type="checkbox" data-dojo-type="dijit/form/CheckBox" data-dojo-attach-point="checkBox"/><span - class="label" data-dojo-attach-point="labelNode"></span> -</div> \ No newline at end of file
--- a/src/djol/resources/LayerRadioButtonTemplate.html Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -<div class="poisk-layer-radiobutton"> - <input type="radio" data-dojo-attach-point="radioButton" - data-dojo-type="dijit/form/RadioButton" /><span - data-dojo-attach-point="labelNode"></span> -</div> \ No newline at end of file
--- a/src/djol/resources/LayerSwitcherTemplate.html Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -<div class="poisk-layer-switcher"> - <h4 class="group-label" data-dojo-attach-point="infoLayersLabelNode"></h4> - <div data-dojo-attach-point="infoLayersContainer" data-dojo-type="app/view/Container"></div> - <h4 class="group-label" data-dojo-attach-point="baseLayersLabelNode"></h4> - <div data-dojo-attach-point="baseLayersContainer" data-dojo-type="app/view/Container"></div> -</div> \ No newline at end of file
--- a/src/djol/resources/PopupContainerTemplate.html Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -<div class="ol-popup"> - <div data-dojo-attach-point="popupOverlay" class="popup-overlay"> - <span class="inline-ghost"></span> - <div class="fa fa-spinner fa-pulse"></div> - </div> - <div class="ol-popup-closer fa fa-times" data-dojo-attach-point="popupCloser"></div> - <div class="popup-content" data-dojo-attach-point="popupContent"></div> -</div> \ No newline at end of file
--- a/src/djol/resources/mapToolCheckBox.html Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -<div class="mapToolCheckBox poisk-measure-control tooltipMatchNode below"> - <div data-dojo-attach-point="iconsBlock" class="iconsBlock"></div> -</div> \ No newline at end of file
--- a/src/implab/Deferred.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -define(["dojo/Deferred"], function(Deferred) { - return Deferred; -}); \ No newline at end of file
--- a/src/implab/Uri.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,232 +0,0 @@ -define( - [ "./declare" ], - function(declare) { - function parseURI(uri) { - var schema, host, port, path, query, hash, i; - if (typeof (uri) == "string") { - if ((i = uri.indexOf(":")) >= 0 && - uri.substr(0, i).match(/^\w+$/)) { - schema = uri.substr(0, i); - uri = uri.substr(i + 1); - } - - if (uri.indexOf("//") === 0) { - uri = uri.substr(2); - if ((i = uri.indexOf("/")) >= 0) { - host = uri.substr(0, i); - uri = uri.substr(i); - } else { - host = uri; - uri = ""; - } - } - - if ((i = uri.indexOf("?")) >= 0) { - path = uri.substr(0, i); - uri = uri.substr(i + 1); - - } else { - path = uri; - uri = ""; - - if ((i = path.indexOf("#")) >= 0) { - hash = path.substr(i + 1); - path = path.substr(0, i); - } - } - - if ((i = uri.indexOf("#")) >= 0) { - query = uri.substr(0, i); - hash = uri.substr(i + 1); - } else { - query = uri; - } - } - - if (host && (i = host.lastIndexOf(":")) >= 0) { - port = host.substr(i + 1); - host = host.substr(0, i); - } - - return { - schema : schema, - host : host, - port : port, - path : path, - query : query, - hash : hash - }; - } - - function makeURI(options) { - var uri = []; - - if (options.schema) - uri.push(options.schema, ":"); - if (options.host) - uri.push("//", options.host); - if (options.host && options.port) - uri.push(":", options.port); - - if (options.path) { - if (options.host && options.path[0] != "/") - uri.push("/"); - uri.push(options.path); - } else if (options.host) { - uri.push("/"); - } - - if (options.query) - uri.push("?", options.query); - if (options.hash) - uri.push("#", options.hash); - - return uri.join(""); - } - - function reducePath(parts) { - var balance = 0, result = [], isRoot; - - for (var i = 0; i < parts.length; i++) { - var part = parts[i]; - switch (part) { - case "..": - if (balance > 0) { - result.pop(); - } else { - if (isRoot) - throw new Error("Unbalanced path: " + parts); - - result.push(part); - } - balance--; - break; - case ".": - break; - case "": - if (i === 0) { - isRoot = true; - result.push(part); - } - break; - default: - result.push(part); - balance++; - break; - } - } - - return result.join("/"); - } - - var meta = { - schema : null, - host : null, - port : null, - path : null, - query : null, - hash : null - }; - - var URI = declare(null, { - constructor : function(opts) { - if (typeof (opts) == "string") - opts = parseURI(opts); - for ( var p in meta) - if (p in opts) - this[p] = opts[p]; - }, - - clone : function() { - return new URI(this); - }, - - combine : function(rel) { - var me = this; - - if (typeof (rel) === "string") - rel = new URI(rel); - else - rel = rel.clone(); - - // //some.host:123/path?q=a#123 - if (rel.host) - return rel; - - // /abs/path?q=a#123 - if (rel.path && rel.path[0] == "/") { - if (me.host) { - rel.schema = me.schema; - rel.host = me.host; - rel.port = me.port; - } - return rel; - } - - var base = me.clone(); - - // rel/path?a=b#cd - if (rel.path) { - var segments = base.getSegments(); - segments.pop(); - segments.push.apply(segments, rel.getSegments()); - - base.path = reducePath(segments); - } - - // ?q=a#123 - if (rel.query) - base.query = rel.query; - if (rel.hash) - base.hase = rel.hash; - - return base; - }, - - optimize : function() { - this.path = reducePath(this.getSegments()); - }, - - getSegments : function() { - if (typeof (this.path) === "string") - return this.path.split("/"); - else - return []; - }, - - toString : function() { - var uri = [], me = this; - - if (me.schema) - uri.push(me.schema, ":"); - if (me.host) - uri.push("//", me.host); - if (me.host && me.port) - uri.push(":", me.port); - - if (me.path) { - if (me.host && me.path[0] != "/") - uri.push("/"); - uri.push(me.path); - } else if (me.host) { - uri.push("/"); - } - - if (me.query) - uri.push("?", me.query); - if (me.hash) - uri.push("#", me.hash); - - return uri.join(""); - } - - }); - - URI.combine = function(base, rel) { - if (typeof (base) === "string") - base = new URI(base); - return base.combine(rel).toString(); - }; - - return URI; - }); \ No newline at end of file
--- a/src/implab/Uuid.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,278 +0,0 @@ -// uuid.js -// -// Copyright (c) 2010-2012 Robert Kieffer -// MIT License - http://opensource.org/licenses/mit-license.php -define([], function () { - 'use strict'; - - var _window = 'undefined' !== typeof window ? window : null; - - // Unique ID creation requires a high quality random # generator. We - // feature - // detect to determine the best RNG source, normalizing to a function - // that - // returns 128-bits of randomness, since that's what's usually required - var _rng, _mathRNG, _nodeRNG, _whatwgRNG, _previousRoot; - - function setupBrowser() { - // Allow for MSIE11 msCrypto - var _crypto = _window.crypto || _window.msCrypto; - - if (!_rng && _crypto && _crypto.getRandomValues) { - // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto - // - // Moderately fast, high quality - try { - var _rnds8 = new Uint8Array(16); - _whatwgRNG = _rng = function whatwgRNG() { - _crypto.getRandomValues(_rnds8); - return _rnds8; - }; - _rng(); - } catch (e) { /**/ } - } - - if (!_rng) { - // Math.random()-based (RNG) - // - // If all else fails, use Math.random(). It's fast, but is of - // unspecified - // quality. - var _rnds = new Array(16); - _mathRNG = _rng = function () { - for (var i = 0, r; i < 16; i++) { - if ((i & 0x03) === 0) { - r = Math.random() * 0x100000000; - } - _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; - } - - return _rnds; - }; - if ('undefined' !== typeof console && console.warn) { - console - .warn("[SECURITY] node-uuid: crypto not usable, falling back to insecure Math.random()"); - } - } - } - - function setupNode() { - // Node.js crypto-based RNG - - // http://nodejs.org/docs/v0.6.2/api/crypto.html - // - // Moderately fast, high quality - if ('function' === typeof require) { - try { - var _rb = require('crypto').randomBytes; - _nodeRNG = _rng = _rb && function () { - return _rb(16); - }; - _rng(); - } catch (e) { /**/ } - } - } - - if (_window) { - setupBrowser(); - } else { - setupNode(); - } - - // Buffer class to use - var BufferClass = ('function' === typeof Buffer) ? Buffer : Array; - - // Maps for number <-> hex string conversion - var _byteToHex = []; - var _hexToByte = {}; - for (var i = 0; i < 256; i++) { - _byteToHex[i] = (i + 0x100).toString(16).substr(1); - _hexToByte[_byteToHex[i]] = i; - } - - // **`parse()` - Parse a UUID into it's component bytes** - function parse(s, buf, offset) { - var i = (buf && offset) || 0, - ii = 0; - - buf = buf || []; - s.toLowerCase().replace(/[0-9a-f]{2}/g, function (oct) { - if (ii < 16) { // Don't overflow! - buf[i + ii++] = _hexToByte[oct]; - } - }); - - // Zero out remaining bytes if string was short - while (ii < 16) { - buf[i + ii++] = 0; - } - - return buf; - } - - // **`unparse()` - Convert UUID byte array (ala parse()) into a string** - function unparse(buf, offset) { - var i = offset || 0, - bth = _byteToHex; - return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + - bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + - bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + - bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]]; - } - - // **`v1()` - Generate time-based UUID** - // - // Inspired by https://github.com/LiosK/UUID.js - // and http://docs.python.org/library/uuid.html - - // random #'s we need to init node and clockseq - var _seedBytes = _rng(); - - // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = - // 1) - var _nodeId = [ - _seedBytes[0] | 0x01, - _seedBytes[1], - _seedBytes[2], - _seedBytes[3], - _seedBytes[4], - _seedBytes[5] - ]; - - // Per 4.2.2, randomize (14 bit) clockseq - var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff; - - // Previous uuid creation time - var _lastMSecs = 0, - _lastNSecs = 0; - - // See https://github.com/broofa/node-uuid for API details - function v1(options, buf, offset) { - var i = buf && offset || 0; - var b = buf || []; - - options = options || {}; - - var clockseq = (options.clockseq != null) ? options.clockseq : _clockseq; - - // UUID timestamps are 100 nano-second units since the Gregorian - // epoch, - // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so - // time is handled internally as 'msecs' (integer milliseconds) and - // 'nsecs' - // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 - // 00:00. - var msecs = (options.msecs != null) ? options.msecs : new Date() - .getTime(); - - // Per 4.2.1.2, use count of uuid's generated during the current - // clock - // cycle to simulate higher resolution clock - var nsecs = (options.nsecs != null) ? options.nsecs : _lastNSecs + 1; - - // Time since last uuid creation (in msecs) - var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs) / 10000; - - // Per 4.2.1.2, Bump clockseq on clock regression - if (dt < 0 && options.clockseq == null) { - clockseq = clockseq + 1 & 0x3fff; - } - - // Reset nsecs if clock regresses (new clockseq) or we've moved onto - // a new - // time interval - if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) { - nsecs = 0; - } - - // Per 4.2.1.2 Throw error if too many uuids are requested - if (nsecs >= 10000) { - throw new Error( - 'uuid.v1(): Can\'t create more than 10M uuids/sec'); - } - - _lastMSecs = msecs; - _lastNSecs = nsecs; - _clockseq = clockseq; - - // Per 4.1.4 - Convert from unix epoch to Gregorian epoch - msecs += 12219292800000; - - // `time_low` - var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; - b[i++] = tl >>> 24 & 0xff; - b[i++] = tl >>> 16 & 0xff; - b[i++] = tl >>> 8 & 0xff; - b[i++] = tl & 0xff; - - // `time_mid` - var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; - b[i++] = tmh >>> 8 & 0xff; - b[i++] = tmh & 0xff; - - // `time_high_and_version` - b[i++] = tmh >>> 24 & 0xf | 0x10; // include version - b[i++] = tmh >>> 16 & 0xff; - - // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) - b[i++] = clockseq >>> 8 | 0x80; - - // `clock_seq_low` - b[i++] = clockseq & 0xff; - - // `node` - var node = options.node || _nodeId; - for (var n = 0; n < 6; n++) { - b[i + n] = node[n]; - } - - return buf ? buf : unparse(b); - } - - // **`v4()` - Generate random UUID** - - // See https://github.com/broofa/node-uuid for API details - function v4(options, buf, offset) { - // Deprecated - 'format' argument, as supported in v1.2 - var i = buf && offset || 0; - - if (typeof (options) === 'string') { - buf = (options === 'binary') ? new BufferClass(16) : null; - options = null; - } - options = options || {}; - - var rnds = options.random || (options.rng || _rng)(); - - // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` - rnds[6] = (rnds[6] & 0x0f) | 0x40; - rnds[8] = (rnds[8] & 0x3f) | 0x80; - - // Copy bytes to buffer, if provided - if (buf) { - for (var ii = 0; ii < 16; ii++) { - buf[i + ii] = rnds[ii]; - } - } - - return buf || unparse(rnds); - } - - // Export public API - var uuid = function () { - return new String(v4()); - }; - uuid.v1 = v1; - uuid.v4 = v4; - uuid.create = v4; - uuid.empty = "00000000-0000-0000-0000-000000000000"; - uuid.parse = parse; - uuid.unparse = unparse; - uuid.BufferClass = BufferClass; - uuid._rng = _rng; - uuid._mathRNG = _mathRNG; - uuid._nodeRNG = _nodeRNG; - uuid._whatwgRNG = _whatwgRNG; - - return uuid; -}); \ No newline at end of file
--- a/src/implab/components/ActivationController.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -define(["dojo/_base/declare", "../guard", "../safe", "../log/_LogMixin"], function (declare, guard, safe, _LogMixin) { - "use strict"; - return declare([_LogMixin], { - - _current: null, - - _pending: false, - - getCurrent: function () { - return this._current; - }, - - _start: function () { - if (this._pending) - throw new Error("The activation/decativation is already pending"); - this._pending = true; - }, - - _await: function (d) { - var me = this; - return d.then(function (x) { - me._pending = false; - return x; - }, function (e) { - me._pending = false; - throw e; - }); - }, - - activate: function (component) { - safe.argumentNotNull(component, "component"); - var me = this; - if (component.getController() !== this) - throw new Error("The specified component doesn't belong to this controller"); - - return me._await(guard(me, "_start").then(function () { - me._activate(component); - })); - }, - - _activate: function (component) { - var me = this; - if (me._current === component) - return guard(false); - - // before activation hook - return guard(me, "onActivating", [component]).then(function () { - // deactivate curent - if (me._current) - return me._current.deactivate(true).then(function () { - try { - me._current.onDeactivated(); - } catch (err) { - me.error(err); - } - // HACK raise deactivated event - try { - me.onDeactivated(me._current, component); - } catch (err) { - // deactivated shouldn't affect the process - me.error(err); - } - me._current = null; - - }); - }).then(function () { - return component.activate(true); - }).then(function () { - me._current = component; - try { - me.onActivated(component); - } catch (err) { - me.error(err); - } - - }); - - }, - - /** - * Деактивирует текущую компоненту. - * - * @async - * @returns true - компонента была деактивирована, либо нет активной - * компоненты. false - запрос на деактивацию - отклонен. - */ - deactivate: function () { - var me = this; - return me._await(guard(me, "_start").then(function () { - return me._deactivate(); - })); - }, - - _deactivate: function () { - var me = this; - if (!me._current) - return guard(false); - - return guard(me, "onDeactivating").then(function () { - return me._current.deactivate(true); - }).then(function () { - // HACK raise deactivated event - try { - me.onDeactivated(me._current); - } catch (err) { - me.error(err); - } - me._current = null; - }); - }, - - onActivating: function (component) {}, - - onDeactivating: function (component) {}, - - onDeactivated: function (component, next) {}, - - onActivated: function (component) {} - }); -}); \ No newline at end of file
--- a/src/implab/components/StateMachine.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -define([ "dojo/_base/declare", "../safe", "../text/format" ], function(declare, safe, format) { - return declare(null, { - states : null, - - current : null, - - constructor : function(opts) { - safe.argumentNotNull(opts, "opts"); - safe.argumentNotNull(opts.states, "opts.states"); - safe.argumentNotNull(opts.initial, "opts.initial"); - - this.states = opts.states; - this.current = opts.initial; - - if (safe.isNull(this.states[this.current])) - throw new Error("Invalid initial state " + this.current); - }, - - move : function(input, noThrow) { - safe.argumentNotNull(input, "input"); - - var next = this.states[this.current][input]; - if(safe.isNull(next)) { - if (noThrow) - return false; - else - throw new Error(format("Invalid transition {0}-{1}->?", this.current, input)); - } else { - this.current = next; - return true; - } - } - }); -}); \ No newline at end of file
--- a/src/implab/components/_ActivatableMixin.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,153 +0,0 @@ -define(["dojo/_base/declare", "../guard", "./StateMachine", "../log/_LogMixin", ], function (declare, guard, StateMachine, _LogMixin) { - - var states = { - inactive: { - activate: "activating" - }, - activating: { - success: "active", - failed: "inactive" - }, - active: { - deactivate: "deactivating" - }, - deactivating: { - success: "inactive", - failed: "active" - } - }; - - return declare([_LogMixin], { - _controller: null, - - _active: null, - - constructor: function () { - this._active = new StateMachine({ - states: states, - initial: "inactive" - }); - }, - - /** - * @returns {Object} контроллер для активации текущей компоненты - */ - getController: function () { - return this._controller; - }, - - /** - * @param {Object} - * v Контроллер для активации текущей компоненты - */ - setController: function (v) { - this._controller = v; - }, - - /** - * @returns {Boolean} текущая компонента активна - */ - isActive: function () { - return this._active.current == "active"; - }, - - assertActive: function () { - if (!this.isActive()) - throw new Error("The object must be active to perform the operation"); - }, - - /** - * Активирует текущую компоненту, если у текущей компоненты задан - * контроллер, то активация будет осуществляться через него - * - * @async - * @param{Boolean} - * direct вызов должен осуществится напрямую, без участия - * контроллера. - * @return{Boolean} успешно/неуспешно - */ - activate: function (direct) { - var me = this; - if (!direct && this._controller) - return me._controller.activate(me).then(function () { - me.onActivated(); - }); - - me._active.move("activate"); - return guard(me, "onActivating").then(function () { - me.log("Activated"); - me._active.move("success"); - if (!me._controller) - me.onActivated(); - }, function (err) { - console.error(err); - me.error("Activation failed: {0}", err); - me._active.move("failed"); - throw err; - }); - }, - - /** - * Деактивирует текущую компоненту, если у компоненты задан контроллер, - * то деактивация будет осуществляться через него. - * - * @async - * @param{Boolean} direct вызов должен осуществится напрямую, без - * участия контроллера. - * - */ - deactivate: function (direct) { - var me = this; - if (!direct && me._controller) - return me._controller.deactivate(me).then(function () { - me.onDeactivated(); - }); - - me._active.move("deactivate"); - return guard(me, "onDeactivating").then(function () { - me.log("Deactivated"); - me._active.move("success"); - if (!me._controller) - me.onDeactivated(); - }, function (err) { - console.error(err); - me.error("Deactivation failed: {0}", err); - me.move("failed"); - throw err; - }); - - }, - - toogleActive: function () { - var me = this; - return (me.isActive() ? me.deactivate() : me.activate()).then(function () { - return me.isActive(); - }); - }, - - /** - * Событие вызывается перед активацией текущей компоненты - * - * @returns{Boolean|undefined} если false - активация будет отменена - */ - onActivating: function () {}, - - /** - * Событие вызывается перед деактивацией текущей компоненты - * - * @returns {Boolean|undefined} если false - деактивация будет отменена - */ - onDeactivating: function () {}, - - /** - * Событие вызывается после активации текущей компоненты - */ - onActivated: function () {}, - - /** - * Событие вызывается после деактивации текущей компоненты - */ - onDeactivated: function () {} - - }); -}); \ No newline at end of file
--- a/src/implab/data/DataContext.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -define([ "dojo/_base/declare", "../safe" ], function(declare, safe) { - return declare( - null, - { - _params : null, - - _repositories : null, - - constructor : function(opts) { - this._params = opts || {}; - this._repositories = {}; - }, - - getRepository : function(name) { - safe.argumentNotEmptyString(name, "name"); - var repo = this._repositories[name]; - if (!repo) { - repo = this._params[name]; - if (!repo) - throw new Error("The repository '" + name + - "' isn't found"); - if (repo instanceof Function) - repo = new repo(); // factory method or constructor - if (repo.initialize) { - repo.initialize({ - dataContext : this - }); - } else if (repo.setDataContext) { - repo.setDataContext(this); - } - this._repositories[name] = repo; - } - - return repo; - }, - - dispose : function() { - for( var name in this._repositories) { - var r = this._repositories[name]; - if (r.dispose) - r.dispose(); - } - } - }); -}); \ No newline at end of file
--- a/src/implab/data/MapSchema.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -define([ "dojo/_base/declare", "../safe" ], function(declare, safe) { - return declare(null, { - /** - * Отображение одного типа объектов в другой. - * - * @remarks Отображения являются односторонними, т.е. позволяют - * перенести часть содержимого одного объекта в другой. Каждая - * схема отображения строится из набора примитивных - * отображений, которые будут применены в произвольном порядке. - */ - _schema : null, - - constructor : function(schema) { - this._schema = schema; - }, - - /** - * Осуществляет отображение одного объекта в другой - * - * @src{Object} Исходный объект из которого будут взяты данные - * @dst{Object} - */ - map : function(src, dst, ctx) { - safe.argumentNotNull(src, "src"); - safe.argumentNotNull(dst, "dst"); - - for ( var p in this._schema) { - var mapper = this._schema[p]; - if (mapper instanceof Function) { - dst[p] = mapper(src[p]); - } else if (mapper && mapper.map) { - mapper.map(src, dst, p, ctx); - } else { - this._defaultMapper(src, dst, p, mapper, ctx); - } - } - }, - - _defaultMapper : function(src, dst, prop, opts) { - if (typeof (opts) == "string") { - if (opts in src) - dst[prop] = src[opts]; - } else if (opts && opts.type instanceof Function) { - if (src[prop] instanceof opts.type) - dst[prop] = src[prop]; - else - dst[prop] = this._isPrimitiveType(opts.type) ? opts.type - .call(null, src[prop]) : new opts.type(src[prop]); - - } else { - if (!(prop in src)) - if (opts && opts.required) - throw new Error("The " + prop + "is missing"); - else - return; - dst[prop] = src[prop]; - } - }, - - _isPrimitiveType : function(type) { - return (type === String || type === Number || type === Boolean - || type === Number || type === Date); - } - - }); - -}); \ No newline at end of file
--- a/src/implab/data/ObjectStore.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,174 +0,0 @@ -define([ "dojo/_base/declare", "dojo/_base/lang", "dojo/_base/array", - "../safe", "dojo/when", "dojo/Deferred", "dojo/store/util/QueryResults" ], function(declare, - lang, array, safe, when, Deferred, QueryResults) { - /** - * @module implab/data/RestStore - * - * Реализует шаблон репозитария dojo/store над уже имеющимся хранилищем. При получении и - * отправке данных в нижележащие хранилище используется implab/data/MapSchema для преобразования - * данных. - */ - return declare(null, { - - model: null, - - mapping: null, - - _dataContext: null, - - _store : null, // backing store - - _cache : null, - - constructor : function(options) { - options = options || {}; - - if (options.store) - this._store = options.store; - - if (options.dataContext) { - this._dataContext = options.dataContext; - } - - if (options.cache === false) { - // no cache at all - } else if (options.cache === "string" && options.dataContext) { - this._cache = this._dataContext.getCache(options.cache); - } else { - this._cache = {}; - } - }, - - getDataContext : function() { - return this._dataContext; - }, - - // READ - get : function(id) { - var me = this; - var cache = me.getCacheEntry(id); - if (cache) - return cache; - else - return when(me._store.get(id), function(data) { - return me._mapToObject(id, data); - }); - }, - - query : function(query, options) { - var me = this; - var d = me._store.query(query, options); - var result = QueryResults(when(d, function(data) { - return array.map(data, function(item) { - return me._mapToObject(me._store.getIdentity(item), item); - }); - })); - result.total = d.total; - return result; - }, - - getIdentity : function(object) { - return object.getId(); - }, - - // UPDATE - put : function(object, directives) { - return this._store.put(this._mapFromObject(object), directives); - }, - - // INSERT - add : function(object, directives) { - var me = this; - // добавляем в хранилище данные, сохраняем в кеше объект с - // полученным идентификатором - return when( - me._store.add(this._mapFromObject(object), directives), - function(id) { - object.attach(id, me); - me.storeCacheEntry(id, object); - return id; - }); - }, - - // DELETE - remove : function(id) { - var me = this; - return when(me._store.remove(id), function() { - me.removeCacheEntry(id); - }); - }, - - _mapToObject : function(id, data) { - var instance = this.createInstance(id); - this.populateInstance(instance, data); - return instance; - }, - - _mapFromObject : function(object) { - return this.serializeInstance(object); - }, - - getCacheEntry : function(id) { - safe.argumentNotNull(id, "id"); - id = id.toString(); - - return this._cache[id]; - }, - - storeCacheEntry : function(id, object) { - safe.argumentNotNull(id, "id"); - id = id.toString(); - - this._cache[id] = object; - }, - - removeCacheEntry : function(id) { - safe.argumentNotNull(id, "id"); - id = id.toString(); - delete this._cache[id]; - }, - - /** Создает экземпляр сущности с указанным идентификатором, либо извлекает из кеша, если таковая уже имеется. - * @remarks - * Технически сюда можно было бы дополнительно передать данные для ининциализации объекта, - * но концептуально это не верно, поскольку процесс чтения объекта состоит из двух этапов: - * 1. Создание пустого объекта (createInstance) - * 2. Заполнение объекта при помощи схемы отображения (populateInstance) - * при этом первый этап может быть выполнен за долго до второго, например, - * при создании заглушек в процессе установления ссылок между объектами. - */ - createInstance : function(id) { - var instance = this.getCacheEntry(id); - if (!instance) { - instance = this.createInstanceImpl(id); - this.storeCacheEntry(id, instance); - } - return instance; - }, - - /** Непосредственно создает экземпляр сущнсти, т.е. является фабричным методом. - * @param {String} id идентификатор создаваемого экземпляра. - */ - createInstanceImpl : function(id) { - var opts = { - dataContext : this.getDataContext(), - id : id - }; - - return new this.itemsType(opts); - }, - - populateInstance : function(instance, data) { - this.mapping.readData(instance, data,this.getDataContext()); - if (instance.onPopulate) - instance.onPopulate(); - }, - - serializeInstance : function(instance) { - var data = {}; - this.mapping.writeData(instance, data, this.getDataContext()); - return data; - } - - }); -}); \ No newline at end of file
--- a/src/implab/data/RestStore.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -define([ "dojo/_base/declare", "dojo/_base/lang", "dojo/_base/array", - "../safe", "dojo/when", "dojo/Deferred", "dojo/store/util/QueryResults" ], function(declare, - lang, array, safe, when, Deferred, QueryResults) { - /** - * @module implab/data/RestStore - * - * Реализует шаблон репозитария dojo/store над уже имеющимся хранилищем. При получении и - * отправке данных в нижележащие хранилище используется implab/data/MapSchema для преобразования - * данных. - */ - return declare(null, { - - itemsType : null, - - _dataContext : null, - - _store : null, // backing store - _cache : null, - - constructor : function(options) { - options = options || {}; - - this._cache = {}; - if (options.store) - this._store = options.store; - if (options.dataContext) - this._dataContext = options.dataContext; - }, - - setDataContext : function(v) { - this._dataContext = v; - }, - - getDataContext : function() { - return this._dataContext; - }, - - // READ - get : function(id) { - var me = this; - var cache = me.getCacheEntry(id); - if (cache) - return cache; - else - return when(me._store.get(id), function(data) { - return me._mapToObject(id, data); - }); - }, - - query : function(query, options) { - var me = this; - var d = me._store.query(query, options); - var result = QueryResults(when(d, function(data) { - return array.map(data, function(item) { - return me._mapToObject(me._store.getIdentity(item), item); - }); - })); - result.total = d.total; - return result; - }, - - getIdentity : function(object) { - return object.getId(); - }, - - // UPDATE - put : function(object, directives) { - return this._store.put(this._mapFromObject(object), directives); - }, - - // INSERT - add : function(object, directives) { - var me = this; - // добавляем в хранилище данные, сохраняем в кеше объект с - // полученным идентификатором - return when( - me._store.add(this._mapFromObject(object), directives), - function(id) { - object.attach(id, me); - me.storeCacheEntry(id, object); - return id; - }); - }, - - // DELETE - remove : function(id) { - var me = this; - return when(me._store.remove(id), function() { - me.removeCacheEntry(id); - }); - }, - - _mapToObject : function(id, data) { - var instance = this.createInstance(id); - this.populateInstance(instance, data); - return instance; - }, - - _mapFromObject : function(object) { - return this.serializeInstance(object); - }, - - getCacheEntry : function(id) { - safe.argumentNotNull(id, "id"); - id = id.toString(); - - return this._cache[id]; - }, - - storeCacheEntry : function(id, object) { - safe.argumentNotNull(id, "id"); - id = id.toString(); - - this._cache[id] = object; - }, - - removeCacheEntry : function(id) { - safe.argumentNotNull(id, "id"); - id = id.toString(); - delete this._cache[id]; - }, - - /** Создает экземпляр сущности с указанным идентификатором, либо извлекает из кеша, если таковая уже имеется. - * @remarks - * Технически сюда можно было бы дополнительно передать данные для ининциализации объекта, - * но концептуально это не верно, поскольку процесс чтения объекта состоит из двух этапов: - * 1. Создание пустого объекта (createInstance) - * 2. Заполнение объекта при помощи схемы отображения (populateInstance) - * при этом первый этап может быть выполнен за долго до второго, например, - * при создании заглушек в процессе установления ссылок между объектами. - */ - createInstance : function(id) { - var instance = this.getCacheEntry(id); - if (!instance) { - instance = this.createInstanceImpl(id); - this.storeCacheEntry(id, instance); - } - return instance; - }, - - /** Непосредственно создает экземпляр сущнсти, т.е. является фабричным методом. - * @param {String} id идентификатор создаваемого экземпляра. - */ - createInstanceImpl : function(id) { - var opts = { - dataContext : this.getDataContext(), - id : id - }; - - return new this.itemsType(opts); - }, - - populateInstance : function(instance, data) { - this.itemsType.readData(instance, data,this.getDataContext()); - if (instance.onPopulate) - instance.onPopulate(); - }, - - serializeInstance : function(instance) { - var data = {}; - this.itemsType.writeData(instance, data, this.getDataContext()); - return data; - } - - }); -}); \ No newline at end of file
--- a/src/implab/data/StatefullStoreAdapter.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -define(["dojo/_base/declare", "dojo/_base/array", "../safe", "./StoreAdapter"], function(declare, array, safe ,AdapterStore){ - return declare([AdapterStore], { - _attrs : null, - - constructor : function(opts) { - safe.argumentNotEmptyArray(opts.attrs, "opts.attrs"); - this._attrs = opts.attrs; - }, - - mapItem : function(item) { - var result = {}; - array.forEach(this._attrs, function(p) { - result[p] = item.get(p); - }); - return result; - } - }); - -}); \ No newline at end of file
--- a/src/implab/data/StoreAdapter.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -define([ - "dojo/_base/declare", - "../safe", - "dojo/when", - "dojo/store/util/QueryResults" ], - -function(declare, safe, when, QueryResults) { - - "use strict"; - - /** - * Обертка вокруг произвольного хранилища, только для чтения. Используется - * для преобразования данных, например, отображения в списках элементов - * пространственных данных. - */ - return declare(null, { - /** - * @type{String} Свойство, хранящее идентификатор - */ - idProperty : null, - - _store : null, - - /** - * @param{String} opts.idProperty Имя свойства, в которое будет записан - * идентификатор, если не указан, то идентификатор будет - * взят из родительского хранилища или использоваться - * строка <code>id</code> - * @param{dojo.store} opts.store Родительское хранилище - */ - constructor : function(opts) { - safe.argumentNotNull(opts, "opts"); - safe.argumentNotNull(opts.store, "opts.store"); - - this._store = opts.store; - delete opts.store; - declare.safeMixin(this, opts); - this.idProperty = opts.idProperty || this._store.idProperty || "id"; - }, - - getParentStore : function() { - return this._store; - }, - - get : function(id) { - var me = this; - return when(me._store.get(id), function(x) { - var m = me.mapItem(x); - if (!(me.idProperty in m)) - m[me.idProperty] = id; - return m; - }); - }, - - /** - * Выполняет запрос в родительском хранилище, для этого используется - * <code>translateQuery</code> для подготовки запроса, затем, - * <code>mapItem</code> для преобразования результатов. - */ - query : function(q, options) { - var me = this, store = this._store; - return when(store.query(me.translateQuery(q), me - .translateOptions(options)), function(res) { - var total = res.total; - var mapped = res.map(function(x) { - var m = me.mapItem(x); - if (!(me.idProperty in m)) - m[me.idProperty] = store.getIdentity && - store.getIdentity(x); - return m; - }); - mapped.total = total; - var results = new QueryResults(mapped); - console.log(results); - return results; - }); - }, - - getIdentity : function(obj) { - return obj && obj[this.idProperty]; - }, - - /** - * Преобразование запроса в формат родительского хранилища. - * - * @param{Object} q Запрос в формате текущего хранилища - * @returns{Object} Запрос в формате родительского хранилища - */ - translateQuery : function(q) { - return q; - }, - - translateOptions : function(options) { - return options; - }, - - /** - * Преобразование объекта из родительского хранилища. При преобразовании - * в объекте можно задать идентификатор, иначе идентификатор будет - * автоматически получен и присвоен из родительского хранилища - * - * @param{Object} item Объект из родительского хранилища - * @returns{Object} результат преобразования - */ - mapItem : function(item) { - return item; - } - }); - -}); \ No newline at end of file
--- a/src/implab/data/_ModelBase.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -define(["dojo/_base/declare"], function(declare) { - - return declare(null, { - dataContext : null, - idField : "id", - loaded : false, - - constructor : function(opts){ - if (opts) { - if(opts.dataContext) - this.dataContext = opts.dataContext; - if(opts.id) - this[this.idField] = opts.id; - } - }, - - getId : function() { - return this[this.idField]; - }, - - attach : function(id, dc) { - if (this.dataContext) - throw new Error("The object is already attached"); - this[this.idField] = id; - this.dataContext = dc; - }, - - isAttached : function() { - return this.dataContext ? true : false; - }, - - onPopulate : function() { - this.loaded = true; - } - - }); -}); \ No newline at end of file
--- a/src/implab/data/_StatefulModelMixin.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -define(["dojo/_base/declare", "dojo/Stateful"], function(declare, Stateful) { - return declare([Stateful], { - - }); -}); \ No newline at end of file
--- a/src/implab/data/declare-model.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -define([ "dojo/_base/declare", "./_ModelBase", "./MapSchema" ], function( - declare, _ModelBase, MapSchema) { - /** - * Создает новый класс, унаследованный от ./ModelBase, с указанной схемой - * отображения данных. - * - * @details Модель представляет собой объект, живущий в рамках контекста - * данных, также имеющий две схемы отображения: из модели хранения - * в источнике данных (toObjectMap) и наооборот в модель хранения в - * источнике данных (fromObjectMap). - * - * Описание схемы выглядит следующим образом - * <pre> - * { - * name : null, // отображение в обе стороны без преобразования - * - * age : Number, // при преобразоваении к объекту поле будет преобразовано dst.age = Number(src.age) - * // обратное преобразование отсутстсвует - * - * age : [Number, null] // тоже самое что и age : Number - * - * date : [Date, function(v) { return v.toString() }] // указывается преобразование в одну и в другую сторону - * } - * <pre> - */ - return function(schema, mixins, opts) { - var fromObjectSchema = {}, toObjectSchema = {}; - if (schema !== null && schema !== undefined) { - for ( var p in schema) { - var mapper = schema[p]; - - if (mapper instanceof Array) { - toObjectSchema[p] = mapper[0]; - fromObjectSchema[p] = mapper[1]; - } else { - toObjectSchema[p] = mapper; - fromObjectSchema[p] = null; - } - } - } - - if (arguments.length < 3) { - opts = mixins; - mixins = undefined; - } - - var base = [ _ModelBase ]; - if (mixins) { - if (mixins instanceof Array) - base = base.concat(mixins); - else - base.push(mixins); - } - - var model = declare(base, opts); - - model.toObjectMap = new MapSchema(toObjectSchema); - - model.fromObjectMap = new MapSchema(fromObjectSchema); - - model.readData = function(that, data, context) { - model.toObjectMap.map(data, that, context); - }; - - model.writeData = function(that, data, context) { - data = data || {}; - model.fromObjectMap.map(that, data, context); - }; - - return model; - }; -}); \ No newline at end of file
--- a/src/implab/declare.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -define([ - './declare/_load!' -], function(declare) { - 'use strict'; - return declare; -}); \ No newline at end of file
--- a/src/implab/declare/_load.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -define([], function () { - 'use strict'; - - return { - load: function (id, require, callback) { - require(['dojo/_base/declare'], function (declare) { - callback(declare); - }); - } - }; - -}); \ No newline at end of file
--- a/src/implab/declare/override.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -"use strict"; -define([], function () { - var slice = Array.prototype.slice; - var override = function (method) { - var proxy; - - /** @this target object */ - proxy = function () { - var me = this; - var inherited = (this.getInherited && this.getInherited(proxy.nom, { - callee: proxy - })) || function () {}; - - return method.apply(me, [function () { - return inherited.apply(me, arguments); - }].concat(slice.apply(arguments))); - }; - - proxy.method = method; - proxy.overrides = true; - - return proxy; - }; - - override.before = function (method) { - var proxy; - - /** @this target object */ - proxy = function () { - var me = this; - var inherited = (this.getInherited && this.getInherited(proxy.nom, { - callee: proxy - })) || function () {}; - - - method.apply(me, arguments); - return inherited.apply(me, arguments); - }; - - proxy.method = method; - proxy.overrides = true; - - return proxy; - }; - - override.after = function (method) { - var proxy; - - /** @this target object */ - proxy = function () { - var me = this; - var inherited = (this.getInherited && this.getInherited(proxy.nom, { - callee: proxy - })) || function () {}; - - inherited.apply(me, arguments); - - return method.apply(me, arguments); - }; - - proxy.method = method; - proxy.overrides = true; - - return proxy; - }; - - override.hide = function (method) { - method.overrides = false; - return method; - }; - - return override; -}); \ No newline at end of file
--- a/src/implab/di/ActivationContext.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,138 +0,0 @@ -define([ - "../declare", - "../safe", - "./Descriptor", - "./ValueDescriptor", - "../log/trace!" -], function (declare, safe, Descriptor, Value, trace) { - var Context = declare(null, { - - _cache: null, - - _services: null, - - _stack: null, - - _visited: null, - - container: null, - - _trace: true, - - constructor: function (container, services, cache, visited) { - safe.argumentNotNull(container, "container"); - safe.argumentNotNull(services, "services"); - - this._visited = visited || {}; - this._stack = []; - this._cache = cache || {}; - this._services = services; - this.container = container; - }, - - getService: function (name, def) { - var d = this._services[name]; - - if (!d) - if (arguments.length > 1) - return def; - else - throw new Error("Service '" + name + "' not found"); - - return d.activate(this, name); - }, - - /** - * registers services local to the the activation context - * - * @name{string} the name of the service - * @service{string} the service descriptor to register - */ - register: function (name, service) { - safe.argumentNotEmptyString(name, "name"); - - if (!(service instanceof Descriptor)) - service = new Value(service, true); - this._services[name] = service; - }, - - clone: function () { - return new Context( - this.container, - Object.create(this._services), - this._cache, - this._visited - ); - - }, - - has: function (id) { - return id in this._cache; - }, - - get: function (id) { - return this._cache[id]; - }, - - store: function (id, value) { - return (this._cache[id] = value); - }, - - parse: function (data, name) { - var me = this; - if (safe.isPrimitive(data)) - return data; - - if (data instanceof Descriptor) { - return data.activate(this, name); - } else if (data instanceof Array) { - me.enter(name); - var v = data.map(function (x, i) { - return me.parse(x, "." + i); - }); - me.leave(); - return v; - } else { - me.enter(name); - var result = {}; - for (var p in data) - result[p] = me.parse(data[p], "." + p); - me.leave(); - return result; - } - }, - - visit: function (id) { - var count = this._visited[id] || 0; - this._visited[id] = count + 1; - return count; - }, - - getStack: function () { - return this._stack.slice().reverse(); - }, - - enter: function (name, d, localize) { - if (this._trace) - trace.log("enter " + name + " " + (d || "") + - (localize ? " localize" : "")); - this._stack.push({ - name: name, - service: d, - scope: this._services - }); - if (localize) - this._services = Object.create(this._services); - }, - - leave: function () { - var ctx = this._stack.pop(); - this._services = ctx.scope; - - if (this._trace) - trace.log("leave " + ctx.name + " " + (ctx.service || "")); - } - }); - - return Context; -}); \ No newline at end of file
--- a/src/implab/di/ActivationError.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -define([ - "../declare" -], function (declare) { - return declare(null, { - activationStack: null, - - service: null, - - innerException: null, - - message: null, - - constructor: function (service, activationStack, innerException) { - this.message = "Failed to activate the service"; - this.activationStack = activationStack; - this.service = service; - this.innerException = innerException; - }, - - toString: function () { - var parts = [this.message]; - if (this.service) - parts.push("when activating: " + this.service.toString()); - - if (this.innerException) - parts.push("caused by: " + this.innerException.toString()); - - if (this.activationStack) { - parts.push("at"); - this.activationStack.forEach(function (x) { - parts.push(" " + x.name + " " + - (x.service ? x.service.toString() : "")); - }); - } - - return parts.join("\n"); - } - }); -}); \ No newline at end of file
--- a/src/implab/di/Container.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,299 +0,0 @@ -define([ - "../declare", - "../safe", - "../Uuid", - "../Deferred", - "./ActivationContext", - "./Descriptor", - "./ValueDescriptor", - "./ReferenceDescriptor", - "./ServiceDescriptor", - "./ActivationError" -], function ( - declare, - safe, - Uuid, - Deferred, - ActivationContext, - Descriptor, - Value, - Reference, - Service, - ActivationError) { - var Container = declare(null, { - _services: null, - _cache: null, - _cleanup: null, - _root: null, - _parent: null, - - constructor: function (parent) { - this._parent = parent; - this._services = parent ? Object.create(parent._services) : {}; - this._cache = {}; - this._cleanup = []; - this._root = parent ? parent.getRootContainer() : this; - this._services.container = new Value(this, true); - }, - - getRootContainer: function () { - return this._root; - }, - - getParent: function () { - return this._parent; - }, - - /** - * - */ - getService: function (name, def) { - var d = this._services[name]; - if (!d) - if (arguments.length > 1) - return def; - else - throw new Error("Service '" + name + "' isn't found"); - if (d.isInstanceCreated()) - return d.getInstance(); - - var context = new ActivationContext(this, this._services); - - try { - return d.activate(context, name); - } catch (error) { - throw new ActivationError(name, context.getStack(), error); - } - }, - - register: function (name, service) { - if (arguments.length == 1) { - var data = name; - for (name in data) - this.register(name, data[name]); - } else { - if (!(service instanceof Descriptor)) - service = new Value(service, true); - this._services[name] = service; - } - return this; - }, - - onDispose: function (callback) { - if (!(callback instanceof Function)) - throw new Error("The callback must be a function"); - this._cleanup.push(callback); - }, - - dispose: function () { - if (this._cleanup) { - for (var i = 0; i < this._cleanup.length; i++) - this._cleanup[i].call(null); - this._cleanup = null; - } - }, - - /** - * @param{String|Object} config - * The configuration of the contaier. Can be either a string or an object, - * if the configuration is an object it's treated as a collection of - * services which will be registed in the contaier. - * - * @param{Function} opts.contextRequire - * The function which will be used to load a configuration or types for services. - * - */ - configure: function (config, opts) { - var p, me = this, - contextRequire = (opts && opts.contextRequire); - - if (typeof (config) === "string") { - p = new Deferred(); - if (!contextRequire) { - var shim = [config, new Uuid()].join(config.indexOf("/") != -1 ? "-" : "/"); - define(shim, ["require", config], function (ctx, data) { - p.resolve([data, { - contextRequire: ctx - }]); - }); - require([shim]); - } else { - // TODO how to get correct contextRequire for the relative config module? - contextRequire([config], function (data) { - p.resolve([data, { - contextRequire: contextRequire - }]); - }); - } - - return p.then(function (args) { - return me._configure.apply(me, args); - }); - } else { - return me._configure(config, opts); - } - }, - - createChildContainer: function () { - return new Container(this); - }, - - has: function (id) { - return id in this._cache; - }, - - get: function (id) { - return this._cache[id]; - }, - - store: function (id, value) { - return (this._cache[id] = value); - }, - - _configure: function (data, opts) { - var typemap = {}, - d = new Deferred(), - me = this, - p, - contextRequire = (opts && opts.contextRequire) || require; - - var services = {}; - - for (p in data) { - var service = me._parse(data[p], typemap); - if (!(service instanceof Descriptor)) - service = new Value(service, false); - services[p] = service; - } - - me.register(services); - - var names = []; - - for (p in typemap) - names.push(p); - - if (names.length) { - contextRequire(names, function () { - for (var i = 0; i < names.length; i++) - typemap[names[i]] = arguments[i]; - d.resolve(me); - }); - } else { - d.resolve(me); - } - return d.promise; - }, - - _parse: function (data, typemap) { - if (safe.isPrimitive(data) || data instanceof Descriptor) - return data; - if (data.$dependency) - return new Reference( - data.$dependency, - data.lazy, - data.optional, - data["default"], - data.services && this._parseObject(data.services, typemap)); - if (data.$value) { - var raw = !data.parse; - return new Value(raw ? data.$value : this._parse( - data.$value, - typemap), raw); - } - if (data.$type || data.$factory) - return this._parseService(data, typemap); - if (data instanceof Array) - return this._parseArray(data, typemap); - - return this._parseObject(data, typemap); - }, - - _parseService: function (data, typemap) { - var me = this, - opts = { - owner: this - }; - if (data.$type) { - - opts.type = data.$type; - - if (typeof (data.$type) === "string") { - typemap[data.$type] = null; - opts.typeMap = typemap; - } - } - - if (data.$factory) - opts.factory = data.$factory; - - if (data.services) - opts.services = me._parseObject(data.services, typemap); - if (data.inject) - opts.inject = data.inject instanceof Array ? data.inject.map(function (x) { - return me._parseObject(x, typemap); - }) : me._parseObject(data.inject, typemap); - if (data.params) - opts.params = me._parse(data.params, typemap); - - if (data.activation) { - if (typeof (data.activation) === "string") { - switch (data.activation.toLowerCase()) { - case "singleton": - opts.activation = Service.SINGLETON; - break; - case "container": - opts.activation = Service.CONTAINER; - break; - case "hierarchy": - opts.activation = Service.HIERARCHY; - break; - case "context": - opts.activation = Service.CONTEXT; - break; - case "call": - opts.activation = Service.CALL; - break; - default: - throw new Error("Unknown activation type: " + - data.activation); - } - } else { - opts.activation = Number(data.activation); - } - } - - if (data.cleanup) - opts.cleanup = data.cleanup; - - return new Service(opts); - }, - - _parseObject: function (data, typemap) { - if (data.constructor && - data.constructor.prototype !== Object.prototype) - return new Value(data, true); - - var o = {}; - - for (var p in data) - o[p] = this._parse(data[p], typemap); - - return o; - }, - - _parseArray: function (data, typemap) { - if (data.constructor && - data.constructor.prototype !== Array.prototype) - return new Value(data, true); - - var me = this; - return data.map(function (x) { - return me._parse(x, typemap); - }); - } - - }); - - return Container; -}); \ No newline at end of file
--- a/src/implab/di/Descriptor.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -define([], function() { - // abstract base type for descriptros - return function() {}; -}); \ No newline at end of file
--- a/src/implab/di/ReferenceDescriptor.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -define([ - "../declare", "../safe", "./Descriptor", "./ActivationError", "./ValueDescriptor" -], - -function(declare, safe, Descriptor, ActivationError, Value) { - return declare(Descriptor, { - _name : null, - _lazy : false, - _optional : false, - _default : undefined, - - constructor : function(name, lazy, optional, def, services) { - safe.argumentNotEmptyString(name, "name"); - this._name = name; - this._lazy = Boolean(lazy); - this._optional = Boolean(optional); - this._default = def; - this._services = services; - }, - - activate : function(context, name) { - var me = this; - - context.enter(name, this, true); - - // добавляем сервисы - if (me._services) { - for ( var p in me._services) { - var sv = me._services[p]; - context.register(p, sv instanceof Descriptor ? sv : new Value(sv, false)); - } - } - - if (me._lazy) { - // сохраняем контекст активации - context = context.clone(); - return function(cfg) { - // защищаем контекст на случай исключения в процессе - // активации - var ct = context.clone(); - try { - if (cfg) - safe.each(cfg, function(v, k) { - ct.register(k, v instanceof Descriptor ? v : new Value(v, false)); - }); - return me._optional ? ct.getService(me._name, me._default) : ct - .getService(me._name); - } catch (error) { - throw new ActivationError(me._name, ct.getStack(), error); - } - }; - } - - var v = me._optional ? context.getService(me._name, me._default) : context - .getService(me._name); - context.leave(me); - return v; - }, - - isInstanceCreated : function() { - return false; - }, - - toString : function() { - var opts = []; - if (this._optional) - opts.push("optional"); - if (this._lazy) - opts.push("lazy"); - - var parts = [ - "@ref " - ]; - if (opts.length) { - parts.push("{"); - parts.push(opts.join()); - parts.push("} "); - } - - parts.push(this._name); - - if (!safe.isNull(this._default)) { - parts.push(" = "); - parts.push(this._default); - } - - return parts.join(""); - } - }); -}); \ No newline at end of file
--- a/src/implab/di/ServiceDescriptor.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,289 +0,0 @@ -define( - [ - "../declare", - "../safe", - "./Descriptor", - "./ValueDescriptor" - ], - - function (declare, safe, Descriptor, Value) { - var SINGLETON_ACTIVATION = 1, - CONTAINER_ACTIVATION = 2, - CONTEXT_ACTIVATION = 3, - CALL_ACTIVATION = 4, - HIERARCHY_ACTIVATION = 5; - - var injectMethod = function (target, method, context, args) { - var m = target[method]; - if (!m) - throw new Error("Method '" + method + "' not found"); - - if (args instanceof Array) - m.apply(target, context.parse(args, "." + method)); - else - m.call(target, context.parse(args, "." + method)); - }; - - var makeClenupCallback = function (target, method) { - if (typeof (method) === "string") { - return function () { - target[method](); - }; - } else { - return function () { - method(target); - }; - } - }; - - var cacheId = 0; - - var cls = declare( - Descriptor, { - _instance: null, - _hasInstance: false, - _activationType: CALL_ACTIVATION, - _services: null, - _type: null, - _typeMap: null, - _factory: null, - _params: undefined, - _inject: null, - _cleanup: null, - _cacheId: null, - _owner: null, - - constructor: function (opts) { - safe.argumentNotNull(opts, "opts"); - safe.argumentNotNull(opts.owner, "opts.owner"); - - this._owner = opts.owner; - - if (!(opts.type || opts.factory)) - throw new Error( - "Either a type or a factory must be specified"); - - if (typeof (opts.type) === "string" && !opts.typeMap) - throw new Error( - "The typeMap is required when the type is specified by its name"); - - if (opts.activation) - this._activationType = opts.activation; - if (opts.type) - this._type = opts.type; - if (opts.params) - this._params = opts.params; - if (opts.inject) - this._inject = opts.inject instanceof Array ? opts.inject : [opts.inject]; - if (opts.services) - this._services = opts.services; - if (opts.factory) - this._factory = opts.factory; - if (opts.typeMap) - this._typeMap = opts.typeMap; - if (opts.cleanup) { - if (!(typeof (opts.cleanup) === "string" || opts.cleanup instanceof Function)) - throw new Error( - "The cleanup parameter must be either a function or a function name"); - - this._cleanup = opts.cleanup; - } - - this._cacheId = ++cacheId; - }, - - activate: function (context, name) { - - // if we have a local service records, register them first - - var instance; - - switch (this._activationType) { - case 1: // SINGLETON - // if the value is cached return it - if (this._hasInstance) - return this._instance; - - var tof = this._type || this._factory; - - // create the persistent cache identifier for the type - if (safe.isPrimitive(tof)) - this._cacheId = this._type; - else - this._cacheId = safe.oid(tof); - - // singletons are bound to the root container - var container = context.container.getRootContainer(); - - if (container.has(this._cacheId)) { - instance = container.get(this._cacheId); - } else { - instance = this._create(context, name); - container.store(this._cacheId, instance); - if (this._cleanup) - container.onDispose( - makeClenupCallback(instance, this._cleanup)); - } - - this._hasInstance = true; - return (this._instance = instance); - - case 2: // CONTAINER - //return a cached value - if (this._hasInstance) - return this._instance; - - // create an instance - instance = this._create(context, name); - - // the instance is bound to the container - if (this._cleanup) - this._owner.onDispose( - makeClenupCallback(instance, this._cleanup)); - - // cache and return the instance - this._hasInstance = true; - return (this._instance = instance); - case 3: // CONTEXT - //return a cached value if one exists - if (context.has(this._cacheId)) - return context.get(this._cacheId); - // context context activated instances are controlled by callers - return context.store(this._cacheId, this._create( - context, - name)); - case 4: // CALL - // per-call created instances are controlled by callers - return this._create(context, name); - case 5: // HIERARCHY - // hierarchy activated instances are behave much like container activated - // except they are created and bound to the child container - - // return a cached value - if (context.container.has(this._cacheId)) - return context.container.get(this._cacheId); - - instance = this._create(context, name); - - if (this._cleanup) - context.container.onDispose(makeClenupCallback( - instance, - this._cleanup)); - - return context.container.store(this._cacheId, instance); - default: - throw "Invalid activation type: " + this._activationType; - } - }, - - isInstanceCreated: function () { - return this._hasInstance; - }, - - getInstance: function () { - return this._instance; - }, - - _create: function (context, name) { - context.enter(name, this, Boolean(this._services)); - - if (this._activationType != CALL_ACTIVATION && - context.visit(this._cacheId) > 0) - throw new Error("Recursion detected"); - - if (this._services) { - for (var p in this._services) { - var sv = this._services[p]; - context.register(p, sv instanceof Descriptor ? sv : new Value(sv, false)); - } - } - - var instance; - - if (!this._factory) { - var ctor, type = this._type; - - if (typeof (type) === "string") { - ctor = this._typeMap[type]; - if (!ctor) - throw new Error("Failed to resolve the type '" + - type + "'"); - } else { - ctor = type; - } - - if (this._params === undefined) { - this._factory = function () { - return new ctor(); - }; - } else if (this._params instanceof Array) { - this._factory = function () { - var inst = Object.create(ctor.prototype); - var ret = ctor.apply(inst, arguments); - return typeof (ret) === "object" ? ret : inst; - }; - } else { - this._factory = function (param) { - return new ctor(param); - }; - } - } - - if (this._params === undefined) { - instance = this._factory(); - } else if (this._params instanceof Array) { - instance = this._factory.apply(this, context.parse( - this._params, - ".params")); - } else { - instance = this._factory(context.parse( - this._params, - ".params")); - } - - if (this._inject) { - this._inject.forEach(function (spec) { - for (var m in spec) - injectMethod(instance, m, context, spec[m]); - }); - } - - context.leave(); - - return instance; - }, - - // @constructor {singleton} foo/bar/Baz - // @factory {singleton} - toString: function () { - var parts = []; - - parts.push(this._type ? "@constructor" : "@factory"); - - parts.push(activationNames[this._activationType]); - - if (typeof (this._type) === "string") - parts.push(this._type); - - return parts.join(" "); - } - - }); - - cls.SINGLETON = SINGLETON_ACTIVATION; - cls.CONTAINER = CONTAINER_ACTIVATION; - cls.CONTEXT = CONTEXT_ACTIVATION; - cls.CALL = CALL_ACTIVATION; - cls.HIERARCHY = HIERARCHY_ACTIVATION; - - var activationNames = [ - "", - "{singleton}", - "{container}", - "{context}", - "{call}", - "{hierarchy}" - ]; - - return cls; - }); \ No newline at end of file
--- a/src/implab/di/ValueDescriptor.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -define([ "../declare", "./Descriptor", "../safe" ], - -function(declare, Descriptor, safe) { - return declare(Descriptor, { - _value : undefined, - _raw : false, - constructor : function(value, raw) { - this._value = value; - this._raw = Boolean(raw); - }, - - activate : function(context, name) { - context.enter(name, this); - var v = this._raw ? this._value : context.parse( - this._value, - ".params"); - context.leave(this); - return v; - }, - - isInstanceCreated : function() { - return this._raw; - }, - - getInstance : function() { - if (!this._raw) - throw new Error("The instance isn't constructed"); - return this._value; - }, - - toString : function() { - if (this._raw) - return "@value {raw}"; - else - return safe.isNull(this._value) ? "@value <null>" : "@value"; - } - }); -}); \ No newline at end of file
--- a/src/implab/dom/css.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -define(["./inject"], function (inject) { - return { - load: function (id, require, cb) { - var url = require.toUrl(id); - inject.injectStylesheet(url).then(function () { - cb(); - }); - } - }; -}); \ No newline at end of file
--- a/src/implab/dom/inject.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -define(["../Deferred", "../log/trace!"], function (Deferred, trace) { - function on(node, eventName, handler) { - // Add an event listener to a DOM node - node.addEventListener(eventName, handler, false); - - return function () { - node.removeEventListener(eventName, handler, false); - }; - } - - return { - injectionPoint: document.head, - injectBefore: document.head.firstChild, - - _map: {}, - - _inject: function (name, attr) { - var node = document.createElement(name), - d = new Deferred(), - - cleanup = function () { - noerr(); - noload(); - }, - - noload = on(node, "load", function () { - d.resolve({ - node: node - }); - cleanup(); - }, true), - - noerr = on(node, "error", function (e) { - d.reject({ - erorr: e, - node: node - }); - cleanup(); - }, true); - - for (var p in attr) - node[p] = attr[p]; - - this.injectionPoint.insertBefore(node, this.injectBefore); - return d; - }, - - injectScript: function (url) { - var d = this._map[url]; - if (!d) { - trace.log("js {0}", url); - d = this._inject("script", { - type: "text/javascript", - charset: "utf-8", - src: url - }); - d.then(function () { - trace.log("done {0}", url); - }, function (e) { - trace.err([url, e]); - }); - this._map[url] = d; - } - return d; - }, - - injectStylesheet: function (url) { - var d = this._map[url]; - if (!d) { - trace.log("css {0}", url); - d = this._inject("link", { - type: "text/css", - rel: "stylesheet", - href: url - }); - d.then(function () { - trace.log("done {0}", url); - }, function (e) { - trace.error([url, e]); - }); - this._map[url] = d; - } - return d; - } - }; -}); \ No newline at end of file
--- a/src/implab/guard.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -define([ "./Deferred" ], function(Deferred) { - var toPromise = function(d) { - if (d && d.then) - return d; - var d2 = new Deferred(); - d2.resolve(d); - return d2; - }; - - /** - * функция для асинхронного выполнения метода - * - * @async - * @param{Object} o Объект, который будет использован в качестве - * <code>this</code>, если не указан, будет - * <code>null</code> - * @param{Function|String} m Функция или имя метода, обязательный параметр. - * Если указано имя, тогда параметр <code>o</code> - * также должен быть задан - * @param{Array} args Параметры для вызова метода, не обязательно. - * @returns{dojo/promise} - * @deprecated use <code>safe.async() + when()</code> instead. - */ - return function(o, m, args) { - if (arguments.length == 1) { - m = o; - o = null; - } else if (arguments.length == 2 && o instanceof Function && - m instanceof Array) { - args = m; - m = o; - o = null; - } - - try { - if (!(m instanceof Function)) { - if (o) - m = o[m]; - else if (arguments.length == 1) - return toPromise(m); - else - throw new Error("The target object must be specified"); - } - - if (!m) - throw new Error("Method not found"); - - return toPromise(m.apply(o, args)); - } catch (err) { - var d = new Deferred(); - d.reject(err); - return d; - } - }; -}); \ No newline at end of file
--- a/src/implab/log/ConsoleLogChannel.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -define( - [ "dojo/_base/declare", "../text/format" ], - function(declare, format) { - return declare( - null, - { - name : null, - - constructor : function(name) { - this.name = name; - }, - - log : function() { - console.log(this._makeMsg(arguments)); - }, - - warn : function() { - console.warn(this._makeMsg(arguments)); - }, - - error : function() { - console.error(this._makeMsg(arguments)); - }, - - _makeMsg : function(args) { - return this.name ? this.name + " " + - format.apply(null, args) : format.apply(null, args); - } - }); - }); \ No newline at end of file
--- a/src/implab/log/_LogMixin.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -define([ "dojo/_base/declare" ], - -function(declare) { - var cls = declare(null, { - _logChannel : null, - - _logLevel : 1, - - constructor : function(opts) { - if (typeof opts == "object") { - if ("logChannel" in opts) - this._logChannel = opts.logChannel; - if ("logLevel" in opts) - this._logLevel = opts.logLevel; - } - }, - - getLogChannel : function() { - return this._logChannel; - }, - - setLogChannel : function(v) { - this._logChannel = v; - }, - - getLogLevel : function() { - return this._logLevel; - }, - - setLogLevel : function(v) { - this._logLevel = v; - }, - - log : function(format) { - if (this._logChannel && this._logLevel > 2) - this._logChannel.log.apply(this._logChannel, arguments); - }, - warn : function(format) { - if (this._logChannel && this._logLevel > 1) - this._logChannel.warn.apply(this._logChannel, arguments); - }, - error : function(format) { - if (this._logChannel && this._logLevel > 0) - this._logChannel.error.apply(this._logChannel, arguments); - }, - - /** - * Used to by widgets - */ - startup : function() { - var me = this, parent; - if (!me.getLogChannel()) { - parent = me; - while (parent = parent.getParent()) { - if (parent.getLogChannel) { - me.setLogChannel(parent.getLogChannel()); - if(parent.getLogLevel) - me.setLogLevel(parent.getLogLevel()); - break; - } - } - } - this.inherited(arguments); - } - }); - return cls; -}); \ No newline at end of file
--- a/src/implab/log/listeners/console.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -define([], function () { - if (console && console.log) - return function (ch, name, msg) { - - var args = [ch + ":"]; - - switch (name) { - case "warn": - case "error": - case "log": - break; - default: - args.push(name + ":"); - name = "log"; - } - - - if (msg instanceof Array) - args.push.apply(args, msg); - else - args.push(msg); - - console[name].apply(console, args); - }; -}); \ No newline at end of file
--- a/src/implab/log/trace.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -define(["../text/format"], function (format) { - 'use strict'; - - var listeners = []; - var channels = {}; - - var Trace = function (name) { - this.name = name; - this._subscribers = []; - }; - - Trace.prototype.debug = function () { - if (Trace.level >= 4) - this.notify("debug", format.apply(null, arguments)); - }; - - Trace.prototype.log = function () { - if (Trace.level >= 3) - this.notify("log", format.apply(null, arguments)); - }; - - Trace.prototype.warn = function () { - if (Trace.level >= 2) - this.notify("warn", format.apply(null, arguments)); - - }; - - Trace.prototype.error = function () { - if (Trace.level >= 1) - this.notify("error", format.apply(null, arguments)); - }; - - Trace.prototype.notify = function (name, msg) { - var me = this; - me._subscribers.forEach(function (cb) { - cb(me, name, msg); - }); - }; - - Trace.prototype.subscribe = function (cb) { - this._subscribers.push(cb); - }; - - Trace.prototype.toString = function () { - return this.name; - }; - - Trace.createChannel = function (type, name, cb) { - var chId = name; - if (channels[chId]) - return channels[chId]; - - var channel = new type(chId); - channels[chId] = channel; - - Trace._onNewChannel(chId, channel); - cb(channel); - }; - - Trace._onNewChannel = function (chId, ch) { - listeners.forEach(function (listener) { - listener(chId, ch); - }); - }; - - Trace.on = function (filter, cb) { - if (arguments.length == 1) { - cb = filter; - filter = undefined; - } - var d, test; - if (filter instanceof RegExp) { - test = function (chId) { - return filter.test(chId); - }; - } else if (filter instanceof Function) { - test = filter; - } else if (filter) { - test = function (chId) { - return chId == filter; - }; - } - - if (test) { - d = function(chId, ch) { - if(test(chId)) - ch.subscribe(cb); - }; - } else { - d = function(chId, ch) { - ch.subscribe(cb); - }; - } - listeners.push(d); - - for(var chId in channels) - d(chId,channels[chId]); - }; - - Trace.load = function (id, require, cb) { - if (id) - Trace.createChannel(Trace, id, cb); - else if (require.module && require.module.mid) - Trace.createChannel(Trace, require.module.mid, cb); - else - require(['module'], function (module) { - Trace.createChannel(Trace, module && module.id, cb); - }); - }; - - Trace.dynamic = true; - - Trace.level = 4; - - return Trace; -}); \ No newline at end of file
--- a/src/implab/messaging/Client.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -define( - [ "dojo/_base/declare", "dojo/_base/lang", "dojo/Evented", "../log/_LogMixin" ], - - function(declare, lang, Evented, _LogMixin) { - return declare([ Evented, _LogMixin ], { - _session : null, - _destination : null, - _id : null, - - constructor : function(session, destination, options) { - this._destination = destination; - this._session = session; - }, - - getDestination : function() { - return this._destination; - }, - - start : function() { - var me = this; - return me._session.createClient(me.prepareOptions({})).then( - function(id) { - me._id = id; - return me; - }); - }, - - prepareOptions : function(options) { - var me = this; - options.mode = me.getMode(); - options.destination = me.getDestination(); - options.client = function(msg) { - me.process(msg); - }; - return options; - }, - - process : function(msg) { - this.warn("Messages are not acceped by this client"); - }, - - stop : function() { - var me = this; - if (me._id) { - me.log("stop"); - return me._session.deleteClient({'clientId': me._id}).then(function() { - me._id = null; - return me; - }); - } - }, - - toString : function() { - return "[" - + [ - this.getMode().toUpperCase(), - this.getDestination(), - this._id ].join(',') + "]"; - } - }); - }); \ No newline at end of file
--- a/src/implab/messaging/Destination.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -define([ "dojo/_base/declare", "./Listener" ], - -function(declare, Listener) { - return declare(null, { - _session : null, - _destination : null, - _listenerClass : null, - - constructor : function(session, destination, options) { - if (!session) - throw new Error("A session is required"); - if (!destination) - throw new Error("A destination is required"); - - this._session = session; - this._destination = destination; - if (options) { - if (options.listenerClass) - this._listenerClass = options.listenerClass; - } - }, - - listen : function(callback) { - var factory = this._listenerClass || Listener; - var listener = new factory(this._session, this._destination, { - listener : callback - }); - listener.start(); - - return listener; - } - - }); -});
--- a/src/implab/messaging/Listener.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -define([ "dojo/_base/declare", "dojo/_base/lang", "./Client" ], - -function(declare, lang, Client) { - return declare([ Client ], { - _listener : null, - - constructor : function(session, destination, options) { - if (!options || !options.listener) - throw new Error("A listener is required"); - this._listener = options.listener; - if (options.transform) - this._transform = options.transform; - }, - - getMode : function() { - return "listener"; - }, - - process : function(result) { - switch (result.type) { - case "message": - try { - this._handleMessage(result.message); - } catch (ex) { - var err = new Error("Failed to handle message"); - err.envelope = result.message; - err.innerException = ex; - this._handleError(err); - } - break; - case "error": - this._handleError(result.error); - break; - } - - }, - - _transform : function(envelope) { - return envelope; - }, - - _handleMessage : function(envelope) { - this.log( - "MESSAGE type = ${0}, headers = ${2}: ${1}", - envelope.bodyType, - envelope.body, - JSON.stringify(envelope.headers)); - var data = this._transform(envelope); - this._listener(data); - this.emit("message", data); - }, - - _handleError : function(ex) { - if (ex.innerException) - this.error( - "ERROR: ${0} -> ${1}", - ex.message, - ex.innerException.message); - else - this.error("ERROR: ${0}", ex.message); - this.emit("error", ex); - } - }); -}); \ No newline at end of file
--- a/src/implab/messaging/Session.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,217 +0,0 @@ -define( - [ - "dojo/_base/declare", - "dojo/_base/lang", - "dojo/request", - "./Destination", - "dojo/Evented", - "dojo/Deferred", - "../log/_LogMixin" ], - - function(declare, lang, request, Destination, Evented, Deferred, _LogMixin) { - - var cls = declare( - [ Evented, _LogMixin ], - { - _id : null, - _baseUrl : null, - _destinations : null, - _timeout : 100000, - _clients : null, - _started : null, - _starting : false, - - constructor : function(baseUrl, options) { - if (!baseUrl) - throw new Error("baseUrl is required"); - options = options || {}; - - this._baseUrl = baseUrl.replace(/\/*$/, ""); - this._destinations = {}; - this._pending = []; - this._clients = {}; - if (options.timeout) - this._timeout = options.timeout; - - this._started = new Deferred(); - }, - - start : function() { - if (this._starting) - return this._started; - this._starting = true; - - var me = this; - me.log("START"); - request(this._baseUrl, { - method : "POST", - handleAs : "json" - }).then(function(result) { - me._id = result; - me._emitConnected(); - me._poll(); - me._started.resolve(me); - }, function(error) { - me._emitError(error); - me._started.reject(me); - }); - return me._started.promise; - }, - - createClient : function(options) { - if (!options || !options.destination || !options.mode) - throw new Error("Invalid argument"); - - var me = this; - - return me._started - .then(function() { - var url = me._makeUrl(me._id); - me.log( - "CREATE mode=${0}, destination=${1}", - options.mode, - options.destination); - - return request(url, { - method : "POST", - data : { - mode : options.mode, - destination : options.destination - }, - handleAs : 'json' - }) - .then( - function(id) { - me - .log( - "CLIENT id=${0}, mode=${1}, destination=${2}", - id, - options.mode, - options.destination); - me._clients[id] = options.client - ? options.client - : function(msg) { - me - .warn( - "The client id=${0}, mode=${1}, destination=${2} isn't accepting mesages", - id, - options.mode, - options.destination); - }; - return id; - }); - }); - - }, - - deleteClient : function(options) { - if (!options || !options.clientId) - throw new Error("Invalid argument"); - - var me = this, id = options.clientId; - - return me._started.then(function() { - var url = me._makeUrl(me._id, options.clientId); - - me.log("DELETE CLIENT ${0}", options.clientId); - - return request(url, { - method : "DELETE", - handleAs : 'json' - }).then(function() { - me.log("CLIENT DELETED ${0}", options.clientId); - me._clients[id] = undefined; - }); - }); - }, - - _poll : function() { - var me = this, url = this._makeUrl(this._id); - me.log("POLL timeout=${0}", me._timeout); - request(url, { - method : "GET", - handleAs : "json", - query : { - timeout : me._timeout - } - }).then(function(response) { - me._handlePoll(response); - me._poll(); - }, function(err) { - me.error("POLL faield with ${0}", err); - me._emitError(err); - }); - }, - - _handlePoll : function(response) { - if (!response) { - this.log("POLL response undefined, looks like a bug"); - return; - } - if (!response.results || !response.results.length) { - this.log("POLL response is empty"); - return; - } - - var results = response.results; - this.log("POLL got ${0} results", results.length); - - for (var i = 0; i < results.length; i++) { - var result = results[i]; - var client = this._clients[result.clientId]; - if (!client) { - // TODO this could happen due to client isn't - // registered yet - this.error("Unknown client ${0}", result.clientId); - continue; - } - client.call(this, result); - } - }, - - _emitError : function(err) { - this.emit("error", err); - }, - - _emitConnected : function() { - var me = this; - me.log("CONNECTED"); - me.emit("connected"); - }, - - _makeUrl : function() { - var parts = [ this._baseUrl ]; - for (var i = 0; i < arguments.length; i++) - parts.push(arguments[i].replace(/\/*$/, "")); - return parts.join('/'); - }, - - queue : function(name) { - return this._getDestination("queue://" + name); - }, - - topic : function(name) { - return this._getDestination("topic://" + name); - }, - - _getDestination : function(uri) { - if (uri in this._destinations) - return this._destinations[uri]; - - var dest = new Destination(this, uri); - this._destinations[uri] = dest; - return dest; - }, - - toString : function() { - return [ "[", "SESSION ", this._id, "]" ].join(" "); - } - }); - - cls.connect = function(url, options) { - var session = new cls(url, options); - return session.start(); - }; - - return cls; - });
--- a/src/implab/safe.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,323 +0,0 @@ -define([], - - function () { - var _create = Object.create, - _keys = Object.keys; - - var safe = null; - safe = { - argumentNotNull: function (arg, name) { - if (arg === null || arg === undefined) - throw new Error("The argument " + name + " can't be null or undefined"); - }, - - argumentNotEmptyString: function (arg, name) { - if (typeof (arg) !== "string" || !arg.length) - throw new Error("The argument '" + name + "' must be a not empty string"); - }, - - argumentNotEmptyArray: function (arg, name) { - if (!(arg instanceof Array) || !arg.length) - throw new Error("The argument '" + name + "' must be a not empty array"); - }, - - argumentOfType: function (arg, type, name) { - if (!(arg instanceof type)) - throw new Error("The argument '" + name + "' type doesn't match"); - }, - - isNull: function (arg) { - return (arg === null || arg === undefined); - }, - - isPrimitive: function (arg) { - return (arg === null || arg === undefined || typeof (arg) === "string" || - typeof (arg) === "number" || typeof (arg) === "boolean"); - }, - - isInteger: function (arg) { - return parseInt(arg) == arg; - }, - - isNumber: function (arg) { - return parseFloat(arg) == arg; - }, - - isString: function (val) { - return typeof (val) == "string" || val instanceof String; - }, - - isNullOrEmptyString: function (str) { - if (str === null || str === undefined || - ((typeof (str) == "string" || str instanceof String) && str.length === 0)) - return true; - }, - - isNotEmptyArray: function (arg) { - return (arg instanceof Array && arg.length > 0); - }, - - /** - * Выполняет метод для каждого элемента массива, останавливается, когда - * либо достигнут конец массива, либо функция <c>cb</c> вернула - * значение. - * - * @param{Array | Object} obj массив элементов для просмотра - * @param{Function} cb функция, вызываемая для каждого элемента - * @param{Object} thisArg значение, которое будет передано в качестве - * <c>this</c> в <c>cb</c>. - * @returns Результат вызова функции <c>cb</c>, либо <c>undefined</c> - * если достигнут конец массива. - */ - each: function (obj, cb, thisArg) { - safe.argumentNotNull(cb, "cb"); - var i, x; - if (obj instanceof Array) { - for (i = 0; i < obj.length; i++) { - x = cb.call(thisArg, obj[i], i); - if (x !== undefined) - return x; - } - } else { - var keys = _keys(obj); - for (i = 0; i < keys.length; i++) { - var k = keys[i]; - x = cb.call(thisArg, obj[k], k); - if (x !== undefined) - return x; - } - } - }, - - /** - * Копирует свойства одного объекта в другой. - * - * @param{Any} dest объект в который нужно скопировать значения - * @param{Any} src источник из которого будут копироваться значения - * @tmpl{Object|Array} tmpl шаблон по которому будет происходить - * копирование. Если шаблон является массивом - * (список свойств), тогда значения этого массива - * являются именами свойсвт которые будут - * скопированы. Если шаблон является объектом (карта - * преобразования имен свойств src->dst), тогда - * копирование будет осуществляться только - * собственных свойств источника, присутсвующих в - * шаблоне, при этом значение свойства шаблона - * является именем свойства в которое будет - * произведено коприрование - */ - mixin: function (dest, src, tmpl) { - safe.argumentNotNull(dest, "dest"); - if (!src) - return dest; - - var keys, i, p; - if (arguments.length < 3) { - keys = _keys(src); - for (i = 0; i < keys.length; i++) { - p = keys[i]; - dest[p] = src[p]; - } - } else { - if (tmpl instanceof Array) { - for (i = 0; i < tmpl.length; i++) { - p = tmpl[i]; - if (p in src) - dest[p] = src[p]; - } - - } else { - keys = _keys(src); - for (i = 0; i < keys.length; i++) { - p = keys[i]; - if (p in tmpl) - dest[tmpl[p]] = src[p]; - } - } - } - return dest; - }, - - /** Wraps the specified function to emulate an asynchronous execution. - * @param{Object} thisArg [Optional] Object which will be passed as 'this' to the function. - * @param{Function|String} fn [Required] Function wich will be wrapped. - */ - async: function (fn, thisArg) { - if (arguments.length == 2 && !(fn instanceof Function)) - fn = thisArg[fn]; - - if (fn == null) - throw new Error("The function must be specified"); - - function wrapresult(x, e) { - if (e) { - return { - then: function (cb, eb) { - try { - return eb ? wrapresult(eb(e)) : this; - } catch (e2) { - return wrapresult(null, e2); - } - } - }; - } else { - if (x && x.then) - return x; - return { - then : function(cb) { - try { - return cb ? wrapresult(cb(x)) : this; - } catch(e2) { - return wrapresult(e2); - } - } - }; - } - } - - try { - return wrapresult(fn.apply(thisArg, arguments)); - } catch (e) { - return wrapresult(null, e); - }; - }, - - create: function () { - if (console && console.warn) - console.warn("implab/safe::create is deprecated use Object.create instead"); - _create.apply(this, arguments); - }, - - delegate: function (target, method) { - if (!(method instanceof Function)) { - this.argumentNotNull(target, "target"); - method = target[method]; - } - - if (!(method instanceof Function)) - throw new Error("'method' argument must be a Function or a method name"); - - return function () { - return method.apply(target, arguments); - }; - }, - - /** - * Для каждого элемента массива вызывает указанную функцию и сохраняет - * возвращенное значение в массиве результатов. - * - * @remarks cb может выполняться асинхронно, при этом одновременно будет - * только одна операция. - * - * @async - */ - pmap: function (items, cb) { - safe.argumentNotNull(cb, "cb"); - - if (items && items.then instanceof Function) - return items.then(function (data) { - return safe.pmap(data, cb); - }); - - if (safe.isNull(items) || !items.length) - return items; - - var i = 0, - result = []; - - function next() { - var r, ri; - - function chain(x) { - result[ri] = x; - return next(); - } - - while (i < items.length) { - r = cb(items[i], i); - ri = i; - i++; - if (r && r.then) { - return r.then(chain); - } else { - result[ri] = r; - } - } - return result; - } - - return next(); - }, - - /** - * Для каждого элемента массива вызывает указанную функцию, результаты - * не сохраняются - * - * @remarks cb может выполняться асинхронно, при этом одновременно будет - * только одна операция. - * @async - */ - pfor: function (items, cb) { - safe.argumentNotNull(cb, "cb"); - - if (items && items.then instanceof Function) - return items.then(function (data) { - return safe.pmap(data, cb); - }); - - if (safe.isNull(items) || !items.length) - return items; - - var i = 0; - - function next() { - while (i < items.length) { - var r = cb(items[i], i); - i++; - if (r && r.then) - return r.then(next); - } - } - - return next(); - }, - - /** - * Выбирает первый элемент из последовательности, или обещания, если в - * качестве параметра используется обещание, оно должно вернуть массив. - * - * @param{Function} cb обработчик результата, ему будет передан первый - * элемент последовательности в случае успеха - * @param{Fucntion} err обработчик исключения, если массив пустой, либо - * не массив - * - * @remarks Если не указаны ни cb ни err, тогда функция вернет либо - * обещание, либо первый элемент. - * @async - */ - first: function (sequence, cb, err) { - if (sequence) { - if (sequence.then instanceof Function) { - return sequence.then(function (res) { - return safe.first(res, cb, err); - }, err); - } else if (sequence && "length" in sequence) { - if (sequence.length === 0) { - if (err) - return err(new Error("The sequence is empty")); - else - throw new Error("The sequence is empty"); - } - return cb ? cb(sequence[0]) : sequence[0]; - } - } - - if (err) - return err(new Error("The sequence is required")); - else - throw new Error("The sequence is required"); - } - }; - - return safe; - }); \ No newline at end of file
--- a/src/implab/text/format-compile.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -define( - [], - function() { - var map = { - "\\{" : "&curlopen;", - "\\}" : "&curlclose;", - "&" : "&", - "\\:" : ":" - }; - - var rev = { - curlopen : "{", - curlclose : "}", - amp : "&", - colon : ":" - }; - - var espaceString = function(s) { - if (!s) - return s; - return "'" + s.replace(/('|\\)/g, "\\$1") + "'"; - }; - - var encode = function(s) { - if (!s) - return s; - return s.replace(/\\{|\\}|&|\\:/g, function(m) { - return map[m] || m; - }); - }; - - var decode = function(s) { - if (!s) - return s; - return s.replace(/&(\w+);/g, function(m, $1) { - return rev[$1] || m; - }); - }; - - var subst = function(s) { - var i = s.indexOf(":"), name, pattern; - if (i >= 0) { - name = s.substr(0, i); - pattern = s.substr(i + 1); - } else { - name = s; - } - - if (pattern) - return [ - espaceString(decode(name)), - espaceString(decode(pattern)) ]; - else - return [ espaceString(decode(name)) ]; - }; - - var compile = function(str) { - if (!str) - return function() {}; - - var chunks = encode(str).split("{"), chunk; - - var code = [ "var result=[];" ]; - - for (var i = 0; i < chunks.length; i++) { - chunk = chunks[i]; - - if (i === 0) { - if (chunk) - code.push("result.push(" + espaceString(decode(chunk)) + - ");"); - } else { - var len = chunk.indexOf("}"); - if (len < 0) - throw new Error("Unbalanced substitution #" + i); - - code.push("result.push(subst(" + - subst(chunk.substr(0, len)).join(",") + "));"); - if (chunk.length > len + 1) - code.push("result.push(" + - espaceString(decode(chunk.substr(len + 1))) + ");"); - } - } - - code.push("return result.join('');"); - - /* jshint -W054 */ - return new Function("subst", code.join("\n")); - }; - - var cache = {}; - - return function(template) { - var compiled = cache[template]; - if (!compiled) { - compiled = compile(template); - cache[template] = compiled; - } - return compiled; - }; - }); \ No newline at end of file
--- a/src/implab/text/format.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -define([ - "../safe", - "./format-compile", - "dojo/number", - "dojo/date/locale", - "dojo/_base/array" ], function(safe, compile, number, date, array) { - - // {short,medium,full,long}-{date,time} - var convert = function(value, pattern) { - if (!pattern) - return value.toString(); - - if (pattern.toLocaleLowerCase() == "json") { - var cache = []; - return JSON.stringify(value, function(k, v) { - if (!safe.isPrimitive(v)) { - var id = array.indexOf(cache, v); - if (id >= 0) - return "@ref-" + id; - else - return v; - } else { - return v; - } - },2); - } - - if (safe.isNumber(value)) { - var nopt = {}; - if (pattern.indexOf("!") === 0) { - nopt.round = -1; - pattern = pattern.substr(1); - } - nopt.pattern = pattern; - return number.format(value, nopt); - } else if (value instanceof Date) { - var m = pattern.match(/^(\w+)-(\w+)$/); - if (m) - return date.format(value, { - selector : m[2], - formatLength : m[1] - }); - else if (pattern == "iso") - return value.toISOString(); - else - return date.format(value, { - selector : "date", - datePattern : pattern - }); - } else { - return value.toString(pattern); - } - }; - - function formatter(format) { - var data; - - if (arguments.length <= 1) - return format; - - data = Array.prototype.slice.call(arguments, 1); - - var template = compile(format); - - return template(function(name, pattern) { - var value = data[name]; - return !safe.isNull(value) ? convert(value, pattern) : ""; - }); - } - - formatter.compile = function(format) { - var template = compile(format); - - return function() { - var data = arguments; - - return template(function(name, pattern) { - var value = data[name]; - return !safe.isNull(value) ? convert(value, pattern) : ""; - }); - }; - }; - - formatter.convert = convert; - - return formatter; -}); \ No newline at end of file
--- a/src/implab/text/template-compile.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -define( - ["dojo/request", "./format", "../log/trace!"], - function (request, format, trace) { - - // разбивает строку шаблона на токены, возвращает контекст для - // дальнейшей обработки в visitTemplate - var parseTemplate = function (str) { - var tokens = str.split(/(<%=|\[%=|<%|\[%|%\]|%>)/); - var pos = -1; - var data = [], - code = []; - - return { - next: function () { - pos++; - return pos < tokens.length; - }, - token: function () { - return tokens[pos]; - }, - pushData: function () { - var i = data.length; - data.push.apply(data, arguments); - return i; - }, - pushCode : function() { - var i = code.length; - code.push.apply(code, arguments); - return i; - }, - compile: function () { - var text = "var $p = [];\n" + - "var print = function(){\n" + - " $p.push(format.apply(null,arguments));\n" + - "};\n" + - // Introduce the data as local variables using with(){} - "with(obj){\n" + - code.join("\n") + - "}\n" + - "return $p.join('');"; - - try { - var compiled = new Function("obj, format, $data", text); - /** - * Функция форматирования по шаблону - * - * @type{Function} - * @param{Object} obj объект с параметрами для подстановки - */ - return function (obj) { - return compiled(obj || {}, format, data); - }; - } catch (e) { - trace.error([e]); - trace.log([text, data]); - throw e; - } - } - } - }; - - function visitTemplate(context) { - while (context.next()) { - switch (context.token()) { - case "<%": - case "[%": - visitCode(context); - break; - case "<%=": - case "[%=": - visitInline(context); - break; - default: - visitTextFragment(context); - break; - } - } - } - - function visitInline(context) { - var code = ["$p.push("]; - while (context.next()) { - if (context.token() == "%>" || context.token() == "%]") - break; - code.push(context.token()); - } - code.push(");"); - context.pushCode(code.join('')); - } - - function visitCode(context) { - var code = []; - while (context.next()) { - if (context.token() == "%>" || context.token() == "%]") - break; - code.push(context.token()); - } - context.pushCode(code.join('')); - } - - function visitTextFragment(context) { - var i = context.pushData(context.token()); - context.pushCode("$p.push($data["+i+"]);"); - } - - var compile = function (str) { - if (!str) - return function() { return "";}; - - var ctx = parseTemplate(str); - visitTemplate(ctx); - return ctx.compile(); - }; - - var cache = {}; - - compile.load = function (id, require, callback) { - var url = require.toUrl(id); - if (url in cache) { - callback(cache[url]); - } else { - request(url).then(compile).then(function (tc) { - callback(cache[url] = tc); - }, function (err) { - require.signal("error", [{ - error: err, - src: 'implab/text/template-compile' - }]); - }); - } - }; - - return compile; - }); \ No newline at end of file
--- a/src/utest/store/mock.js Sat Jun 23 21:50:11 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -define([ - "dojo/_base/declare", - "dojo/_base/lang", - "dojo/request", - "dojo/store/Memory", - "dojo/Deferred", - "dojo/store/util/QueryResults" - -], function (declare, lang, request, Memory, Deferred, QueryResults) { - /** - * @amdplugin - * @usage - * - * <pre> - * require([ - * "tests/store/mock!./data/sample.json" - * ], function(Store) { - * var store = new Store(); // will create a memory store - * }); - * </pre> - */ - var cache = {}; - return { - load: function (id, require, callback) { - var url = require.toUrl(id); - if (url in cache) { - callback(cache[url]); - } else { - request(url).then(function (data) { - // handle result as text and parse it every time the - // store - // is created to get an independent copy - var f = cache[url] = function (opts) { - var store = new Memory(lang.mixin({ - data: JSON.parse(data), - async: true, - delay: 100 - }, opts || {})); - - declare.safeMixin(store, { - query: function () { - var results = this.inherited(arguments); - if (this.async) { - var d = new Deferred(); - setTimeout(function () { - d.resolve(results); - }, this.delay); - return new QueryResults(d.promise); - } - return results; - }, - - get: function () { - var results = this.inherited(arguments); - if (this.async) { - var d = new Deferred(); - setTimeout(function () { - d.resolve(results); - }, this.delay); - return d.promise; - } - return results; - }, - - put: function () { - var me = this; - - if (me.async) { - var inherited = me.getInherited(arguments); - var args = Array.prototype.slice.apply(arguments); - var d = new Deferred(); - - setTimeout(function () { - d.resolve(inherited.apply(me, args)); - }, me.delay); - - return d.promise; - } - return me.inherited(arguments); - } - }); - - return store; - }; - callback(f); - }, function (err) { - require.signal("error", [{ - error: err, - src: 'implab/store/mock' - }]); - }); - } - } - }; -}); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/utest/src/js/utest/store/mock.js Tue Jun 26 19:35:44 2018 +0300 @@ -0,0 +1,95 @@ +define([ + "dojo/_base/declare", + "dojo/_base/lang", + "dojo/request", + "dojo/store/Memory", + "dojo/Deferred", + "dojo/store/util/QueryResults" + +], function (declare, lang, request, Memory, Deferred, QueryResults) { + /** + * @amdplugin + * @usage + * + * <pre> + * require([ + * "tests/store/mock!./data/sample.json" + * ], function(Store) { + * var store = new Store(); // will create a memory store + * }); + * </pre> + */ + var cache = {}; + return { + load: function (id, require, callback) { + var url = require.toUrl(id); + if (url in cache) { + callback(cache[url]); + } else { + request(url).then(function (data) { + // handle result as text and parse it every time the + // store + // is created to get an independent copy + var f = cache[url] = function (opts) { + var store = new Memory(lang.mixin({ + data: JSON.parse(data), + async: true, + delay: 100 + }, opts || {})); + + declare.safeMixin(store, { + query: function () { + var results = this.inherited(arguments); + if (this.async) { + var d = new Deferred(); + setTimeout(function () { + d.resolve(results); + }, this.delay); + return new QueryResults(d.promise); + } + return results; + }, + + get: function () { + var results = this.inherited(arguments); + if (this.async) { + var d = new Deferred(); + setTimeout(function () { + d.resolve(results); + }, this.delay); + return d.promise; + } + return results; + }, + + put: function () { + var me = this; + + if (me.async) { + var inherited = me.getInherited(arguments); + var args = Array.prototype.slice.apply(arguments); + var d = new Deferred(); + + setTimeout(function () { + d.resolve(inherited.apply(me, args)); + }, me.delay); + + return d.promise; + } + return me.inherited(arguments); + } + }); + + return store; + }; + callback(f); + }, function (err) { + require.signal("error", [{ + error: err, + src: 'implab/store/mock' + }]); + }); + } + } + }; +}); \ No newline at end of file