diff --git a/api.js b/api.js index 8d8989f..01aa8bf 100644 --- a/api.js +++ b/api.js @@ -1,307 +1,318 @@ define([ - "require", - "dojo/_base/declare", - "dojo/_base/lang", - "dojo/_base/window", - "dojo/_base/xhr", - "dojo/has", - "dojo/json", - "dojo/topic", - "./util/value", - "./util/async", - - "./util/generateRandomUuid", - "dojo/Deferred", - "dojo/promise/all", + "require", + "dojo/_base/declare", + "dojo/_base/lang", + "dojo/_base/window", + "dojo/_base/xhr", + "dojo/has", + "dojo/json", + "dojo/topic", + "./util/value", + "./util/async", + + "./util/generateRandomUuid", + "dojo/Deferred", + "dojo/promise/all" ], function(require, declare, lang, window, request, has, json, topic, value, async, - generateRandomUuid, Deferred, whenAll) { - - var ApiError = declare(Error, { - - constructor: function(errorData) { - this.name = "ApiError"; - this.type = errorData.name; - this.message = errorData.message || "(no details)"; - this.error = errorData; - }, - - // toString: function() { - // return 'ApiError "'+this.name+'": '+this.message; - // }, - // toLocaleString: function() { - // return this.toString(); - // // return 'ApiError "'+this.name+'": '+this.message; - // }, - - declaredClass: "ApiError" - - }); - - var self = { - - /** - * @type {string} Default URL, if not given in params - */ - url: '/api', - - /** - * @type {Object} Common parameters which are added automatically to every request - */ - requestCommonParams: {}, - - /** - * @type {string} Name of topic to publish events to. First arg is a boolean telling whether an XHR is active - */ - noticeTopic: 'jig/api/request', - - /** - * Whether to show exceptions to the user - * - * @type {boolean} - */ - showExceptions: false, - - /** - * Number of seconds between pings, when no API request is made during that time - */ - pingDelay: 300, - - /** - * Delay in milliseconds of extra-time to wait before sending the XHR - * - * (used for debugging) - * - * Set to null to disable the grouping of API requests - */ - timeout: 0, - - /** - * Limit upon the number of API calls per XHR - * - * If more API calls are made within the timeout, several XHR will be made - * - * @type {number} - */ - maxReqsPerXHR: 40, - - /** - * Delay between different XHR made because of maxReqsPerXHR - */ - subsequentXHRDelay: 400, - - /** - * Parallel requests deferred to later execution - * - * @type {Object} - */ - _deferredRequests: {}, - - /** - * @type {dojo/Deferred} Global XHR promise for pending XHR call - */ - _deferred: null, - - /** - * Make API request - asynchronous - * - * @param {Object} req Request object - * @param {?Object} object for parameters to pass to dojo XHR. - * @return {dojo/Deferred} promise, resolved with response - */ - request: function(req, options) { - self.cancelPing(); - options = options || {}; - var ret = req.promise = new Deferred(); - ret._request = req; - ret.whenSealed = new Deferred(); - topic.publish(this.noticeTopic, { request: req, options: options }); - if (options) { - req.__options = options; - } - self._deferredRequests[generateRandomUuid()] = req; - - var executeRequests = function() { - // execute all deferred requests - self._timeout = null; - var reqs = lang.mixin({}, self._deferredRequests); - self._deferredRequests = {}; - var _deferred = self._deferred; - - // Take maxReqsPerXHR into account by dividing API calls into groups - var blocks = Object.keys(reqs).reduce(function(blocks, currentKey, idx) { - var lastObj = blocks[blocks.length - 1]; - if (!lastObj || Object.keys(lastObj).length >= self.maxReqsPerXHR) { - blocks.push(lastObj = {}); - - } - lastObj[currentKey] = reqs[currentKey]; - return blocks; - }, []); - if (blocks.length > 1) { - console.info("API: got", Object.keys(reqs).length, "calls, devided into", blocks.length, "XHR"); - } - - // Call self._doRequest() for actual XHR - whenAll(blocks.map(function(block, idx) { - return async.whenTimeout(idx * self.subsequentXHRDelay) - .then(function() { return self._doRequest(block, options); }); - })).then(function() { _deferred.resolve(); }); - }; - - if (!self._timeout) { // order requests, if none is pending through setTimeout() - self._deferred = new Deferred(); - if (self.timeout === null) { - executeRequests(); - } else { - self._timeout = window.global.setTimeout(executeRequests, self.timeout); - } - } - - return ret; - }, - - /** - * Execute XHR for all deferred requests - * - * @return {dojo/Deferred} from XHR call - */ - _doRequest: function(req, options) { - - /** - * Process single-request response - */ - var _processResponseReq = - function(req, response) { - var options = req.__options || {}; - if (response.error) { - if (response.exception) { - console.info("API exception:", response.exception.message); - if (response.exception.previous) { - console.info("API previous exception:", response.exception.previous.message); - } + generateRandomUuid, Deferred, whenAll) { + + var ApiError = declare(Error, { + + constructor: function(errorData) { + this.name = "ApiError"; + this.type = errorData.name; + this.message = errorData.message || "(no details)"; + this.error = errorData; + }, + + // toString: function() { + // return 'ApiError "'+this.name+'": '+this.message; + // }, + // toLocaleString: function() { + // return this.toString(); + // // return 'ApiError "'+this.name+'": '+this.message; + // }, + + declaredClass: "ApiError" + + }); + + var self = { + + /** + * @type {string} Default URL, if not given in params + */ + url: '/api', + + /** + * @type {Object} Common parameters which are added automatically to every request + */ + requestCommonParams: {}, + + /** + * @type {string} Name of topic to publish events to. First arg is a boolean telling whether an XHR is active + */ + noticeTopic: 'jig/api/request', + + /** + * Whether to show exceptions to the user + * + * @type {boolean} + */ + showExceptions: false, + + /** + * Number of seconds between pings, when no API request is made during that time + */ + pingDelay: 300, + + /** + * Delay in milliseconds of extra-time to wait before sending the XHR + * + * (used for debugging) + * + * Set to null to disable the grouping of API requests + */ + timeout: 0, + + /** + * Limit upon the number of API calls per XHR + * + * If more API calls are made within the timeout, several XHR will be made + * + * @type {number} + */ + maxReqsPerXHR: 40, + + /** + * Delay between different XHR made because of maxReqsPerXHR + */ + subsequentXHRDelay: 400, + + /** + * Parallel requests deferred to later execution + * + * @type {Object} + */ + _deferredRequests: {}, + + /** + * @type {dojo/Deferred} Global XHR promise for pending XHR call + */ + _deferred: null, + + /** + * Make API request - asynchronous + * + * @param {Object} req Request object + * @param {?Object} object for parameters to pass to dojo XHR. + * @return {dojo/Deferred} promise, resolved with response + */ + request: function(req, options) { + self.cancelPing(); + options = options || {}; + var ret = req.promise = new Deferred(); + ret._request = req; + ret.whenSealed = new Deferred(); + topic.publish(this.noticeTopic, { + request: req, + options: options + }); + if (options) { + req.__options = options; } - req.promise.reject(new ApiError(response.error)); - return; - } - req.promise.resolve(response); - }; - - /** - * Process XHR (transport) response - */ - var _processResponse = function(text, xhr) { - //console.log('JiG API Response', xhr, text); - // topic.publish('noticeTopic', false); - var i, data = null; - try { - data = json.parse(text); - } - catch (e) { - console.error('JiG API response: invalid JSON string: ', + self._deferredRequests[generateRandomUuid()] = req; + + var executeRequests = function() { + // execute all deferred requests + self._timeout = null; + var reqs = lang.mixin({}, self._deferredRequests); + self._deferredRequests = {}; + var _deferred = self._deferred; + + // Take maxReqsPerXHR into account by dividing API calls into groups + var blocks = Object.keys(reqs).reduce(function(blocks, currentKey, idx) { + var lastObj = blocks[blocks.length - 1]; + if (!lastObj || Object.keys(lastObj).length >= self.maxReqsPerXHR) { + blocks.push(lastObj = {}); + + } + lastObj[currentKey] = reqs[currentKey]; + return blocks; + }, []); + if (blocks.length > 1) { + console.info("API: got", Object.keys(reqs).length, "calls, devided into", blocks.length, "XHR"); + } + + // Call self._doRequest() for actual XHR + whenAll(blocks.map(function(block, idx) { + return async.whenTimeout(idx * self.subsequentXHRDelay) + .then(function() { + return self._doRequest(block, options); + }); + })).then(function() { + _deferred.resolve(); + }); + }; + + if (!self._timeout) { // order requests, if none is pending through setTimeout() + self._deferred = new Deferred(); + if (self.timeout === null) { + executeRequests(); + } else { + self._timeout = window.global.setTimeout(executeRequests, self.timeout); + } + } + + return ret; + }, + + /** + * Execute XHR for all deferred requests + * + * @return {dojo/Deferred} from XHR call + */ + _doRequest: function(req, options) { + + /** + * Process single-request response + */ + var _processResponseReq = + function(req, response) { + var options = req.__options || {}; + if (response.error) { + if (response.exception) { + console.info("API exception:", response.exception.message); + if (response.exception.previous) { + console.info("API previous exception:", response.exception.previous.message); + } + } + req.promise.reject(new ApiError(response.error)); + return; + } + req.promise.resolve(response); + }; + + /** + * Process XHR (transport) response + */ + var _processResponse = function(text, xhr) { + //console.log('JiG API Response', xhr, text); + // topic.publish('noticeTopic', false); + var i, data = null; + try { + data = json.parse(text); + } catch (e) { + console.error('JiG API response: invalid JSON string: ', text, xhr); - for (i in req) { - if (req.hasOwnProperty(i)) { - req[i].promise.reject(new ApiError({ - name: "transport:failed", - message: "invalid JSON" - })); + for (i in req) { + if (req.hasOwnProperty(i)) { + req[i].promise.reject(new ApiError({ + name: "transport:failed", + message: "invalid JSON" + })); + } + } + return; + } + // check if one req or many in the structure + if (typeof req.callback === 'function') { + _processResponseReq(req, data, xhr); + } else { + for (i in data) { + if (data.hasOwnProperty(i)) { + _processResponseReq(req[i], data[i], xhr); + } + } + } + self.delayPing(); + }; + + /** + * Process XHR (transport) failure + */ + var _processError = function(error, xhr) { + console.error('JiG API transport Error: ', error, xhr); + for (var i in req) { + if (req.hasOwnProperty(i)) { + req[i].promise.reject(new ApiError({ + name: "transport:failed" + })); + } + } + }; + + /** + * Make single request structure out of single request params + * + * @param {Object} origRequest + * @return {Object} the structure ready to be serialized + */ + var _prepareRequest = function(origRequest) { + origRequest.promise.whenSealed.resolve(origRequest); + var ret = lang.mixin({}, origRequest, self.requestCommonParams); + delete ret.promise; + delete ret.__options; + return ret; + }; + + var requestToSend; + if (request.module) { + requestToSend = _prepareRequest(req); + } else { + requestToSend = {}; + for (var i in req) { + if (req.hasOwnProperty(i)) { + requestToSend[i] = _prepareRequest(req[i]); + } + } } - } - return; - } - // check if one req or many in the structure - if (typeof req.callback === 'function') { - _processResponseReq(req, data, xhr); - } else { - for (i in data) { - if (data.hasOwnProperty(i)) { - _processResponseReq(req[i], data[i], xhr); + if (has("geonef-debug")) { + try { + var jsonText = json.stringify(requestToSend); + } catch (error) { + console.error("error when stringifying object:", requestToSend); + throw error; + } + } else { + var jsonText = json.stringify(requestToSend); + } + + return request.post(lang.mixin({ + url: options.url || self.url, + handleAs: 'text', + postData: jsonText, + }, options), true) + .then(_processResponse, _processError); + }, + + /** + * Send a dumb API request to preserve the session (timed-out) + * + * Called after an effective API request has been sent. + * The timeout cleared before an API request is sent. + */ + delayPing: function() { + var delay = self.pingDelay * 1000; + self._pingTO = window.global.setTimeout(self.doPing, delay); + }, + + cancelPing: function() { + if (self._pingTO) { + window.global.clearTimeout(self._pingTO); + delete self._pingTO; } - } - } - self.delayPing(); - }; - - /** - * Process XHR (transport) failure - */ - var _processError = function(error, xhr) { - console.error('JiG API transport Error: ', error, xhr); - for (var i in req) { - if (req.hasOwnProperty(i)) { - req[i].promise.reject(new ApiError({name: "transport:failed"})); - } - } - }; - - /** - * Make single request structure out of single request params - * - * @param {Object} origRequest - * @return {Object} the structure ready to be serialized - */ - var _prepareRequest = function(origRequest) { - origRequest.promise.whenSealed.resolve(origRequest); - var ret = lang.mixin({}, origRequest, self.requestCommonParams); - delete ret.promise; - delete ret.__options; - return ret; - }; - - var requestToSend; - if (request.module) { - requestToSend = _prepareRequest(req); - } else { - requestToSend = {}; - for (var i in req) { - if (req.hasOwnProperty(i)) { - requestToSend[i] = _prepareRequest(req[i]); - } - } - } - if (has("geonef-debug")) { - try { - var jsonText = json.stringify(requestToSend); - } catch (error) { - console.error("error when stringifying object:", requestToSend); - throw error; - } - } else { - var jsonText = json.stringify(requestToSend); - } - - return request.post(lang.mixin({ - url: options.url || self.url, - handleAs: 'text', - postData: jsonText, - }, options), true) - .then(_processResponse, _processError); - }, - - /** - * Send a dumb API request to preserve the session (timed-out) - * - * Called after an effective API request has been sent. - * The timeout cleared before an API request is sent. - */ - delayPing: function() { - var delay = self.pingDelay * 1000; - self._pingTO = window.global.setTimeout(self.doPing, delay); - }, - - cancelPing: function() { - if (self._pingTO) { - window.global.clearTimeout(self._pingTO); - delete self._pingTO; - } - }, - - doPing: function() { - self.request({ module: 'user', action: 'ping' } ); - }, - - }; - - return self; - -}); + }, + + doPing: function() { + self.request({ + module: 'user', + action: 'ping' + }); + }, + + }; + + return self; + +}); \ No newline at end of file diff --git a/button/Action.js b/button/Action.js index c2ff237..d459e81 100644 --- a/button/Action.js +++ b/button/Action.js @@ -9,256 +9,262 @@ * */ define([ - "module", - "dojo/_base/declare", - "dijit/_Widget", - - "../util/widget", - "../util/async", - - "dojo/_base/lang", - "dojo/_base/array", - "dojo/_base/window", - "dojo/_base/event", - "dojo/on", - "dojo/keys", - "dojo/topic", - "dojo/dom-construct", - "dojo/dom-class", + "module", + "dojo/_base/declare", + "dijit/_Widget", + + "../util/widget", + "../util/async", + + "dojo/_base/lang", + "dojo/_base/array", + "dojo/_base/window", + "dojo/_base/event", + "dojo/on", + "dojo/keys", + "dojo/topic", + "dojo/dom-construct", + "dojo/dom-class" ], function(module, declare, _Widget, - widget, async, - lang, array, window, event, - on, keys, topic, construct, domClass) { - - var h = lang.hitch; - -return declare(_Widget, { //--noindent-- - - /** - * Link label, HTML supported (innerHTML) - * - * @type {string} - */ - label: '', - - /** - * Content of 'title' tooltip - * - * @type {string} - */ - title: '', - - /** - * If set, onExecute will (dojo.)publish a message on the given channel - * - * @type {string} - */ - publish: '', - - /** - * CSS classes to be set on domNode - * - * @type {string} class - */ - "class": "button", - - /** - * Additional CSS classes to set (obsolete - use 'extraClass' instead) - * - * @type {string} - */ - cssClasses: '', - - /** - * Set 'false' to disable : - * - auto uppercase label when node has the CSS class "important" - */ - autoFeatures: true, - - /** - * If set, a confirmation is asked on mouseClick before calling onExecute - */ - confirm: '', - - /** - * Name of element to create, unless one of 'srcNodeRef' or 'href' is provided - * - * @type {string} - */ - nodeName: 'span', - - /** - * If provided, an element is created rather than - * (whatever is the value of 'nodeName') - * - * @type {string} - */ - href: '', - - target: '', - - /** - * If true, onExecute() is called on a deferred loop - */ - deferExecute: false, - - /** - * If true, do not bubble up the execute() event - * - * It's a kind of "submit", for example it would automatically close - * a dialog or tooltip dialog. - * - * @type {boolean} - */ - noSubmit: false, - - /** - * If true, the submit is made after the call to onExecute(), - * unless the return value is false - * - * @type {boolean} - */ - lateSubmit: false, - - connectA: true, - - tabIndex: undefined, - - // // finally not needed - // enableTouchEvents: true, - // triggerOnTouchStart: false, - - buildRendering: function() { - if (this.srcNodeRef) { - this.domNode = construct.create(this.srcNodeRef.nodeName); - array.forEach(this.srcNodeRef.childNodes, - function(node) { this.domNode.appendChild(node); }, this); - } else { - if (this.href) { - this.domNode = construct.create('a', { href: this.href }); - } else { - this.domNode = construct.create(this.nodeName); - } - } - domClass.add(this.domNode, this["class"]+" "+(this.extraClass||"") + " " + this.cssClasses); - - var tabIndex = this.tabindex; - if (tabIndex === undefined && domClass.contains(this.domNode, "button")) { - tabIndex = 0; - } - if (tabIndex >= -1) { - this.domNode.tabIndex = tabIndex; - } - - if (this.domNode.nodeName !== 'A' || this.connectA) { - this.connect(this.domNode, 'onclick', 'onClick'); - } - this.domNode.innerHTML = " "; - }, - - postCreate: function() { - this.inherited(arguments); - this.own( - on(this.domNode, "keydown", lang.hitch(this, this.onKeyDown)) - ); - // if (this.enableTouchEvents) { - // if (this.triggerOnTouchStart) { - // this.own(on(this.domNode, "touchstart", h(this, this.execute))); - // } else { - // this.own(on(this.domNode, "touchstop", h(this, this.execute))); - // } - // } - }, - - _setLabelAttr: function(label) { - this.label = label; - if (label) { - label = this.autoFeatures && domClass.contains(this.domNode, "important") ? - label.toUpperCase() : label; - } else { - label = " "; - } - this.domNode.innerHTML = label; - }, - - _setTitleAttr: function(title) { - this.title = title; - this.domNode.title = title; - }, - - _setHrefAttr: function(href) { - this.href = href; - this.domNode.href = href; - }, - - _setTargetAttr: function(target) { - this.target = target; - this.domNode.target = target; - }, - - _setDisabledAttr: function(state) { - this.disabled = state; - (state ? domClass.add : domClass.remove)(this.domNode, 'disabled'); - }, - - - onClick: function(evt) { - if (this.domNode.nodeName === 'A') { - if (this.disabled) { - event.stop(evt); - } - return; - } - event.stop(evt); - if (this.disabled) { return; } - var execute = lang.hitch(this, this.execute, evt); - if (!this.confirm || - window.global.confirm(this.confirm)) { - if (this.deferExecute) { - async.whenTimeout(0).then(execute); - } else { - execute(); - } - } - }, - - onKeyDown: function(evt) { - if ([keys.ENTER, keys.SPACE].indexOf(evt.keyCode) !== -1) { - event.stop(evt); - this.execute(evt); - } - }, - - execute: function(evt) { - var ret; - - if (this.lateSubmit) { - ret = this.onExecute(); - } - if (ret !== false && !this.noSubmit) { - widget.bubbleSubmit(this.domNode, evt); - } - if (!this.lateSubmit) { - ret = this.onExecute(); - } - if (this.publish) { - topic.publish(this.publish); - } - // if (ret !== false && !this._destroyed) { - // } - }, - - /** - * Hook - */ - onExecute: function() {}, - - _setEmphasizeAttr: function(state) { - (state ? domClass.add : domClass.remove)(this.domNode, 'emphasize'); - }, - - declaredClass: module.id - -}); - -}); + widget, async, + lang, array, window, event, + on, keys, topic, construct, domClass) { + + var h = lang.hitch; + + return declare(_Widget, { //--noindent-- + + /** + * Link label, HTML supported (innerHTML) + * + * @type {string} + */ + label: '', + + /** + * Content of 'title' tooltip + * + * @type {string} + */ + title: '', + + /** + * If set, onExecute will (dojo.)publish a message on the given channel + * + * @type {string} + */ + publish: '', + + /** + * CSS classes to be set on domNode + * + * @type {string} class + */ + "class": "button", + + /** + * Additional CSS classes to set (obsolete - use 'extraClass' instead) + * + * @type {string} + */ + cssClasses: '', + + /** + * Set 'false' to disable : + * - auto uppercase label when node has the CSS class "important" + */ + autoFeatures: true, + + /** + * If set, a confirmation is asked on mouseClick before calling onExecute + */ + confirm: '', + + /** + * Name of element to create, unless one of 'srcNodeRef' or 'href' is provided + * + * @type {string} + */ + nodeName: 'span', + + /** + * If provided, an element is created rather than + * (whatever is the value of 'nodeName') + * + * @type {string} + */ + href: '', + + target: '', + + /** + * If true, onExecute() is called on a deferred loop + */ + deferExecute: false, + + /** + * If true, do not bubble up the execute() event + * + * It's a kind of "submit", for example it would automatically close + * a dialog or tooltip dialog. + * + * @type {boolean} + */ + noSubmit: false, + + /** + * If true, the submit is made after the call to onExecute(), + * unless the return value is false + * + * @type {boolean} + */ + lateSubmit: false, + + connectA: true, + + tabIndex: undefined, + + // // finally not needed + // enableTouchEvents: true, + // triggerOnTouchStart: false, + + buildRendering: function() { + if (this.srcNodeRef) { + this.domNode = construct.create(this.srcNodeRef.nodeName); + array.forEach(this.srcNodeRef.childNodes, + function(node) { + this.domNode.appendChild(node); + }, this); + } else { + if (this.href) { + this.domNode = construct.create('a', { + href: this.href + }); + } else { + this.domNode = construct.create(this.nodeName); + } + } + domClass.add(this.domNode, this["class"] + " " + (this.extraClass || "") + " " + this.cssClasses); + + var tabIndex = this.tabindex; + if (tabIndex === undefined && domClass.contains(this.domNode, "button")) { + tabIndex = 0; + } + if (tabIndex >= -1) { + this.domNode.tabIndex = tabIndex; + } + + if (this.domNode.nodeName !== 'A' || this.connectA) { + this.connect(this.domNode, 'onclick', 'onClick'); + } + this.domNode.innerHTML = " "; + }, + + postCreate: function() { + this.inherited(arguments); + this.own( + on(this.domNode, "keydown", lang.hitch(this, this.onKeyDown)) + ); + // if (this.enableTouchEvents) { + // if (this.triggerOnTouchStart) { + // this.own(on(this.domNode, "touchstart", h(this, this.execute))); + // } else { + // this.own(on(this.domNode, "touchstop", h(this, this.execute))); + // } + // } + }, + + _setLabelAttr: function(label) { + this.label = label; + if (label) { + label = this.autoFeatures && domClass.contains(this.domNode, "important") ? + label.toUpperCase() : label; + } else { + label = " "; + } + this.domNode.innerHTML = label; + }, + + _setTitleAttr: function(title) { + this.title = title; + this.domNode.title = title; + }, + + _setHrefAttr: function(href) { + this.href = href; + this.domNode.href = href; + }, + + _setTargetAttr: function(target) { + this.target = target; + this.domNode.target = target; + }, + + _setDisabledAttr: function(state) { + this.disabled = state; + (state ? domClass.add : domClass.remove)(this.domNode, 'disabled'); + }, + + + onClick: function(evt) { + if (this.domNode.nodeName === 'A') { + if (this.disabled) { + event.stop(evt); + } + return; + } + event.stop(evt); + if (this.disabled) { + return; + } + var execute = lang.hitch(this, this.execute, evt); + if (!this.confirm || + window.global.confirm(this.confirm)) { + if (this.deferExecute) { + async.whenTimeout(0).then(execute); + } else { + execute(); + } + } + }, + + onKeyDown: function(evt) { + if ([keys.ENTER, keys.SPACE].indexOf(evt.keyCode) !== -1) { + event.stop(evt); + this.execute(evt); + } + }, + + execute: function(evt) { + var ret; + + if (this.lateSubmit) { + ret = this.onExecute(); + } + if (ret !== false && !this.noSubmit) { + widget.bubbleSubmit(this.domNode, evt); + } + if (!this.lateSubmit) { + ret = this.onExecute(); + } + if (this.publish) { + topic.publish(this.publish); + } + // if (ret !== false && !this._destroyed) { + // } + }, + + /** + * Hook + */ + onExecute: function() {}, + + _setEmphasizeAttr: function(state) { + (state ? domClass.add : domClass.remove)(this.domNode, 'emphasize'); + }, + + declaredClass: module.id + + }); + +}); \ No newline at end of file diff --git a/button/DialogAction.js b/button/DialogAction.js index b6eb304..21286dd 100644 --- a/button/DialogAction.js +++ b/button/DialogAction.js @@ -3,66 +3,66 @@ * */ define([ - "module", - "dojo/_base/declare", - "./Action", - "./LazyDropDown", + "module", + "dojo/_base/declare", + "./Action", + "./LazyDropDown", - "dojo/_base/lang", - "dojo/_base/window", - "dojo/dom-style", - "../util/value", - "../util/async", + "dojo/_base/lang", + "dojo/_base/window", + "dojo/dom-style", + "../util/value", + "../util/async" ], function(module, declare, Action, LazyDropDown, - lang, window, style, value, async) { + lang, window, style, value, async) { - // depending on screensize, until 800px (Action) or more (LazyDropDown) - var Parent = window.global.innerWidth <= 800 ? Action : LazyDropDown; + // depending on screensize, until 800px (Action) or more (LazyDropDown) + var Parent = window.global.innerWidth <= 800 ? Action : LazyDropDown; - var mixinPrototype = Parent.prototype.isDropDown ? { // parent is ./DropDown + var mixinPrototype = Parent.prototype.isDropDown ? { // parent is ./DropDown - // LazyDropDown read as is + // LazyDropDown read as is - } : { // parent is ./Action + } : { // parent is ./Action - "class": Parent.prototype["class"] + " dropDown", - ddOptions: {}, + "class": Parent.prototype["class"] + " dropDown", + ddOptions: {}, - onExecute: function() { - var _this = this; - this.getWidget().then(function(widget) { - _this.appView.openPane(widget, { - closeOnClickOut: true, - dialogWidth: window.global.innerWidth - 60 - }); - }); - }, + onExecute: function() { + var _this = this; + this.getWidget().then(function(widget) { + _this.appView.openPane(widget, { + closeOnClickOut: true, + dialogWidth: window.global.innerWidth - 60 + }); + }); + }, - getWidget: function() { - return this.dialogWidget ? async.bindArg(this.dialogWidget) : - this.widgetCreateFunc().then(async.setProp(this, "dialogWidget")); - }, + getWidget: function() { + return this.dialogWidget ? async.bindArg(this.dialogWidget) : + this.widgetCreateFunc().then(async.setProp(this, "dialogWidget")); + }, - widgetCreateFunc: function() { - var _this = this; - return value.getModule(this.ddClass).then(function(_Class) { - // console.log("this.ddOptions", _this.ddOptions, _Class.prototype.declaredClass); - var widget = new _Class(lang.mixin({ - appView: _this.appView, - anchorMode: "dialog", - closeDialogOnClickOut: true, - }, _this.ddOptions)); - widget._floatAnchor = true; - style.set(widget.domNode, _this.ddStyle); - return widget; - }); - }, - }; + widgetCreateFunc: function() { + var _this = this; + return value.getModule(this.ddClass).then(function(_Class) { + // console.log("this.ddOptions", _this.ddOptions, _Class.prototype.declaredClass); + var widget = new _Class(lang.mixin({ + appView: _this.appView, + anchorMode: "dialog", + closeDialogOnClickOut: true, + }, _this.ddOptions)); + widget._floatAnchor = true; + style.set(widget.domNode, _this.ddStyle); + return widget; + }); + }, + }; - return declare(Parent, lang.mixin({ + return declare(Parent, lang.mixin({ - declaredClass: module.id + declaredClass: module.id - }, mixinPrototype)); + }, mixinPrototype)); -}); +}); \ No newline at end of file diff --git a/button/DijitFix.js b/button/DijitFix.js index 606c30e..dbe36f9 100644 --- a/button/DijitFix.js +++ b/button/DijitFix.js @@ -2,34 +2,34 @@ * Mixin class to make a dijit/form/Button-based widget look like button/Action */ define([ - "module", - "dojo/_base/declare", - "dojo/query", - "dojo/NodeList-dom", + "module", + "dojo/_base/declare", + "dojo/query", + "dojo/NodeList-dom" ], function(module, declare, query) { - return declare(null, { //--noindent-- + return declare(null, { //--noindent-- - fixDijitButton: true, - buttonClass: "button", + fixDijitButton: true, + buttonClass: "button", - /** - * @override - */ - buildRendering: function() { - this.inherited(arguments); - if (this.fixDijitButton) { - query(".dijitButtonNode", this.domNode) - .removeClass("dijitButtonNode") - .addClass(this.buttonClass); - } - }, + /** + * @override + */ + buildRendering: function() { + this.inherited(arguments); + if (this.fixDijitButton) { + query(".dijitButtonNode", this.domNode) + .removeClass("dijitButtonNode") + .addClass(this.buttonClass); + } + }, - /** - * The Class name comes from module's -- used by declare() - */ - declaredClass: module.id + /** + * The Class name comes from module's -- used by declare() + */ + declaredClass: module.id - }); + }); -}); +}); \ No newline at end of file diff --git a/button/DropDown.js b/button/DropDown.js index 19ae718..73931a2 100644 --- a/button/DropDown.js +++ b/button/DropDown.js @@ -1,63 +1,62 @@ define([ - "module", - "dojo/_base/declare", - "./Action", - "dijit/_HasDropDown", - "dojo/has", - "dojo/on", - "dijit/focus", - + "module", + "dojo/_base/declare", + "./Action", + "dijit/_HasDropDown", + "dojo/has", + "dojo/on", + "dijit/focus" ], function(module, declare, Action, _HasDropDown, has, on, dijitFocus) { - return declare([Action, _HasDropDown], { - - /** - * @override - */ - "class": Action.prototype["class"] + " dropDown", - - /** - * @override - */ - noSubmit: true, - - toggleOnTouchStart: false, - toggleOnTouchStop: true, - - /** - * Tell others that we are a dropdown class - */ - isDropDown: true, - - /** - * @override - */ - postCreate: function() { - this._buttonNode = this.focusNode = this.domNode; - this.inherited(arguments); - // var _this = this; - // if (this.toggleOnTouchStart) { - // this.own(on(this.domNode, "touchstart", function(e) { - // _this.toggleDropDown(); - // })); - // } - // if (this.toggleOnTouchStop) { - // this.own(on(this.domNode, "touchstop", function(e) { - // _this.toggleDropDown(); - // })); - // } - }, - - // Required by _HasDropDown - focus: function() { - dijitFocus.focus(this.domNode); - }, - - // no "onExecute" callback - managed by mouse/key events of _HasDropDown - // onExecute: function() {}, - - declaredClass: module.id - - }); - -}); + return declare([Action, _HasDropDown], { + + /** + * @override + */ + "class": Action.prototype["class"] + " dropDown", + + /** + * @override + */ + noSubmit: true, + + toggleOnTouchStart: false, + toggleOnTouchStop: true, + + /** + * Tell others that we are a dropdown class + */ + isDropDown: true, + + /** + * @override + */ + postCreate: function() { + this._buttonNode = this.focusNode = this.domNode; + this.inherited(arguments); + // var _this = this; + // if (this.toggleOnTouchStart) { + // this.own(on(this.domNode, "touchstart", function(e) { + // _this.toggleDropDown(); + // })); + // } + // if (this.toggleOnTouchStop) { + // this.own(on(this.domNode, "touchstop", function(e) { + // _this.toggleDropDown(); + // })); + // } + }, + + // Required by _HasDropDown + focus: function() { + dijitFocus.focus(this.domNode); + }, + + // no "onExecute" callback - managed by mouse/key events of _HasDropDown + // onExecute: function() {}, + + declaredClass: module.id + + }); + +}); \ No newline at end of file diff --git a/button/Toggle.js b/button/Toggle.js index e339ab7..d1e7485 100644 --- a/button/Toggle.js +++ b/button/Toggle.js @@ -1,53 +1,51 @@ define([ - "module", - "dojo/_base/declare", - "./Action", - "dojo/dom-class", - + "module", + "dojo/_base/declare", + "./Action", + "dojo/dom-class" ], function(module, declare, Action, domClass) { - return declare(Action, { - - /** - * @override - */ - "class": Action.prototype["class"] + " toggle icon", - - /** - * @override - */ - noSubmit: true, - - /** - * Value - * - * @type {boolean} - */ - value: false, - - /** - * @override - */ - onExecute: function() { - this.set("value", !this.value); - }, - - _setValueAttr: function(state) { - (state ? domClass.add : domClass.remove)(this.domNode, "checked"); - if (state !== this.value) { - this.value = state; - this.onChange(state); - } - }, - - /** - * Hook - */ - onChange: function() {}, - - declaredClass: module.id - - }); - -}); - + return declare(Action, { + + /** + * @override + */ + "class": Action.prototype["class"] + " toggle icon", + + /** + * @override + */ + noSubmit: true, + + /** + * Value + * + * @type {boolean} + */ + value: false, + + /** + * @override + */ + onExecute: function() { + this.set("value", !this.value); + }, + + _setValueAttr: function(state) { + (state ? domClass.add : domClass.remove)(this.domNode, "checked"); + if (state !== this.value) { + this.value = state; + this.onChange(state); + } + }, + + /** + * Hook + */ + onChange: function() {}, + + declaredClass: module.id + + }); + +}); \ No newline at end of file diff --git a/input/BooleanCheckBox.js b/input/BooleanCheckBox.js index 5a7de45..814bcb6 100644 --- a/input/BooleanCheckBox.js +++ b/input/BooleanCheckBox.js @@ -1,120 +1,124 @@ define([ - "module", - "dojo/_base/declare", - "dijit/form/CheckBox", + "module", + "dojo/_base/declare", + "dijit/form/CheckBox", - "dojo/_base/lang", - "dojo/aspect", - "dijit/registry", + "dojo/_base/lang", + "dojo/aspect", + "dijit/registry" ], function(module, declare, CheckBox, - lang, aspect, registry) { + lang, aspect, registry) { - /** - * Same as dijit/CheckBox, but deals with boolean value - * - * dijit/form/CheckBox deals with the HTML way (string value), - * which is usually not what we want - */ - return declare(CheckBox, { - value: false, - /** - * id of input widget to disable according to checkbox state + * Same as dijit/CheckBox, but deals with boolean value * - * If provided, the corresponding widget is disabled when this checkbox - * is set to false. (disabled in the sense of .set('disable', true)) + * dijit/form/CheckBox deals with the HTML way (string value), + * which is usually not what we want */ - toggleInput: '', - - toggleInputInverse: false, - - postMixInProperties: function() { - this.inherited(arguments); - this.checked = this.value; - }, - - destroy: function() { - this.cleanToggleInput(); - this.inherited(arguments); - }, - - startup: function() { - this.inherited(arguments); - this.updateToggleInput(); - }, - - _getValueAttr: function() { - return !!this.checked; - }, - - _setToggleInputAttr: function(id) { - this.toggleInput = id; - if (this._started) { - this.updateToggleInput(); - } - }, - - updateToggleInput: function() { - this.cleanToggleInput(); - if (this.toggleInput) { - var w = registry.byId(this.toggleInput); - if (!w) { - console.warn("widget ID not found: ", this.toggleInput); - return; - } - var savedValue; // static to all calls to the closure below - var notNull = function(v) { return v !== null && v !== undefined && v !== ''; }; - var _this = this; - - function isChecked() { - return _this.toggleInputInverse ? !_this.checked : _this.checked; - } - - var updateFromValue = lang.hitch(this, function() { - var value = w.attr('value'); - if (notNull(value)) { - savedValue = value; - } - if (isChecked() !== notNull(value)) { - this.attr('checked', _this.toggleInputInverse ? !value : !!value); - } - }); - - this._toggleInputCnt = [ - - // Hook on our changes - aspect.before(this, 'onChange', function() { - - if (!isChecked() && !w.attr('disabled')) { - var value = w.attr('value'); - if (notNull(value)) { - savedValue = value; - } - w.attr('value', null); + return declare(CheckBox, { + value: false, + + /** + * id of input widget to disable according to checkbox state + * + * If provided, the corresponding widget is disabled when this checkbox + * is set to false. (disabled in the sense of .set('disable', true)) + */ + toggleInput: '', + + toggleInputInverse: false, + + postMixInProperties: function() { + this.inherited(arguments); + this.checked = this.value; + }, + + destroy: function() { + this.cleanToggleInput(); + this.inherited(arguments); + }, + + startup: function() { + this.inherited(arguments); + this.updateToggleInput(); + }, + + _getValueAttr: function() { + return !!this.checked; + }, + + _setToggleInputAttr: function(id) { + this.toggleInput = id; + if (this._started) { + this.updateToggleInput(); } - if (isChecked() && w.attr('disabled') && notNull(savedValue)) { - w.attr('value', savedValue); + }, + + updateToggleInput: function() { + this.cleanToggleInput(); + if (this.toggleInput) { + var w = registry.byId(this.toggleInput); + if (!w) { + console.warn("widget ID not found: ", this.toggleInput); + return; + } + var savedValue; // static to all calls to the closure below + var notNull = function(v) { + return v !== null && v !== undefined && v !== ''; + }; + var _this = this; + + function isChecked() { + return _this.toggleInputInverse ? !_this.checked : _this.checked; + } + + var updateFromValue = lang.hitch(this, function() { + var value = w.attr('value'); + if (notNull(value)) { + savedValue = value; + } + if (isChecked() !== notNull(value)) { + this.attr('checked', _this.toggleInputInverse ? !value : !!value); + } + }); + + this._toggleInputCnt = [ + + // Hook on our changes + aspect.before(this, 'onChange', function() { + + if (!isChecked() && !w.attr('disabled')) { + var value = w.attr('value'); + if (notNull(value)) { + savedValue = value; + } + w.attr('value', null); + } + if (isChecked() && w.attr('disabled') && notNull(savedValue)) { + w.attr('value', savedValue); + } + w.attr('disabled', !isChecked()); + }), + + // Hook on target widget change + aspect.before(w, 'onChange', updateFromValue) + ]; + updateFromValue(); } - w.attr('disabled', !isChecked()); - }), - - // Hook on target widget change - aspect.before(w, 'onChange', updateFromValue) - ]; - updateFromValue(); - } - }, - - cleanToggleInput: function() { - if (this._toggleInputCnt) { - this._toggleInputCnt.forEach(function(c) { c.remove(); }); - this._toggleInputCnt = undefined; - } - }, + }, + + cleanToggleInput: function() { + if (this._toggleInputCnt) { + this._toggleInputCnt.forEach(function(c) { + c.remove(); + }); + this._toggleInputCnt = undefined; + } + }, - declaredClass: module.id + declaredClass: module.id - }); + }); -}); +}); \ No newline at end of file diff --git a/input/DateTextBox.js b/input/DateTextBox.js index 7256687..2741696 100644 --- a/input/DateTextBox.js +++ b/input/DateTextBox.js @@ -1,46 +1,45 @@ define([ - "module", - "dojo/_base/declare", - "dijit/form/DateTextBox", - "dojo/date/stamp", + "module", + "dojo/_base/declare", + "dijit/form/DateTextBox", + "dojo/date/stamp" ], function(module, declare, DateTextBox, stamp) { -/** - * Extension of dijit/DataTextBox to deal with string date value - * - * It is used in the same way, except that it will work when set with - * a string date value. - * - * The value getter is unchanged and returns a Date object. - */ -return declare(DateTextBox, -{ + /** + * Extension of dijit/DataTextBox to deal with string date value + * + * It is used in the same way, except that it will work when set with + * a string date value. + * + * The value getter is unchanged and returns a Date object. + */ + return declare(DateTextBox, { - timestamp: false, - autoSerialize: false, + timestamp: false, + autoSerialize: false, - _setValueAttr: function(value) { - if (typeof value == 'string') { - // var displayValue = value.replace(/Z/, '').replace(/-/g, '/'); - var displayValue = value; - // var date = new Date(displayValue); - var date = stamp.fromISOString(displayValue); - this.set('value', date); - } else { - this.inherited(arguments); - } - }, + _setValueAttr: function(value) { + if (typeof value == 'string') { + // var displayValue = value.replace(/Z/, '').replace(/-/g, '/'); + var displayValue = value; + // var date = new Date(displayValue); + var date = stamp.fromISOString(displayValue); + this.set('value', date); + } else { + this.inherited(arguments); + } + }, - _getValueAttr: function() { - var value = this.inherited(arguments); - if (value && this.autoSerialize) { - value = this.serialize(value); - } - return value; - }, + _getValueAttr: function() { + var value = this.inherited(arguments); + if (value && this.autoSerialize) { + value = this.serialize(value); + } + return value; + }, - declaredClass: module.id + declaredClass: module.id -}); + }); -}); +}); \ No newline at end of file diff --git a/input/TextBox.js b/input/TextBox.js index 99202dd..6d30006 100644 --- a/input/TextBox.js +++ b/input/TextBox.js @@ -1,29 +1,29 @@ define([ - "module", - "dojo/_base/declare", - "dijit/form/ValidationTextBox", - "./_TextMixin", - "dojo/query", + "module", + "dojo/_base/declare", + "dijit/form/ValidationTextBox", + "./_TextMixin", + "dojo/query" ], function(module, declare, ValidationTextBox, _TextMixin, query) { - /** - * Add some features to dijit/form/TextBox : - * - Pressing ENTER triggers onExecute - * - autoExecute - * - * @class - */ - return declare([ValidationTextBox, _TextMixin], { + /** + * Add some features to dijit/form/TextBox : + * - Pressing ENTER triggers onExecute + * - autoExecute + * + * @class + */ + return declare([ValidationTextBox, _TextMixin], { - postCreate: function() { - this.inherited(arguments); - query('input.dijitValidationInner', this.domNode)[0] - .setAttribute('disabled', 'disabled'); - }, + postCreate: function() { + this.inherited(arguments); + query('input.dijitValidationInner', this.domNode)[0] + .setAttribute('disabled', 'disabled'); + }, - declaredClass: module.id + declaredClass: module.id - }); + }); -}); +}); \ No newline at end of file diff --git a/input/_Container.js b/input/_Container.js index 7e36722..98d5d1b 100644 --- a/input/_Container.js +++ b/input/_Container.js @@ -8,285 +8,311 @@ * class instead. */ define([ - "module", - "dojo/_base/declare", - "dijit/form/_FormMixin", - "dojo/_base/lang", - "dojo/aspect", - "../util/widget", + "module", + "dojo/_base/declare", + "dijit/form/_FormMixin", + "dojo/_base/lang", + "dojo/aspect", + "../util/widget" ], function(module, declare, _FormMixin, lang, aspect, widget) { -return declare(_FormMixin, { //--noindent-- + return declare(_FormMixin, { //--noindent-- - /** - * Name of this item: required if we are a child of another _Container - */ - name: '', + /** + * Name of this item: required if we are a child of another _Container + */ + name: '', - /** - * If true, will return an array (in doc order) rather than a name/value object - * - * @type {boolean} - */ - arrayContainer: false, + /** + * If true, will return an array (in doc order) rather than a name/value object + * + * @type {boolean} + */ + arrayContainer: false, - /** - * If true, returned value is the array of sub-widgets' names whose value is true - * Implies that arrayContainer==true - * - * @type {boolean} - */ - booleanUnion: false, + /** + * If true, returned value is the array of sub-widgets' names whose value is true + * Implies that arrayContainer==true + * + * @type {boolean} + */ + booleanUnion: false, - /** - * All keps specified there are managed by this.attr instead of sub-widgets - * - * @type {Array.} - */ - manageValueKeys: [], + /** + * All keps specified there are managed by this.attr instead of sub-widgets + * + * @type {Array.} + */ + manageValueKeys: [], - additionalRoots: [], + additionalRoots: [], - /** - * 'read-only' property, forwarded to child inputs - */ - readOnly: null, + /** + * 'read-only' property, forwarded to child inputs + */ + readOnly: null, - /** - * @override - */ - postMixInProperties: function() { - this.internalValues = {}; - this.manageValueKeys = lang.clone(this.manageValueKeys); - this.inherited(arguments); - }, + /** + * @override + */ + postMixInProperties: function() { + this.internalValues = {}; + this.manageValueKeys = lang.clone(this.manageValueKeys); + this.inherited(arguments); + }, - /** - * @override - */ - buildRendering: function() { - this.inherited(arguments); - if (!this.containerNode) { - this.containerNode = this.domNode; // needed by parent _FormMixin - } - }, + /** + * @override + */ + buildRendering: function() { + this.inherited(arguments); + if (!this.containerNode) { + this.containerNode = this.domNode; // needed by parent _FormMixin + } + }, - /** - * Find first descendants widgets having a "name" property - * - * When a widget is met, if it has a "name" property, the search does not go deeper. - * If it does not, its sub-widgets are scanned recursively. - * - * @return {Array.} - */ - getDescendants: function() { - var list = []; - this.getInputRootNodes().map(widget.getFirstNamedDescendants) - .forEach(function(set) { set.forEach(function(n) { list.push(n); }); }); - return list; - }, + /** + * Find first descendants widgets having a "name" property + * + * When a widget is met, if it has a "name" property, the search does not go deeper. + * If it does not, its sub-widgets are scanned recursively. + * + * @return {Array.} + */ + getDescendants: function() { + var list = []; + this.getInputRootNodes().map(widget.getFirstNamedDescendants) + .forEach(function(set) { + set.forEach(function(n) { + list.push(n); + }); + }); + return list; + }, - _getDescendantFormWidgets: function() { - return this.getDescendants(); - }, + _getDescendantFormWidgets: function() { + return this.getDescendants(); + }, - /** - * Make the list of DOMNodes to search child inputs into - protected - * - * @return {Array.} - */ - getInputRootNodes: function() { - return [ this.domNode ].concat(this.additionalRoots); - }, + /** + * Make the list of DOMNodes to search child inputs into - protected + * + * @return {Array.} + */ + getInputRootNodes: function() { + return [this.domNode].concat(this.additionalRoots); + }, - /** - * @override - */ - connectChildren: function(){ - // console.log('connectChildren', this, arguments); - this.inherited(arguments); - this.updateChildren(); - }, + /** + * @override + */ + connectChildren: function() { + // console.log('connectChildren', this, arguments); + this.inherited(arguments); + this.updateChildren(); + }, - /** - * need to call this to rescan children and update the "onChange" connections : - * remove the old ones * and add the new ones - */ - updateChildren: function() { - // console.log('updateChildren', this, arguments); - var self = this; - var _oldChildrenCnts = this._childrenCnts || {}; - this._childrenCnts = {}; - this.getDescendants() - .filter(function(item){ return !!item.onChange; }) - .forEach(function(widget) { - if (_oldChildrenCnts.hasOwnProperty(widget.id)) { - self._childrenCnts[widget.id] = _oldChildrenCnts[widget.id]; - delete _oldChildrenCnts[widget.id]; - } else { - self._childrenCnts[widget.id] = - aspect.after(widget, "onChange", lang.hitch(self, self.onChange, widget)); - } - }); - for (var i in _oldChildrenCnts) { - if (_oldChildrenCnts.hasOwnProperty(i)) { - _oldChildrenCnts[i].remove(); - delete _oldChildrenCnts[i]; - } - } - }, + /** + * need to call this to rescan children and update the "onChange" connections : + * remove the old ones * and add the new ones + */ + updateChildren: function() { + // console.log('updateChildren', this, arguments); + var self = this; + var _oldChildrenCnts = this._childrenCnts || {}; + this._childrenCnts = {}; + this.getDescendants() + .filter(function(item) { + return !!item.onChange; + }) + .forEach(function(widget) { + if (_oldChildrenCnts.hasOwnProperty(widget.id)) { + self._childrenCnts[widget.id] = _oldChildrenCnts[widget.id]; + delete _oldChildrenCnts[widget.id]; + } else { + self._childrenCnts[widget.id] = + aspect.after(widget, "onChange", lang.hitch(self, self.onChange, widget)); + } + }); + for (var i in _oldChildrenCnts) { + if (_oldChildrenCnts.hasOwnProperty(i)) { + _oldChildrenCnts[i].remove(); + delete _oldChildrenCnts[i]; + } + } + }, - /** - * hook - called upon value change (at any sub-input's value change) - */ - onChange: function() {}, + /** + * hook - called upon value change (at any sub-input's value change) + */ + onChange: function() {}, - /** - * Focus on first sub-input - */ - focus: function() { - var widgets = this.getDescendants(); - return widgets[0].focus(); - }, + /** + * Focus on first sub-input + */ + focus: function() { + var widgets = this.getDescendants(); + return widgets[0].focus(); + }, - /** - * Get child input by name - * - * @param {string} name - * @return {dijit/_Widget} - */ - getSubWidget: function(name) { - var child = this.getDescendants() - .filter(function(ch) { return ch.name === name; })[0]; - if (!child) { - console.warn('getSubWidget: child not defined: ', name, this.getDescendants(), this); - return null; - } - return child; - }, + /** + * Get child input by name + * + * @param {string} name + * @return {dijit/_Widget} + */ + getSubWidget: function(name) { + var child = this.getDescendants() + .filter(function(ch) { + return ch.name === name; + })[0]; + if (!child) { + console.warn('getSubWidget: child not defined: ', name, this.getDescendants(), this); + return null; + } + return child; + }, - /** - * Set value of sub-input - * - * @deprecated Use instead: getSubWidget(name).set("value", value) - * @param {string} name - * @param {mixed} value - */ - setSubValue: function(name, value) { - this.getSubWidget(name).set('value', value); - }, + /** + * Set value of sub-input + * + * @deprecated Use instead: getSubWidget(name).set("value", value) + * @param {string} name + * @param {mixed} value + */ + setSubValue: function(name, value) { + this.getSubWidget(name).set('value', value); + }, - /** - * Get value of sub-input - * - * @deprecated Use instead: getSubWidget(name).get("value") - * @param {string} name - * @return {mixed} - */ - getSubValue: function(name) { - return this.getSubWidget(name).get('value'); - }, + /** + * Get value of sub-input + * + * @deprecated Use instead: getSubWidget(name).get("value") + * @param {string} name + * @return {mixed} + */ + getSubValue: function(name) { + return this.getSubWidget(name).get('value'); + }, - /** - * @override - */ - _setValueAttr: function(value, priorityChange) { - if (!value) { - this.internalValues = {}; - this.getDescendants().forEach(function(w) { w.set('value', null); }); - } else { - //this.inherited(arguments); - var descendants = this.getDescendants(); - var i; - if (this.booleanUnion) { - descendants.forEach( - function(w) { w.set('value', - value.indexOf(w.get('name')) !== -1); }); - } else if (this.arrayContainer) { - for (i = 0; i < value.length && i < descendants.length; i++) { - descendants[i].set('value', value[i]); - } - } else { - var map = {}; - descendants.forEach(function(w) { map[w.name] = w; }); - for (i in value) { - if (!value.hasOwnProperty(i)) continue; - if (map[i]) { - map[i].set('value', value[i], false); - delete this.internalValues[i]; - } else if (this.manageValueKeys.indexOf(i) !== -1) { - this.set(i, value[i]); - } else { - //console.log('missing widget', i, value[i]); - this.internalValues[i] = value[i]; - } - } - } - } - if (priorityChange || priorityChange === undefined) { - this.onChange(); - } - }, + /** + * @override + */ + _setValueAttr: function(value, priorityChange) { + if (!value) { + this.internalValues = {}; + this.getDescendants().forEach(function(w) { + w.set('value', null); + }); + } else { + //this.inherited(arguments); + var descendants = this.getDescendants(); + var i; + if (this.booleanUnion) { + descendants.forEach( + function(w) { + w.set('value', + value.indexOf(w.get('name')) !== -1); + }); + } else if (this.arrayContainer) { + for (i = 0; i < value.length && i < descendants.length; i++) { + descendants[i].set('value', value[i]); + } + } else { + var map = {}; + descendants.forEach(function(w) { + map[w.name] = w; + }); + for (i in value) { + if (!value.hasOwnProperty(i)) continue; + if (map[i]) { + map[i].set('value', value[i], false); + delete this.internalValues[i]; + } else if (this.manageValueKeys.indexOf(i) !== -1) { + this.set(i, value[i]); + } else { + //console.log('missing widget', i, value[i]); + this.internalValues[i] = value[i]; + } + } + } + } + if (priorityChange || priorityChange === undefined) { + this.onChange(); + } + }, - /** - * @override - */ - _getValueAttr: function() { - var descendants = this.getDescendants(); - var value; - if (this.booleanUnion) { - value = descendants.filter(function(w) { return !!w.get('value'); }). - map(function(w) { return w.get('name'); }); - } else if (this.arrayContainer) { - value = descendants.map(function(w) { return w.get('value'); }); - /*value = []; - for (var i = 0; i < descendants.length; i++) { - value.push(descendants[i].attr('value')); - }*/ - } else { - var self = this; - value = lang.mixin({}, this.internalValues); - descendants.forEach( - function(w) { value[w.name] = w.get('value'); }); - this.manageValueKeys.forEach( - function(p) { value[p] = self.get(p); }); - } - this.getValueHook(value); - return value; - }, + /** + * @override + */ + _getValueAttr: function() { + var descendants = this.getDescendants(); + var value; + if (this.booleanUnion) { + value = descendants.filter(function(w) { + return !!w.get('value'); + }). + map(function(w) { + return w.get('name'); + }); + } else if (this.arrayContainer) { + value = descendants.map(function(w) { + return w.get('value'); + }); + /*value = []; + for (var i = 0; i < descendants.length; i++) { + value.push(descendants[i].attr('value')); + }*/ + } else { + var self = this; + value = lang.mixin({}, this.internalValues); + descendants.forEach( + function(w) { + value[w.name] = w.get('value'); + }); + this.manageValueKeys.forEach( + function(p) { + value[p] = self.get(p); + }); + } + this.getValueHook(value); + return value; + }, - /** - * Hook: called before _getValueAttr() returns. - * - * The value can be modified here - */ - getValueHook: function(value) { - // hook - }, + /** + * Hook: called before _getValueAttr() returns. + * + * The value can be modified here + */ + getValueHook: function(value) { + // hook + }, - /** - * Recursively set child inputs as read-only - * - * @param {boolean} state - */ - _setReadOnlyAttr: function(state) { - this.readOnly = state; - if (state === true || state === false) { - this.getDescendants().forEach( - function(input) { input.set('readOnly', state); }); - } - }, + /** + * Recursively set child inputs as read-only + * + * @param {boolean} state + */ + _setReadOnlyAttr: function(state) { + this.readOnly = state; + if (state === true || state === false) { + this.getDescendants().forEach( + function(input) { + input.set('readOnly', state); + }); + } + }, - /** - * @override - */ - startup: function() { - this.inherited(arguments); - this.connectChildren(); - }, + /** + * @override + */ + startup: function() { + this.inherited(arguments); + this.connectChildren(); + }, - declaredClass: module.id + declaredClass: module.id -}); + }); -}); +}); \ No newline at end of file diff --git a/jig.js b/jig.js new file mode 100644 index 0000000..1c71747 --- /dev/null +++ b/jig.js @@ -0,0 +1,5 @@ +define([ + "geonef/jig/_Widget" +], function(w) { + return {}; +}); \ No newline at end of file diff --git a/tool/Processing.js b/tool/Processing.js index 6f7b9f4..1b84cb4 100644 --- a/tool/Processing.js +++ b/tool/Processing.js @@ -3,105 +3,133 @@ * */ define([ - "module", "require", - "dojo/_base/declare", - "geonef/jig/_Widget", - "dojo/_base/window", - "dojo/dom-style", - "dojo/_base/fx", - "dojo/fx/easing", - "../util/async" + "module", "require", + "dojo/_base/declare", + "geonef/jig/_Widget", + "dojo/_base/window", + "dojo/dom-style", + "dojo/_base/fx", + "dojo/fx/easing", + "../util/async" ], function(module, require, declare, _Widget, window, style, fx, easing, async) { -return declare(_Widget, { //--noindent-- - - /** - * @type {?HTMLElement} - */ - processingNode: null, - - fxAppearDuration: 400, - fxDisappearDuration: 200, - - iconUrl: require.toUrl('geonef/jig/style/icon'), - - "class": _Widget.prototype["class"] + " jigWidgetProcessing", - - - makeContentNodes: function() { - return [ - ["div", {"class": "bg"}, " "], - ["div", {"class": "content"}, [ - ["span", {}], - // ["img", { src: this.iconUrl + "/spinner32.gif", - // alt: "Loading..." }] - ]], - - ]; - }, - - postCreate: function() { - this.inherited(arguments); - if (this.processingNode && !this.domNode.parentNode) { - // console.log("style.get(this.processingNode, 'position')", ); - if (style.get(this.processingNode, 'position') === 'static') { - style.set(this.processingNode, 'position', 'relative'); - } - this.placeFx(this.processingNode); - } - }, - - placeFx: function(node) { - style.set(this.domNode, 'opacity', 0); - this.placeAt(node); - var _this = this; - this.placeAnim = fx.animateProperty( - { - node: this.domNode, duration: this.fxAppearDuration, - properties: { - opacity: { start: 0, end: 1 } + return declare(_Widget, { //--noindent-- + + /** + * @type {?HTMLElement} + */ + processingNode: null, + spinnerSize: null, + defaultSpinnerSize: 32, + + fxAppearDuration: 400, + fxDisappearDuration: 200, + + iconUrl: require.toUrl('geonef/jig/style/icon'), + + "class": _Widget.prototype["class"] + " jigWidgetProcessing", + + postMixInProperties: function() { + this.inherited(arguments); + this.spinnerSize = this.spinnerSize || this.defaultSpinnerSize; + }, + + makeContentNodes: function() { + return [ + ["div", { + "class": "bg", + _attach: "bg" + }, " "], + ["div", { + "class": "content spinner-" + this.spinnerSize, + _attach: "content" + }, + [ + ["span", {}], + // ["img", { src: this.iconUrl + "/spinner32.gif", + // alt: "Loading..." }] + ] + ], + + ]; + }, + + postCreate: function() { + this.inherited(arguments); + if (this.processingNode && !this.domNode.parentNode) { + // console.log("style.get(this.processingNode, 'position')", ); + if (style.get(this.processingNode, 'position') === 'static') { + style.set(this.processingNode, 'position', 'relative'); + } + var zIndex = style.get(this.processingNode, 'z-index'); + if (isNaN(zIndex)) { + zIndex = 1; + } + style.set(this.bg, "z-index", zIndex + 1); + style.set(this.content, "z-index", zIndex + 2); + this.placeFx(this.processingNode); + } }, - easing: easing.sinIn, - onEnd: function() { - delete _this.placeAnim; - } - }); - this.placeAnim.play(); - }, - - - startup: function() { - - }, - - end: function() { - this.destroyFx(); - }, - - destroyFx: function() { - if (this._destroyed) { return; } - if (this.placeAnim) { - this.placeAnim.stop(false); - delete this.placeAnim; - } - var destroy = async.deferHitch(this, this.destroy); - fx.animateProperty( - { - node: this.domNode, duration: this.fxDisappearDuration, - properties: { - opacity: { start: 1, end: 0 } + + placeFx: function(node) { + style.set(this.domNode, 'opacity', 0); + this.placeAt(node); + var _this = this; + this.placeAnim = fx.animateProperty({ + node: this.domNode, + duration: this.fxAppearDuration, + properties: { + opacity: { + start: 0, + end: 1 + } + }, + easing: easing.sinIn, + onEnd: function() { + delete _this.placeAnim; + } + }); + this.placeAnim.play(); + }, + + + startup: function() { + + }, + + end: function() { + this.destroyFx(); + }, + + destroyFx: function() { + if (this._destroyed) { + return; + } + if (this.placeAnim) { + this.placeAnim.stop(false); + delete this.placeAnim; + } + var destroy = async.deferHitch(this, this.destroy); + fx.animateProperty({ + node: this.domNode, + duration: this.fxDisappearDuration, + properties: { + opacity: { + start: 1, + end: 0 + } + }, + easing: easing.sinIn, + onEnd: function() { + if (!window.global.__debug_keepProcessing) { + destroy(); + } + } + }).play(); }, - easing: easing.sinIn, - onEnd: function() { - if (!window.global.__debug_keepProcessing) { - destroy(); - } - } - }).play(); - }, - declaredClass: module.id + declaredClass: module.id -}); + }); -}); +}); \ No newline at end of file diff --git a/util/async.js b/util/async.js index 67c49a2..624df03 100644 --- a/util/async.js +++ b/util/async.js @@ -2,226 +2,231 @@ * Utilities about deferred, promises and asynchronicity in general */ define([ - "require", // the getModule() function also uses the global AMD 'require' function - "dojo/Deferred", - "dojo/_base/lang", - "dojo/_base/window", - "dojo/_base/kernel", - "dojo/promise/all", + "require", // the getModule() function also uses the global AMD 'require' function + "dojo/Deferred", + "dojo/_base/lang", + "dojo/_base/window", + "dojo/_base/kernel", + "dojo/promise/all" ], function(myRequire, Deferred, lang, window, kernel, allPromises) { -var self = { //--noindent-- - - /** - * Generate an already-resolved deferred - * - * WILL SOON BE OBSOLETE IN FAVOR OF bindArg() with no promise - * - * Useful for async-style function which return a sync value. - * This can be seen as an "async wrapper" for sync values. - * - * @return {dojo/Deferred} - */ - newResolved: function(arg) { - var deferred = new Deferred(); - deferred.resolve(arg); - return deferred; - }, - - /** - * Bind the given arg the the promise and return the new (bound) promise - * - * Kind of dojo's lang.hitch(). - * If no promise is given, a new one is created, already resolved. - * - * @param {mixed} arg - * @param {dojo/Deferred} promise - * @return {dojo/Deferred} - */ - bindArg: function(arg, promise) { - if (!promise) { - promise = new Deferred(); - promise.resolve(arg); - return promise; - } - return promise.then(function() { return arg; }); - }, - - newRejected: function(error) { - var promise = new Deferred(); - promise.reject(error); - return promise; - }, - - /** - * Multiplex multiple deferreds - * - * TODO: use directly dojo/promise/all - * - * @deprecated use dojo's dojo/promise/all instead - * @return {dojo/Deferred} - */ - // whenAll: function(deferreds) { - // kernel.deprecated("geonef/jig/util/async.whenAll()", - // "use dojo/promise/all instead"); - // return allPromises(deferreds); - // }, - - /** - * @param {Number} delay in milliseconds (arg 2 to dojo/global/setTimeout) - */ - whenTimeout: function(delay) { - var id; - var deferred = new Deferred(function(reason) { - if (id) { - window.global.clearTimeout(id); - id = null; - } - }); - id = window.global.setTimeout(function() { - deferred.resolve(); - id = null; - }, delay); - - return deferred; - }, - - /** - * Test given func until it returns true - * - * This can be useful to wait for the DOM to be updated, for example. - * - * @param {Function} testFunc test function - * @param {integer} delay delay between each test (in milliseconds) - * @param {integer} timeout time before giving up (milliseconds) - * @return {dojo/Deferred} - */ - whenSatisfied: function(testFunc, delay, timeout) { - var promise = new Deferred(); - timeout = timeout || 2000; - delay = delay || 50; - var count = timeout / delay; - var checkFunc = function() { - if (testFunc()) { - promise.resolve(); - } else { - --count; - if (count > 0) { - window.global.setTimeout(checkFunc, delay || 50); - } else { - console.warn("whenSatisfied: timeout has passed: ", timeout, "Giving up."); - promise.reject("timeout"); - } - } - }; - checkFunc(); - - return promise; - }, - - /** - * Create busy effect on node until returned function is called - * - * Example: - * deferred.then(geonef/jig/util/busy(node)) - * - * @param {DOMElement} node - * @return {function} must be called to stop the busy effect - */ - busy: function(node) { - var control; - myRequire(["../tool/Processing"], function(Processing) { - if (control !== null) { // if terminate callback was called before we are - control = new Processing({ processingNode: node }); - control.startup(); - } - }); - return function(arg) { - if (control) { - control.end(); - } else { - control = null; - } - return arg; - }; - }, - - /** - * Return a function which will set its arg to the given obj - * - * @param {Object} obj - * @param {string} name - * @return {Function} - */ - setProp: function(obj, propName) { - return function(arg) { - obj[propName] = arg; - return arg; - }; - }, - - /** - * Wrap call into timeout function - */ - deferHitch: function(scope, func) { - var _func = lang.hitch.apply(null, arguments); - return function() { - self.whenTimeout(0).then(_func); - }; - }, - - /** - * Return a function that will return a promise resolved when - * the given promise is resolved. - * - * The promise will be resolved with the argument provided - * to the function. - */ - deferWhen: function(promise) { - return function(arg) { - return self.bindArg(arg, promise); + var self = { //--noindent-- + + /** + * Generate an already-resolved deferred + * + * WILL SOON BE OBSOLETE IN FAVOR OF bindArg() with no promise + * + * Useful for async-style function which return a sync value. + * This can be seen as an "async wrapper" for sync values. + * + * @return {dojo/Deferred} + */ + newResolved: function(arg) { + var deferred = new Deferred(); + deferred.resolve(arg); + return deferred; + }, + + /** + * Bind the given arg the the promise and return the new (bound) promise + * + * Kind of dojo's lang.hitch(). + * If no promise is given, a new one is created, already resolved. + * + * @param {mixed} arg + * @param {dojo/Deferred} promise + * @return {dojo/Deferred} + */ + bindArg: function(arg, promise) { + if (!promise) { + promise = new Deferred(); + promise.resolve(arg); + return promise; + } + return promise.then(function() { + return arg; + }); + }, + + newRejected: function(error) { + var promise = new Deferred(); + promise.reject(error); + return promise; + }, + + /** + * Multiplex multiple deferreds + * + * TODO: use directly dojo/promise/all + * + * @deprecated use dojo's dojo/promise/all instead + * @return {dojo/Deferred} + */ + // whenAll: function(deferreds) { + // kernel.deprecated("geonef/jig/util/async.whenAll()", + // "use dojo/promise/all instead"); + // return allPromises(deferreds); + // }, + + /** + * @param {Number} delay in milliseconds (arg 2 to dojo/global/setTimeout) + */ + whenTimeout: function(delay) { + var id; + var deferred = new Deferred(function(reason) { + if (id) { + window.global.clearTimeout(id); + id = null; + } + }); + id = window.global.setTimeout(function() { + deferred.resolve(); + id = null; + }, delay); + + return deferred; + }, + + /** + * Test given func until it returns true + * + * This can be useful to wait for the DOM to be updated, for example. + * + * @param {Function} testFunc test function + * @param {integer} delay delay between each test (in milliseconds) + * @param {integer} timeout time before giving up (milliseconds) + * @return {dojo/Deferred} + */ + whenSatisfied: function(testFunc, delay, timeout) { + var promise = new Deferred(); + timeout = timeout || 2000; + delay = delay || 50; + var count = timeout / delay; + var checkFunc = function() { + if (testFunc()) { + promise.resolve(); + } else { + --count; + if (count > 0) { + window.global.setTimeout(checkFunc, delay || 50); + } else { + console.warn("whenSatisfied: timeout has passed: ", timeout, "Giving up."); + promise.reject("timeout"); + } + } + }; + checkFunc(); + + return promise; + }, + + /** + * Create busy effect on node until returned function is called + * + * Example: + * deferred.then(geonef/jig/util/busy(node)) + * + * @param {DOMElement} node + * @return {function} must be called to stop the busy effect + */ + busy: function(node, spinnerSize) { + var control; + myRequire(["../tool/Processing"], function(Processing) { + if (control !== null) { // if terminate callback was called before we are + control = new Processing({ + processingNode: node, + spinnerSize: spinnerSize + }); + control.startup(); + } + }); + return function(arg) { + if (control) { + control.end(); + } else { + control = null; + } + return arg; + }; + }, + + /** + * Return a function which will set its arg to the given obj + * + * @param {Object} obj + * @param {string} name + * @return {Function} + */ + setProp: function(obj, propName) { + return function(arg) { + obj[propName] = arg; + return arg; + }; + }, + + /** + * Wrap call into timeout function + */ + deferHitch: function(scope, func) { + var _func = lang.hitch.apply(null, arguments); + return function() { + self.whenTimeout(0).then(_func); + }; + }, + + /** + * Return a function that will return a promise resolved when + * the given promise is resolved. + * + * The promise will be resolved with the argument provided + * to the function. + */ + deferWhen: function(promise) { + return function(arg) { + return self.bindArg(arg, promise); + }; + }, + + /** + * Flexible AMD module getter + * + * If 'name' is a string, the module is required, using the given + * 'contextRequire' function (if provided), or the global one. + * + * If 'name' is a promise, that will be resolved first, then + * getModule() is called again with the promise value + * (which again can be a string, a module ref or a class). + * + * If 'name' is not a string, it is simply returned (through the deferred). + * + * @param {mixed} name + * @param {!Function} contextRequire context-sensitive require function + * @return {dojo/Deferred} + */ + getModule: function(name, contextRequire) { + if (name.load) { + return name.load(); + } + if (name.then) { + return name.then(function(resolvedName) { + return self.getModule(resolvedName, contextRequire); + }); + } + var deferred = new Deferred(); + if (typeof name === "string") { + (contextRequire || require)([name], function(module) { + deferred.resolve(module); + }); + } else { + deferred.resolve(name); + } + return deferred; + } + }; - }, - - /** - * Flexible AMD module getter - * - * If 'name' is a string, the module is required, using the given - * 'contextRequire' function (if provided), or the global one. - * - * If 'name' is a promise, that will be resolved first, then - * getModule() is called again with the promise value - * (which again can be a string, a module ref or a class). - * - * If 'name' is not a string, it is simply returned (through the deferred). - * - * @param {mixed} name - * @param {!Function} contextRequire context-sensitive require function - * @return {dojo/Deferred} - */ - getModule: function(name, contextRequire) { - if (name.load) { - return name.load(); - } - if (name.then) { - return name.then(function(resolvedName) { - return self.getModule(resolvedName, contextRequire); - }); - } - var deferred = new Deferred(); - if (typeof name === "string") { - (contextRequire || require)([name], function(module) { - deferred.resolve(module); - }); - } else { - deferred.resolve(name); - } - return deferred; - }, - -}; - - return self; - -}); + + return self; + +}); \ No newline at end of file diff --git a/util/makeDOM.js b/util/makeDOM.js index 6fd73f0..6edfe84 100644 --- a/util/makeDOM.js +++ b/util/makeDOM.js @@ -63,216 +63,237 @@ * @return {?DOMElement|dojo/Deferred} */ define([ - "dojo/_base/lang", - "dojo/dom-construct", - "dojo/promise/all", - "dijit/_Widget", - "dijit/Tooltip", + "dojo/_base/lang", + "dojo/dom-construct", + "dojo/promise/all", + "dijit/_Widget", + "dijit/Tooltip" ], function(lang, construct, whenAll, _Widget, Tooltip) { - function addChildTo(node, childNode) { + function addChildTo(node, childNode) { - if (!childNode) { - return null; - } + if (!childNode) { + return null; + } - var _do = - function(childNode) { - if (childNode) { - node.appendChild(childNode); + var _do = + function(childNode) { + if (childNode) { + node.appendChild(childNode); + } + return childNode; + }; + + if (childNode.then) { + return childNode.then(_do); } - return childNode; - }; - if (childNode.then) { - return childNode.then(_do); + return _do(childNode); } - return _do(childNode); - } - - function addChildren(children, node, obj) { + function addChildren(children, node, obj) { - var addChild = lang.hitch(null, addChildTo, node); + var addChild = lang.hitch(null, addChildTo, node); - if (children) { - var child = children; - if (child instanceof Array) { - if (typeof child[0] == 'string' || typeof child[0] == 'function') { - // child is an args array for makeDOM - var childNode = self(child, obj); - addChild(childNode); - } else { - // assume child is an array of args - child.map(function(c) { return self(c, obj); }) - .forEach(addChild); + if (children) { + var child = children; + if (child instanceof Array) { + if (typeof child[0] == 'string' || typeof child[0] == 'function') { + // child is an args array for makeDOM + var childNode = self(child, obj); + addChild(childNode); + } else { + // assume child is an array of args + child.map(function(c) { + return self(c, obj); + }) + .forEach(addChild); + } + } else if (child instanceof HTMLElement || child.then) { + addChild(child); + } else { + // scalar content value - set as text + node.innerHTML = child; + } } - } else if (child instanceof HTMLElement || child.then) { - addChild(child); - } else { - // scalar content value - set as text - node.innerHTML = child; - } } - } - /** - * Main module function - */ - function self(args, obj) { - // console.log('makeDOM args=', args); - obj = obj || {}; - var node, widget; + /** + * Main module function + */ + function self(args, obj) { + // console.log('makeDOM args=', args); + obj = obj || {}; + var node, widget; - var attrs = {}, magic = {}; - if (args && args[1]) { - lang.mixin(attrs, args[1]); - ['_attach', '_insert', '_insertPosition', '_tooltip', '_tooltipOptions', - '_srcNodeName', '_if', '_ifNot', '_style'].forEach( - function(attr) { - if (attrs[attr] !== undefined) { - magic[attr] = attrs[attr]; - delete attrs[attr]; - } - }); - if (magic._if !== undefined) { - if (!magic._if) { return null; } - if (magic._if.then) { - return magic._if.then( - function(ret) { - if (!ret) { return null; } + var attrs = {}, + magic = {}; + if (args && args[1]) { + lang.mixin(attrs, args[1]); + ['_attach', '_insert', '_insertPosition', '_tooltip', '_tooltipOptions', + '_srcNodeName', '_if', '_ifNot', '_style' + ].forEach( + function(attr) { + if (attrs[attr] !== undefined) { + magic[attr] = attrs[attr]; + delete attrs[attr]; + } + }); + if (magic._if !== undefined) { + if (!magic._if) { + return null; + } + if (magic._if.then) { + return magic._if.then( + function(ret) { + if (!ret) { + return null; + } - var _args = args.slice(0); - _args[1] = lang.mixin({}, _args[1]); - delete _args[1]._ifNot; + var _args = args.slice(0); + _args[1] = lang.mixin({}, _args[1]); + delete _args[1]._ifNot; - return self(_args, obj); - }); - } - } - if (magic._ifNot) { - if (magic._ifNot.then) { - return magic._ifNot.then( - function(ret) { - if (ret) { return null; } + return self(_args, obj); + }); + } + } + if (magic._ifNot) { + if (magic._ifNot.then) { + return magic._ifNot.then( + function(ret) { + if (ret) { + return null; + } - var _args = args.slice(0); - _args[1] = lang.mixin({}, _args[1]); - delete _args[1]._ifNot; + var _args = args.slice(0); + _args[1] = lang.mixin({}, _args[1]); + delete _args[1]._ifNot; - return self(_args, obj); - }); + return self(_args, obj); + }); + } + return null; + } + if (magic._style) { + attrs.style = Object.keys(magic._style) + .map(function(key) { + return key + ":" + magic._style[key]; + }).join(";"); + } } - return null; - } - if (magic._style) { - attrs.style = Object.keys(magic._style) - .map(function(key) { return key+":"+magic._style[key]; }).join(";"); - } - } - //// - - if (!args) { return null; } - if (args instanceof HTMLElement) { - return args; - } - if (args.then) { - return args.then(function(def) { return self(def, obj); }); - } - if (args.domNode) { - widget = args; - // .domNode; - } else { - - if (!(args instanceof Array)) { - console.error("args is: ", args); - throw new Error("makeDOM: args is not an array not promise or a DOM element"); - } - if (!args.length) { - return []; - } - if (!args[0]) { - console.error("obj is: ", obj, " and args are: ", args); - throw new Error("makeDOM: args[0] is null: undeclared widget class?"); - } - if (args[0] && ['string', 'function'].indexOf(typeof args[0]) === -1) { - // if args[0] is neither of string, function or falsy: assume node-array mode - // todo: manage async - args = args.map(function(def) { return self(def, obj); }); - //// These 2 lines should work but has not been tested yet [20150204]: - // var promises = args.filter(function(arg) { return arg && arg.then; }); - // return promises.length > 0 ? whenAll(args) : args; - return args; - } + //// - // if (args[0] instanceof Array || args[0].then) { - // return args.map(function(def) { return self(def, obj); }); - // } - // if (args[0] instanceof _Widget) { - // return args[0].domNode; - // } - // if (args[0] instanceof HTMLElement) { - // return args[0]; - // } - if (typeof args[0] == 'function') { // assume widget class - var _Class = args[0]; - var srcNode = null; - if (magic._srcNodeName) { - srcNode = self([magic._srcNodeName, {}, args[2]], obj); + if (!args) { + return null; } - widget = new _Class(lang.mixin(attrs, obj && obj.domWidgetProps), srcNode); - if (!magic._srcNodeName) { - addChildren(args[2], widget.containerNode, obj); + if (args instanceof HTMLElement) { + return args; } - } else if (!args[0]) { - console.error("obj is: ", obj, " and args are: ", args); - throw new Error("makeDOM: args[0] is null: undeclared widget class?"); - } else { // assume string - node name of DOMElement to create - node = construct.create(args[0], attrs); - addChildren(args[2], node, obj); - if (magic._attach) { - obj[magic._attach] = node; + if (args.then) { + return args.then(function(def) { + return self(def, obj); + }); } - } - } - if (widget) { - node = widget.domNode; - if (obj.domWidgets) { - obj.domWidgets.push(widget); - } + if (args.domNode) { + widget = args; + // .domNode; + } else { - if (obj._started) { - widget.startup(); - } + if (!(args instanceof Array)) { + console.error("args is: ", args); + throw new Error("makeDOM: args is not an array not promise or a DOM element"); + } + if (!args.length) { + return []; + } + if (!args[0]) { + console.error("obj is: ", obj, " and args are: ", args); + throw new Error("makeDOM: args[0] is null: undeclared widget class?"); + } + if (args[0] && ['string', 'function'].indexOf(typeof args[0]) === -1) { + // if args[0] is neither of string, function or falsy: assume node-array mode + // todo: manage async + args = args.map(function(def) { + return self(def, obj); + }); + //// These 2 lines should work but has not been tested yet [20150204]: + // var promises = args.filter(function(arg) { return arg && arg.then; }); + // return promises.length > 0 ? whenAll(args) : args; + return args; + } - if (magic._attach) { - if (obj[magic._attach] instanceof Array) { - obj[magic._attach].push(widget); - } else { - obj[magic._attach] = widget; + // if (args[0] instanceof Array || args[0].then) { + // return args.map(function(def) { return self(def, obj); }); + // } + // if (args[0] instanceof _Widget) { + // return args[0].domNode; + // } + // if (args[0] instanceof HTMLElement) { + // return args[0]; + // } + if (typeof args[0] == 'function') { // assume widget class + var _Class = args[0]; + var srcNode = null; + if (magic._srcNodeName) { + srcNode = self([magic._srcNodeName, {}, args[2]], obj); + } + widget = new _Class(lang.mixin(attrs, obj && obj.domWidgetProps), srcNode); + if (!magic._srcNodeName) { + addChildren(args[2], widget.containerNode, obj); + } + } else if (!args[0]) { + console.error("obj is: ", obj, " and args are: ", args); + throw new Error("makeDOM: args[0] is null: undeclared widget class?"); + } else { // assume string - node name of DOMElement to create + node = construct.create(args[0], attrs); + addChildren(args[2], node, obj); + if (magic._attach) { + obj[magic._attach] = node; + } + } } - } - } + if (widget) { + node = widget.domNode; + if (obj.domWidgets) { + obj.domWidgets.push(widget); + } - if (magic._insert) { - construct.place(node, magic._insert, magic._insertPosition); - // magic._insert.appendChild(node); - } - if (magic._tooltip) { - var tooltip = new Tooltip( - lang.mixin({ label: magic._tooltip, connectId: [node], - showDelay: 200, position: ['below', 'above'] - }, magic._tooltipOptions)); - if (obj.domWidgets) { - obj.domWidgets.push(tooltip); - } - } + if (obj._started) { + widget.startup(); + } - // console.log('makeDOM', args, 'returning', node); + if (magic._attach) { + if (obj[magic._attach] instanceof Array) { + obj[magic._attach].push(widget); + } else { + obj[magic._attach] = widget; + } + } + } + + if (magic._insert) { + construct.place(node, magic._insert, magic._insertPosition); + // magic._insert.appendChild(node); + } + if (magic._tooltip) { + var tooltip = new Tooltip( + lang.mixin({ + label: magic._tooltip, + connectId: [node], + showDelay: 200, + position: ['below', 'above'] + }, magic._tooltipOptions)); + if (obj.domWidgets) { + obj.domWidgets.push(tooltip); + } + } + + // console.log('makeDOM', args, 'returning', node); - return node; - } + return node; + } - return self; -}); + return self; +}); \ No newline at end of file diff --git a/util/number.js b/util/number.js index 4b71c37..d2f43a0 100644 --- a/util/number.js +++ b/util/number.js @@ -2,128 +2,135 @@ * Utility functions dealing with angles */ define([ - "dojo/_base/lang", - "dojo/number", - // "dojo/i18n!../nls/number", + "dojo/_base/lang", + "dojo/number" + // "dojo/i18n!../nls/number", ], function(lang, dojoNumber) { -var self = { //--noindent-- - - /** - * Format a number - * - * Forwarded to dojo/number/format, but before, the number is - * rounded depending on the "digits" option. - * - * @param {number} value - * @param {Object} options - * @return {string} - * @nosideeffects - */ - format: function(value, options) { - if (options && options.digits) { - var nb = Math.ceil(Math.log(value) / Math.LN10); - var factor = nb < options.digits ? Math.pow(10, options.digits - nb) : 1; - value = Math.round(value * factor) / factor; - } - return dojoNumber.format(value, options); - }, - - - /** - * Format an array of numbers (called "dimensions") - * - * Can typically work on 2D or 3D coordinates, sizes... - * Can also work on simple numbers (call: formatDims([number])) - * - * Examples: - * formatDims([fileWeight], { mult: 1024, - * units: ['B', 'KiB', 'MiB', 'GiB' ]}) - * formatDims([width, height], { units ['m', 'km'] }) - * - * @param {Array.} dims Array of float numbers so that dims.length >= 1 - * @param {Object} options Used to override default options. Options are: - * mult: exp base between units - * units: array - * string array specifying the unit names in powers - * of "options.mult". - * preci: float - * precision for decimal part (ex: 0.1, 0.01, 0.001 ...) - * joinSep: string - * separator for numbers serialization (join) - * - * Specify options.mult for no-SI units (ex: KiB, MiB use 1024) - * @return {string} - * @nosideeffects - */ - formatDims: function(dims, options) { - var o = lang.mixin({ - units: [ '', 'K', 'M' ], - mult: 1000, - preci: 0.1, - joinSep: ' ; ', - decimalSep: ',', - space: " ", - }, options); - var max = Math.max.apply(null, dims), - logNp = function(x, base) { - return Math.max(0, Math.floor(Math.log(x) / Math.log(base))); }, - exp = Math.min(logNp(max, o.mult), o.units.length - 1), - getU = function(x) { return x < 0 ? x : - Math.round((x / Math.pow(o.mult, exp)) * - (1 / o.preci)) / (1 / o.preci); }, - commaR = function(s) { return (''+s).replace(/\./, o.decimalSep); }, - ndims = dims.map(function(n) { return commaR(getU(n)); }), - str = ndims.join(o.joinSep) + o.space + o.units[exp]; - - return str; - }, - - formatBytes: function(size) { - return self.formatDims([size], { - units: ['o', 'ko', 'Mo', 'Go', 'To'], - mult: 1024 - }); - }, - - /** - * Choose word given the count - * - * For example : - * number.pluralString(15, ["objet", "objet", "objets"]) - * returns: "objets" - * - * @param {number} count - * @param {Array} dic - */ - pluralString: function(count, dic, useNbsp) { - var str = dic[Math.min(2, count)].replace("${count}", count); - if (useNbsp !== false) { - str = str.replace(" ", " "); - } - - return str; - }, - - formatDuration: function(duration) { - var n = duration % 60; - duration = Math.floor(duration / 60); - var str = n < 10 ? ("0"+n) : n; - - n = duration % 60; - duration = Math.floor(duration / 60); - str = (n < 10 && duration > 0 ? ("0"+n) : n) + ":" + str; - - if (duration > 0) { - str = duration + ":" + str; - } - - return str; - }, - - -}; - - return self; - -}); + var self = { //--noindent-- + + /** + * Format a number + * + * Forwarded to dojo/number/format, but before, the number is + * rounded depending on the "digits" option. + * + * @param {number} value + * @param {Object} options + * @return {string} + * @nosideeffects + */ + format: function(value, options) { + if (options && options.digits) { + var nb = Math.ceil(Math.log(value) / Math.LN10); + var factor = nb < options.digits ? Math.pow(10, options.digits - nb) : 1; + value = Math.round(value * factor) / factor; + } + return dojoNumber.format(value, options); + }, + + + /** + * Format an array of numbers (called "dimensions") + * + * Can typically work on 2D or 3D coordinates, sizes... + * Can also work on simple numbers (call: formatDims([number])) + * + * Examples: + * formatDims([fileWeight], { mult: 1024, + * units: ['B', 'KiB', 'MiB', 'GiB' ]}) + * formatDims([width, height], { units ['m', 'km'] }) + * + * @param {Array.} dims Array of float numbers so that dims.length >= 1 + * @param {Object} options Used to override default options. Options are: + * mult: exp base between units + * units: array + * string array specifying the unit names in powers + * of "options.mult". + * preci: float + * precision for decimal part (ex: 0.1, 0.01, 0.001 ...) + * joinSep: string + * separator for numbers serialization (join) + * + * Specify options.mult for no-SI units (ex: KiB, MiB use 1024) + * @return {string} + * @nosideeffects + */ + formatDims: function(dims, options) { + var o = lang.mixin({ + units: ['', 'K', 'M'], + mult: 1000, + preci: 0.1, + joinSep: ' ; ', + decimalSep: ',', + space: " ", + }, options); + var max = Math.max.apply(null, dims), + logNp = function(x, base) { + return Math.max(0, Math.floor(Math.log(x) / Math.log(base))); + }, + exp = Math.min(logNp(max, o.mult), o.units.length - 1), + getU = function(x) { + return x < 0 ? x : + Math.round((x / Math.pow(o.mult, exp)) * + (1 / o.preci)) / (1 / o.preci); + }, + commaR = function(s) { + return ('' + s).replace(/\./, o.decimalSep); + }, + ndims = dims.map(function(n) { + return commaR(getU(n)); + }), + str = ndims.join(o.joinSep) + o.space + o.units[exp]; + + return str; + }, + + formatBytes: function(size) { + return self.formatDims([size], { + units: ['o', 'ko', 'Mo', 'Go', 'To'], + mult: 1024 + }); + }, + + /** + * Choose word given the count + * + * For example : + * number.pluralString(15, ["objet", "objet", "objets"]) + * returns: "objets" + * + * @param {number} count + * @param {Array} dic + */ + pluralString: function(count, dic, useNbsp) { + var str = dic[Math.min(2, count)].replace("${count}", count); + if (useNbsp !== false) { + str = str.replace(" ", " "); + } + + return str; + }, + + formatDuration: function(duration) { + var n = duration % 60; + duration = Math.floor(duration / 60); + var str = n < 10 ? ("0" + n) : n; + + n = duration % 60; + duration = Math.floor(duration / 60); + str = (n < 10 && duration > 0 ? ("0" + n) : n) + ":" + str; + + if (duration > 0) { + str = duration + ":" + str; + } + + return str; + }, + + + }; + + return self; + +}); \ No newline at end of file diff --git a/util/widget.js b/util/widget.js index e3c61cd..53957bf 100644 --- a/util/widget.js +++ b/util/widget.js @@ -2,119 +2,121 @@ * Utilities about widgets */ define([ - "dojo/_base/lang", - "dojo/_base/kernel", - "dojo/aspect", - "dojo/on", - "dijit/_Contained", - "dijit/registry" + "dojo/_base/lang", + "dojo/_base/kernel", + "dojo/aspect", + "dojo/on", + "dijit/_Contained", + "dijit/registry" ], function(lang, kernel, aspect, on, _Contained, registry) { -var self = { //--noindent-- + var self = { //--noindent-- - getParent: function(w) { - return w.getParent ? w.getParent() : - _Contained.prototype.getParent.call(w); - }, + getParent: function(w) { + return w.getParent ? w.getParent() : + _Contained.prototype.getParent.call(w); + }, - /** - * Return an array of widgets below 'node' which have a 'name' property - * - * Made as a separate function to allow child-classes to use it - * and include widgets outside this' domNode. - * - * @param {DOMElement} node - * @return {Array.} - */ - getFirstNamedDescendants: function(node) { - var widgets = []; - registry.findWidgets(node).forEach( - function(w) { - if (w.name) { - widgets.push(w); - } else { - self.getFirstNamedDescendants(w.domNode).forEach( - function(w2) { widgets.push(w2); }); - } - } - ); - return widgets; - }, + /** + * Return an array of widgets below 'node' which have a 'name' property + * + * Made as a separate function to allow child-classes to use it + * and include widgets outside this' domNode. + * + * @param {DOMElement} node + * @return {Array.} + */ + getFirstNamedDescendants: function(node) { + var widgets = []; + registry.findWidgets(node).forEach( + function(w) { + if (w.name) { + widgets.push(w); + } else { + self.getFirstNamedDescendants(w.domNode).forEach( + function(w2) { + widgets.push(w2); + }); + } + } + ); + return widgets; + }, - bubbleSubmit: function(node, event) { - for (; node && node.parentNode; node = node.parentNode){ - var widget = registry.byNode(node); - if (widget) { - if (widget.stopBubbleSubmit) { - return; - } - if (typeof widget._onSubmit == "function") { - widget._onSubmit(event); - break; - } - } - } - }, + bubbleSubmit: function(node, event) { + for (; node && node.parentNode; node = node.parentNode) { + var widget = registry.byNode(node); + if (widget) { + if (widget.stopBubbleSubmit) { + return; + } + if (typeof widget._onSubmit == "function") { + widget._onSubmit(event); + break; + } + } + } + }, - /** - * Makes a single-time dojo/connect - OBSOLETE - * - * OBSOLETE: since dojo 1.7, this function has been updated to - * use dojo/aspect/after (upgrade of dojo/connect) or - * dojo/on, if 'obj' has an 'addEventListener' method. - * - * This works the same as with dojo/connect, but for once only: - * the handler is automatically disconnected the first time - * the method is called. - * - * However, the connection can be canceled before the call if needed, - * simply by calling dojo/disconnect. - * - * @param {!Object} obj Source object for event function - * @param {string} event Name of event function in obj - * @param {Object} context Object to bind to the method as "this" - * @param {function()|string} method Function or method name of context - * @return {Object} Handler for use with dojo/disconnect. - */ - connectOnce: function(obj, event, context, method) { - kernel.deprecated("geonef/jig/util/widget.connectOnce()", - "use aspect.after() directly"); - var _h; - var callback = lang.hitch(context, function() { - _h.remove(); - // dojo/disconnect(_h); - method.apply(context, arguments); - }); - if (obj.addEventListener) { - if (/^on/.test(event)) { - event = event.substr(2); - } else { - console.warn("widget.connectOnce: obj has an addEventListener method " + - "but event does not start with 'on'", event, obj); - } - _h = on(obj, event, callback); - } else { - _h = aspect.after(obj, event, callback); - } - return _h; - }, + /** + * Makes a single-time dojo/connect - OBSOLETE + * + * OBSOLETE: since dojo 1.7, this function has been updated to + * use dojo/aspect/after (upgrade of dojo/connect) or + * dojo/on, if 'obj' has an 'addEventListener' method. + * + * This works the same as with dojo/connect, but for once only: + * the handler is automatically disconnected the first time + * the method is called. + * + * However, the connection can be canceled before the call if needed, + * simply by calling dojo/disconnect. + * + * @param {!Object} obj Source object for event function + * @param {string} event Name of event function in obj + * @param {Object} context Object to bind to the method as "this" + * @param {function()|string} method Function or method name of context + * @return {Object} Handler for use with dojo/disconnect. + */ + connectOnce: function(obj, event, context, method) { + kernel.deprecated("geonef/jig/util/widget.connectOnce()", + "use aspect.after() directly"); + var _h; + var callback = lang.hitch(context, function() { + _h.remove(); + // dojo/disconnect(_h); + method.apply(context, arguments); + }); + if (obj.addEventListener) { + if (/^on/.test(event)) { + event = event.substr(2); + } else { + console.warn("widget.connectOnce: obj has an addEventListener method " + + "but event does not start with 'on'", event, obj); + } + _h = on(obj, event, callback); + } else { + _h = aspect.after(obj, event, callback); + } + return _h; + }, - /** - * Focus on the given widget - * - * @param {dijit/_Widget} widget - * @return {object} - */ - focus: function(widget) { - var parent = registry.getEnclosingWidget(widget.domNode.parentNode); - if (parent && parent.selectChild) { - parent.selectChild(widget); - } - return widget; - }, + /** + * Focus on the given widget + * + * @param {dijit/_Widget} widget + * @return {object} + */ + focus: function(widget) { + var parent = registry.getEnclosingWidget(widget.domNode.parentNode); + if (parent && parent.selectChild) { + parent.selectChild(widget); + } + return widget; + } -}; + }; - return self; + return self; -}); +}); \ No newline at end of file