xblox - port 1/3
This commit is contained in:
parent
0fa17ead0c
commit
444f78ceb7
37
packages/xblox/ref-control-freak/xblox-ts/.gitignore
vendored
Normal file
37
packages/xblox/ref-control-freak/xblox-ts/.gitignore
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules
|
||||
jspm_packages
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
29
packages/xblox/ref-control-freak/xblox-ts/LICENSE
Normal file
29
packages/xblox/ref-control-freak/xblox-ts/LICENSE
Normal file
@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2017,
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
2
packages/xblox/ref-control-freak/xblox-ts/README.md
Normal file
2
packages/xblox/ref-control-freak/xblox-ts/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# xblox
|
||||
xblox-core
|
||||
44
packages/xblox/ref-control-freak/xblox-ts/package.json
Normal file
44
packages/xblox/ref-control-freak/xblox-ts/package.json
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "@xblox/xblox",
|
||||
"version": "0.0.1",
|
||||
"license": "BSD",
|
||||
"licenses": [
|
||||
{
|
||||
"type": "BSD",
|
||||
"url": "https://github.com/xblox/xblox/blob/master/LICENSE"
|
||||
}
|
||||
],
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Günter Baumgart",
|
||||
"url": "http://github.com/xblox"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/xblox/xblox.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"js-data": "^2.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"dojo-typings": "^1.11.6",
|
||||
"nodemon": "^1.11.0",
|
||||
"ts-node": "^1.7.3",
|
||||
"tsconfig-paths": "^2.1.1",
|
||||
"tslint": "^4.3.1",
|
||||
"typescript": "^2.2.1"
|
||||
},
|
||||
"optionalDependencies": {},
|
||||
"main": "index",
|
||||
"scripts": {
|
||||
"test": "tsc && mocha build/test",
|
||||
"build": "tsc",
|
||||
"start": "node build/index.js",
|
||||
"dev": "nodemon -w src -x ts-node -r ./tsconfig-paths/register src/index.ts",
|
||||
"lint": "tslint --project=./tsconfig.json",
|
||||
"install": "git-module init-modules"
|
||||
},
|
||||
"modules": [],
|
||||
"readmeFilename": "Readme.md"
|
||||
}
|
||||
291
packages/xblox/ref-control-freak/xblox-ts/src/enums.ts
Normal file
291
packages/xblox/ref-control-freak/xblox-ts/src/enums.ts
Normal file
@ -0,0 +1,291 @@
|
||||
|
||||
|
||||
/**
|
||||
* The block's capabilities. This will be evaluated in the interface but also
|
||||
* by the run-time (speed ups).
|
||||
*
|
||||
*/
|
||||
export enum BLOCK_CAPABILITIES {
|
||||
/**
|
||||
* No other block includes this one.
|
||||
* @constant
|
||||
* @type int
|
||||
*/
|
||||
TOPMOST = 0x00004000,
|
||||
/**
|
||||
* The block's execution context can be changed to another object.
|
||||
* @constant
|
||||
* @type int
|
||||
*/
|
||||
TARGET = 0x00040000,
|
||||
/**
|
||||
* The block may create additional input terminals ('reset', 'pause', ...).
|
||||
* @constant
|
||||
* @type int
|
||||
*/
|
||||
VARIABLE_INPUTS = 0x00000080,
|
||||
/**
|
||||
* The block may create additional output terminals ('onFinish', 'onError').
|
||||
* @constant
|
||||
* @type int
|
||||
*/
|
||||
VARIABLE_OUTPUTS = 0x00000100,
|
||||
/**
|
||||
* The block may create additional ouput parameters ('result', 'error',...).
|
||||
* @constant
|
||||
* @type int
|
||||
*/
|
||||
VARIABLE_OUTPUT_PARAMETERS = 0x00000200,
|
||||
/**
|
||||
* The block may create additional input parameters.
|
||||
* @constant
|
||||
* @type int
|
||||
*/
|
||||
VARIABLE_INPUT_PARAMETERS = 0x00000400,
|
||||
/**
|
||||
* The block can contain child blocks.
|
||||
* @constant
|
||||
* @type int
|
||||
*/
|
||||
CHILDREN = 0x00000020,
|
||||
/**
|
||||
* Block provides standard signals ('paused', 'error').
|
||||
* @constant
|
||||
* @type int
|
||||
*/
|
||||
SIGNALS = 0x00000080
|
||||
}
|
||||
/**
|
||||
* Flags to describe a block's execution behavior.
|
||||
*
|
||||
* @enum {integer} module=xide/types/RUN_FLAGS
|
||||
* @memberOf module=xide/types
|
||||
*/
|
||||
export enum RUN_FLAGS {
|
||||
/**
|
||||
* The block can execute child blocks.
|
||||
* @constant
|
||||
* @type int
|
||||
*/
|
||||
CHILDREN = 0x00000020,
|
||||
/**
|
||||
* Block is waiting for a message => EXECUTION_STATE==RUNNING
|
||||
* @constant
|
||||
* @type int
|
||||
*/
|
||||
WAIT = 0x000008000
|
||||
};
|
||||
|
||||
/**
|
||||
* Flags to describe a block's execution state.
|
||||
*
|
||||
* @enum {integer} module=xide/types/EXECUTION_STATE
|
||||
* @memberOf module=xide/types
|
||||
*/
|
||||
export enum EXECUTION_STATE {
|
||||
/**
|
||||
* The block is doing nothing and also has done nothing. The is the default state
|
||||
* @constant
|
||||
* @type int
|
||||
*/
|
||||
NONE = 0x00000000,
|
||||
/**
|
||||
* The block is running.
|
||||
* @constant
|
||||
* @type int
|
||||
*/
|
||||
RUNNING = 0x00000001,
|
||||
/**
|
||||
* The block is an error state.
|
||||
* @constant
|
||||
* @type int
|
||||
*/
|
||||
ERROR = 0x00000002,
|
||||
/**
|
||||
* The block is in an paused state.
|
||||
* @constant
|
||||
* @type int
|
||||
*/
|
||||
PAUSED = 0x00000004,
|
||||
/**
|
||||
* The block is an finished state, ready to be cleared to "NONE" at the next frame.
|
||||
* @constant
|
||||
* @type int
|
||||
*/
|
||||
FINISH = 0x00000008,
|
||||
/**
|
||||
* The block is an stopped state, ready to be cleared to "NONE" at the next frame.
|
||||
* @constant
|
||||
* @type int
|
||||
*/
|
||||
STOPPED = 0x00000010,
|
||||
/**
|
||||
* The block has been launched once...
|
||||
* @constant
|
||||
* @type int
|
||||
*/
|
||||
ONCE = 0x80000000,
|
||||
/**
|
||||
* Block will be reseted next frame
|
||||
* @constant
|
||||
* @type int
|
||||
*/
|
||||
RESET_NEXT_FRAME = 0x00800000,
|
||||
/**
|
||||
* Block is locked and so no further inputs can be activated.
|
||||
* @constant
|
||||
* @type int
|
||||
*/
|
||||
LOCKED = 0x20000000 // Block is locked for utilisation in xblox
|
||||
}
|
||||
|
||||
export enum BLOCK_MODE {
|
||||
NORMAL = 0,
|
||||
UPDATE_WIDGET_PROPERTY = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* Flags to describe a block's belonging to a standard signal.
|
||||
* @enum {integer} module=xblox/types/BLOCK_OUTLET
|
||||
* @memberOf module=xblox/types
|
||||
*/
|
||||
export enum BLOCK_OUTLET {
|
||||
NONE = 0x00000000,
|
||||
PROGRESS = 0x00000001,
|
||||
ERROR = 0x00000002,
|
||||
PAUSED = 0x00000004,
|
||||
FINISH = 0x00000008,
|
||||
STOPPED = 0x00000010
|
||||
};
|
||||
/**
|
||||
* Flags to describe flags of the inner state of a block which might change upon the optimization. It also
|
||||
* contains some other settings which might be static, default or changed by the UI(debugger, etc...)
|
||||
*
|
||||
* @enum {integer} module:xide/types/BLOCK_FLAGS
|
||||
* @memberOf module:xide/types
|
||||
*/
|
||||
export enum BLOCK_FLAGS {
|
||||
NONE = 0x00000000, // Reserved for future use
|
||||
ACTIVE = 0x00000001, // This behavior is active
|
||||
SCRIPT = 0x00000002, // This behavior is a script
|
||||
RESERVED1 = 0x00000004, // Reserved for internal use
|
||||
USEFUNCTION = 0x00000008, // Block uses a function and not a graph
|
||||
RESERVED2 = 0x00000010, // Reserved for internal use
|
||||
SINGLE = 0x00000020, // Only this block will excecuted, child blocks not.
|
||||
WAITSFORMESSAGE = 0x00000040, // Block is waiting for a message to activate one of its outputs
|
||||
VARIABLEINPUTS = 0x00000080, // Block may have its inputs changed by editing them
|
||||
VARIABLEOUTPUTS = 0x00000100, // Block may have its outputs changed by editing them
|
||||
VARIABLEPARAMETERINPUTS = 0x00000200, // Block may have its number of input parameters changed by editing them
|
||||
VARIABLEPARAMETEROUTPUTS = 0x00000400, // Block may have its number of output parameters changed by editing them
|
||||
TOPMOST = 0x00004000, // No other Block includes this one
|
||||
BUILDINGBLOCK = 0x00008000, // This Block is a building block (eg= not a transformer of parameter operation)
|
||||
MESSAGESENDER = 0x00010000, // Block may send messages during its execution
|
||||
MESSAGERECEIVER = 0x00020000, // Block may check messages during its execution
|
||||
TARGETABLE = 0x00040000, // Block may be owned by a different object that the one to which its execution will apply
|
||||
CUSTOMEDITDIALOG = 0x00080000, // This Block have a custom Dialog Box for parameters edition .
|
||||
RESERVED0 = 0x00100000, // Reserved for internal use.
|
||||
EXECUTEDLASTFRAME = 0x00200000, // This behavior has been executed during last process. (Available only in profile mode )
|
||||
DEACTIVATENEXTFRAME = 0x00400000, // Block will be deactivated next frame
|
||||
RESETNEXTFRAME = 0x00800000, // Block will be reseted next frame
|
||||
|
||||
INTERNALLYCREATEDINPUTS = 0x01000000, // Block execution may create/delete inputs
|
||||
INTERNALLYCREATEDOUTPUTS = 0x02000000, // Block execution may create/delete outputs
|
||||
INTERNALLYCREATEDINPUTPARAMS = 0x04000000, // Block execution may create/delete input parameters or change their type
|
||||
INTERNALLYCREATEDOUTPUTPARAMS = 0x08000000, // Block execution may create/delete output parameters or change their type
|
||||
INTERNALLYCREATEDLOCALPARAMS = 0x40000000, // Block execution may create/delete local parameters or change their type
|
||||
|
||||
ACTIVATENEXTFRAME = 0x10000000, // Block will be activated next frame
|
||||
LOCKED = 0x20000000, // Block is locked for utilisation in xblox
|
||||
LAUNCHEDONCE = 0x80000000 // Block has not yet been launched...
|
||||
}
|
||||
/**
|
||||
* Mask for the messages the callback function of a block should be aware of. This goes directly in
|
||||
* the EventedMixin as part of the 'emits' chain (@TODO)
|
||||
*
|
||||
* @enum module:xide/types/BLOCK_CALLBACKMASK
|
||||
* @memberOf module:xide/types
|
||||
*/
|
||||
export enum BLOCK_CALLBACKMASK {
|
||||
PRESAVE = 0x00000001, // Emits PRESAVE messages
|
||||
DELETE = 0x00000002, // Emits DELETE messages
|
||||
ATTACH = 0x00000004, // Emits ATTACH messages
|
||||
DETACH = 0x00000008, // Emits DETACH messages
|
||||
PAUSE = 0x00000010, // Emits PAUSE messages
|
||||
RESUME = 0x00000020, // Emits RESUME messages
|
||||
CREATE = 0x00000040, // Emits CREATE messages
|
||||
RESET = 0x00001000, // Emits RESET messages
|
||||
POSTSAVE = 0x00000100, // Emits POSTSAVE messages
|
||||
LOAD = 0x00000200, // Emits LOAD messages
|
||||
EDITED = 0x00000400, // Emits EDITED messages
|
||||
SETTINGSEDITED = 0x00000800, // Emits SETTINGSEDITED messages
|
||||
READSTATE = 0x00001000, // Emits READSTATE messages
|
||||
NEWSCENE = 0x00002000, // Emits NEWSCENE messages
|
||||
ACTIVATESCRIPT = 0x00004000, // Emits ACTIVATESCRIPT messages
|
||||
DEACTIVATESCRIPT = 0x00008000, // Emits DEACTIVATESCRIPT messages
|
||||
RESETINBREAKPOINT = 0x00010000, // Emits RESETINBREAKPOINT messages
|
||||
RENAME = 0x00020000, // Emits RENAME messages
|
||||
BASE = 0x0000000E, // Base flags =attach /detach /delete
|
||||
SAVELOAD = 0x00000301, // Base flags for load and save
|
||||
PPR = 0x00000130, // Base flags for play/pause/reset
|
||||
EDITIONS = 0x00000C00, // Base flags for editions of settings or parameters
|
||||
ALL = 0xFFFFFFFF // All flags
|
||||
}
|
||||
|
||||
export enum EVENTS {
|
||||
ON_RUN_BLOCK = <any>'onRunBlock',
|
||||
ON_RUN_BLOCK_FAILED = <any>'onRunBlockFailed',
|
||||
ON_RUN_BLOCK_SUCCESS = <any>'onRunBlockSuccess',
|
||||
ON_BLOCK_SELECTED = <any>'onItemSelected',
|
||||
ON_BLOCK_UNSELECTED = <any>'onBlockUnSelected',
|
||||
ON_BLOCK_EXPRESSION_FAILED = <any>'onExpressionFailed',
|
||||
ON_BUILD_BLOCK_INFO_LIST = <any>'onBuildBlockInfoList',
|
||||
ON_BUILD_BLOCK_INFO_LIST_END = <any>'onBuildBlockInfoListEnd',
|
||||
ON_BLOCK_PROPERTY_CHANGED = <any>'onBlockPropertyChanged',
|
||||
ON_SCOPE_CREATED = <any>'onScopeCreated',
|
||||
ON_VARIABLE_CHANGED = <any>'onVariableChanged',
|
||||
ON_CREATE_VARIABLE_CI = <any>'onCreateVariableCI'
|
||||
}
|
||||
|
||||
|
||||
export enum Type {
|
||||
AssignmentExpression = <any>'AssignmentExpression',
|
||||
ArrayExpression = <any>'ArrayExpression',
|
||||
BlockStatement = <any>'BlockStatement',
|
||||
BinaryExpression = <any>'BinaryExpression',
|
||||
BreakStatement = <any>'BreakStatement',
|
||||
CallExpression = <any>'CallExpression',
|
||||
CatchClause = <any>'CatchClause',
|
||||
ConditionalExpression = <any>'ConditionalExpression',
|
||||
ContinueStatement = <any>'ContinueStatement',
|
||||
DoWhileStatement = <any>'DoWhileStatement',
|
||||
DebuggerStatement = <any>'DebuggerStatement',
|
||||
EmptyStatement = <any>'EmptyStatement',
|
||||
ExpressionStatement = <any>'ExpressionStatement',
|
||||
ForStatement = <any>'ForStatement',
|
||||
ForInStatement = <any>'ForInStatement',
|
||||
FunctionDeclaration = <any>'FunctionDeclaration',
|
||||
FunctionExpression = <any>'FunctionExpression',
|
||||
Identifier = <any>'Identifier',
|
||||
IfStatement = <any>'IfStatement',
|
||||
Literal = <any>'Literal',
|
||||
LabeledStatement = <any>'LabeledStatement',
|
||||
LogicalExpression = <any>'LogicalExpression',
|
||||
MemberExpression = <any>'MemberExpression',
|
||||
NewExpression = <any>'NewExpression',
|
||||
ObjectExpression = <any>'ObjectExpression',
|
||||
Program = <any>'Program',
|
||||
Property = <any>'Property',
|
||||
ReturnStatement = <any>'ReturnStatement',
|
||||
SequenceExpression = <any>'SequenceExpression',
|
||||
SwitchStatement = <any>'SwitchStatement',
|
||||
SwitchCase = <any>'SwitchCase',
|
||||
ThisExpression = <any>'ThisExpression',
|
||||
ThrowStatement = <any>'ThrowStatement',
|
||||
TryStatement = <any>'TryStatement',
|
||||
UnaryExpression = <any>'UnaryExpression',
|
||||
UpdateExpression = <any>'UpdateExpression',
|
||||
VariableDeclaration = <any>'VariableDeclaration',
|
||||
VariableDeclarator = <any>'VariableDeclarator',
|
||||
WhileStatement = <any>'WhileStatement',
|
||||
WithStatement = <any>'WithStatement'
|
||||
};
|
||||
35
packages/xblox/ref-control-freak/xblox-ts/tsconfig.json
Normal file
35
packages/xblox/ref-control-freak/xblox-ts/tsconfig.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"allowJs": false,
|
||||
"noImplicitAny": false,
|
||||
"sourceMap": true,
|
||||
"outDir": "./build/node",
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"pretty": true,
|
||||
"baseUrl": "./src/",
|
||||
"rootDir": "../",
|
||||
"paths": {
|
||||
"@xblox/core/*": [
|
||||
"../../core-ts/src/*",
|
||||
"../../../core-ts/src/*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"compileOnSave": false,
|
||||
"filesGlob": [
|
||||
"./src/**/*.ts"
|
||||
],
|
||||
"exclude": [],
|
||||
"atom": {
|
||||
"rewriteTsconfig": true
|
||||
},
|
||||
"files": [
|
||||
"./src/index.ts",
|
||||
"./src/enums.ts",
|
||||
"./src/model/Block.ts",
|
||||
"./typings/index.d.ts"
|
||||
]
|
||||
}
|
||||
0
packages/xblox/ref-control-freak/xblox/.gitmodules
vendored
Normal file
0
packages/xblox/ref-control-freak/xblox/.gitmodules
vendored
Normal file
1707
packages/xblox/ref-control-freak/xblox/BlockActions.js
Normal file
1707
packages/xblox/ref-control-freak/xblox/BlockActions.js
Normal file
File diff suppressed because it is too large
Load Diff
140
packages/xblox/ref-control-freak/xblox/CSSState.js
Normal file
140
packages/xblox/ref-control-freak/xblox/CSSState.js
Normal file
@ -0,0 +1,140 @@
|
||||
define([
|
||||
"dcl/dcl",
|
||||
"delite/register",
|
||||
"delite/CustomElement",
|
||||
'xblox/_State',
|
||||
'xide/utils',
|
||||
'xdojo/has'
|
||||
], function (dcl, register, CustomElement, _State, utils, has) {
|
||||
var extraRules = [],
|
||||
extraSheet,
|
||||
removeMethod,
|
||||
rulesProperty,
|
||||
invalidCssChars = /([^A-Za-z0-9_\u00A0-\uFFFF-])/g;
|
||||
|
||||
has.add('dom-contains', function (global, doc, element) {
|
||||
return !!element.contains; // not supported by FF < 9
|
||||
});
|
||||
|
||||
function removeRule(index) {
|
||||
// Function called by the remove method on objects returned by addCssRule.
|
||||
var realIndex = extraRules[index],
|
||||
i, l;
|
||||
if (realIndex === undefined) {
|
||||
return; // already removed
|
||||
}
|
||||
|
||||
// remove rule indicated in internal array at index
|
||||
extraSheet[removeMethod](realIndex);
|
||||
|
||||
// Clear internal array item representing rule that was just deleted.
|
||||
// NOTE: we do NOT splice, since the point of this array is specifically
|
||||
// to negotiate the splicing that occurs in the stylesheet itself!
|
||||
extraRules[index] = undefined;
|
||||
|
||||
// Then update array items as necessary to downshift remaining rule indices.
|
||||
// Can start at index + 1, since array is sparse but strictly increasing.
|
||||
for (i = index + 1, l = extraRules.length; i < l; i++) {
|
||||
if (extraRules[i] > realIndex) {
|
||||
extraRules[i]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
var Impl = {
|
||||
_lastState: null,
|
||||
declaredClass: 'xblox/CSSState',
|
||||
cssClass: "",
|
||||
addCssRule: function (selector, css) {
|
||||
// summary:
|
||||
// Dynamically adds a style rule to the document. Returns an object
|
||||
// with a remove method which can be called to later remove the rule.
|
||||
|
||||
if (!extraSheet) {
|
||||
// First time, create an extra stylesheet for adding rules
|
||||
extraSheet = document.createElement('style');
|
||||
document.getElementsByTagName('head')[0].appendChild(extraSheet);
|
||||
// Keep reference to actual StyleSheet object (`styleSheet` for IE < 9)
|
||||
extraSheet = extraSheet.sheet || extraSheet.styleSheet;
|
||||
// Store name of method used to remove rules (`removeRule` for IE < 9)
|
||||
removeMethod = extraSheet.deleteRule ? 'deleteRule' : 'removeRule';
|
||||
// Store name of property used to access rules (`rules` for IE < 9)
|
||||
rulesProperty = extraSheet.cssRules ? 'cssRules' : 'rules';
|
||||
}
|
||||
|
||||
var index = extraRules.length;
|
||||
extraRules[index] = (extraSheet.cssRules || extraSheet.rules).length;
|
||||
extraSheet.addRule ?
|
||||
extraSheet.addRule(selector, css) :
|
||||
extraSheet.insertRule(selector + '{' + css + '}', extraRules[index]);
|
||||
return {
|
||||
get: function (prop) {
|
||||
return extraSheet[rulesProperty][extraRules[index]].style[prop];
|
||||
},
|
||||
set: function (prop, value) {
|
||||
if (typeof extraRules[index] !== 'undefined') {
|
||||
extraSheet[rulesProperty][extraRules[index]].style[prop] = value;
|
||||
}
|
||||
},
|
||||
remove: function () {
|
||||
removeRule(index);
|
||||
},
|
||||
sheet: extraSheet
|
||||
};
|
||||
},
|
||||
escapeCssIdentifier: function (id, replace) {
|
||||
return typeof id === 'string' ? id.replace(invalidCssChars, replace || '\\$1') : id;
|
||||
},
|
||||
detachedCallback: function () {
|
||||
this._styles && _.each(this._styles, function (style) {
|
||||
style.remove();
|
||||
});
|
||||
delete this._styles;
|
||||
},
|
||||
applyTo: function (widget, name) {
|
||||
if (this._lastState) {
|
||||
this._lastState.remove();
|
||||
}
|
||||
delete this._lastStateName;
|
||||
this._lastStateName = name;
|
||||
if (!this._attached) {
|
||||
return;
|
||||
}
|
||||
var cssClass = this.cssClass;
|
||||
var isCSSClass = cssClass.length > 0;
|
||||
var id = widget.id || utils.createUUID();
|
||||
var _uniqueId = widget.tagName.replace(/\./g, "_") + '_' + id;
|
||||
var css = '' + this.innerHTML;
|
||||
css = css.replace('.style', '');
|
||||
css = css.replace(/<(?:.|\n)*?>/gm, '');
|
||||
css = css.replace('{', '');
|
||||
css = css.replace('}', '');
|
||||
css = css.replace(/(\r\n|\n|\r|\t)/gm, "");
|
||||
|
||||
_uniqueId += '_state_' + name;
|
||||
|
||||
$(widget).removeClass($(widget).data('_lastCSSState'));
|
||||
$(widget).removeClass($(widget).data('_lastCSSClass'));
|
||||
$(widget).removeClass(cssClass);
|
||||
|
||||
if (!cssClass) {
|
||||
$(widget).addClass(_uniqueId);
|
||||
$(widget).data('_lastCSSState', _uniqueId);
|
||||
var selectorPrefix = '.' + this.escapeCssIdentifier(_uniqueId);
|
||||
if (!this._styles) {
|
||||
this._styles = [];
|
||||
}
|
||||
var style = this.addCssRule(selectorPrefix, css);
|
||||
this._styles.push(style);
|
||||
} else {
|
||||
$(widget).addClass(cssClass);
|
||||
$(widget).data('_lastCSSClass', cssClass);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var _class = dcl([_State], Impl);
|
||||
//static access to Impl.
|
||||
_class.Impl = Impl;
|
||||
return register("d-xstate-css", [HTMLElement, CustomElement, _class]);
|
||||
});
|
||||
189
packages/xblox/ref-control-freak/xblox/Gruntfile.js
Normal file
189
packages/xblox/ref-control-freak/xblox/Gruntfile.js
Normal file
@ -0,0 +1,189 @@
|
||||
/*global module */
|
||||
module.exports = function (grunt) {
|
||||
|
||||
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON("package.json"),
|
||||
jshint: {
|
||||
src: [
|
||||
"**/*.js",
|
||||
"!./app.profile.js",
|
||||
"!{node_modules}/**/*.js"
|
||||
],
|
||||
options: {
|
||||
jshintrc: ".jshintrc"
|
||||
}
|
||||
},
|
||||
|
||||
// Task for compiling less files into CSS files
|
||||
less : {
|
||||
// Compile theme independent files
|
||||
transitions: {
|
||||
expand: true,
|
||||
cwd: "themes/common/transitions",
|
||||
src: ["*.less"],
|
||||
dest: "themes/common/transitions",
|
||||
ext: ".css"
|
||||
},
|
||||
|
||||
// Infrastructure per-theme files
|
||||
common : {
|
||||
files: [
|
||||
{
|
||||
expand: true,
|
||||
src: ["themes/*/*.less", "!themes/common/*.less", "!**/variables.less", "!**/common.less"],
|
||||
ext: ".css"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
// Compile less code for each widget
|
||||
widgets : {
|
||||
files: [
|
||||
{
|
||||
expand: true,
|
||||
src: [
|
||||
"*/themes/*/*.less",
|
||||
"samples/ExampleWidget/themes/*/*.less",
|
||||
"!{dijit,mobile}/themes/*/*.less"
|
||||
],
|
||||
ext: ".css"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
// convert CSS files to JS files
|
||||
cssToJs : {
|
||||
// conversions removing the CSS files
|
||||
replace: {
|
||||
src: [
|
||||
// infrastructure
|
||||
"themes/*/*.css",
|
||||
"!themes/common/*.css",
|
||||
"themes/common/transitions/*.css",
|
||||
|
||||
// widgets
|
||||
"*/themes/*/*.css",
|
||||
"samples/ExampleWidget/themes/*/*.css",
|
||||
"!{dijit,mobile}/themes/*/*.css"
|
||||
],
|
||||
options: {
|
||||
remove: true
|
||||
}
|
||||
},
|
||||
|
||||
// conversions keeping the CSS files
|
||||
keep: {
|
||||
src: [
|
||||
// some apps may want to load defaultapp.css as a JS file rather than a CSS file.
|
||||
"themes/defaultapp.css",
|
||||
|
||||
// files originally authored as CSS
|
||||
"tests/unit/css/*.css"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
intern: {
|
||||
local: {
|
||||
options: {
|
||||
runType: 'runner',
|
||||
config: 'test/intern/intern.local'
|
||||
}
|
||||
},
|
||||
remote: {
|
||||
options: {
|
||||
runType: 'runner',
|
||||
config: 'test/intern/intern'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"jsdoc-amddcl": {
|
||||
"plugins": [
|
||||
"plugins/markdown"
|
||||
],
|
||||
docs: {
|
||||
files: [
|
||||
{
|
||||
src: [
|
||||
"./views/Grid.js",
|
||||
"xblox/views/BlockGrid.js",
|
||||
"./BlockActions.js",
|
||||
"../xide/types/Types.js",
|
||||
"./types/Types.js",
|
||||
"!./node_modules"
|
||||
]
|
||||
|
||||
}
|
||||
]
|
||||
},
|
||||
'export': {
|
||||
files: [
|
||||
{
|
||||
args: [
|
||||
"-X"
|
||||
],
|
||||
src: [
|
||||
".",
|
||||
"../xide/types/Types.js",
|
||||
"./README.md",
|
||||
"./package.json"
|
||||
],
|
||||
dest: "/tmp/doclets.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Load plugins
|
||||
grunt.loadNpmTasks("intern");
|
||||
grunt.loadNpmTasks("grunt-contrib-jshint");
|
||||
grunt.loadNpmTasks("grunt-contrib-less");
|
||||
grunt.loadNpmTasks("grunt-contrib-uglify");
|
||||
grunt.loadNpmTasks("jsdoc-amddcl");
|
||||
grunt.loadNpmTasks('intern-geezer');
|
||||
|
||||
// Aliases
|
||||
//grunt.registerTask("css", ["less", "cssToJs"]);
|
||||
grunt.registerTask("jsdoc", "jsdoc-amddcl");
|
||||
|
||||
// Testing.
|
||||
// Always specify the target e.g. grunt test:remote, grunt test:remote
|
||||
// then add on any other flags afterwards e.g. console, lcovhtml.
|
||||
var testTaskDescription = "Run this task instead of the intern task directly! \n" +
|
||||
"Always specify the test target e.g. \n" +
|
||||
"grunt test:local\n" +
|
||||
"grunt test:remote\n\n" +
|
||||
"Add any optional reporters via a flag e.g. \n" +
|
||||
"grunt test:local:console\n" +
|
||||
"grunt test:local:lcovhtml\n" +
|
||||
"grunt test:local:console:lcovhtml";
|
||||
|
||||
/*
|
||||
grunt.registerTask("test", testTaskDescription, function (target) {
|
||||
function addReporter(reporter) {
|
||||
var property = "intern." + target + ".options.reporters",
|
||||
value = grunt.config.get(property);
|
||||
if (value.indexOf(reporter) !== -1) {
|
||||
return;
|
||||
}
|
||||
value.push(reporter);
|
||||
grunt.config.set(property, value);
|
||||
}
|
||||
|
||||
if (this.flags.lcovhtml) {
|
||||
addReporter("lcovhtml");
|
||||
}
|
||||
|
||||
if (this.flags.console) {
|
||||
addReporter("console");
|
||||
}
|
||||
grunt.task.run("intern:" + target);
|
||||
});*/
|
||||
|
||||
grunt.registerTask('test', [ 'intern:local' ]);
|
||||
};
|
||||
0
packages/xblox/ref-control-freak/xblox/Readme.md
Normal file
0
packages/xblox/ref-control-freak/xblox/Readme.md
Normal file
564
packages/xblox/ref-control-freak/xblox/RunScript.js
Normal file
564
packages/xblox/ref-control-freak/xblox/RunScript.js
Normal file
@ -0,0 +1,564 @@
|
||||
define([
|
||||
"dojo/_base/lang",
|
||||
"dojo/on",
|
||||
"dcl/dcl",//make sure
|
||||
"delite/register",
|
||||
"delite/CustomElement",
|
||||
//explicit because a bootstrap might not be loaded at some point
|
||||
"xide/factory/Events",
|
||||
//explicit because a bootstrap might not be loaded at some point
|
||||
'xide/utils/StringUtils',
|
||||
'xide/types/Types',
|
||||
'xblox/model/Referenced',
|
||||
'xide/mixins/EventedMixin',
|
||||
'xide/mixins/ReloadMixin',
|
||||
/** 2way binding dependencies **/
|
||||
'xwire/Binding',
|
||||
'xwire/EventSource',
|
||||
'xwire/WidgetTarget'
|
||||
|
||||
], function (lang, on, dcl, register, CustomElement, Events, utils, Types, Referenced, EventedMixin, ReloadMixin, Binding, EventSource, WidgetTarget, registry) {
|
||||
|
||||
var debugWidgets = false;
|
||||
var debugApp = false;
|
||||
var debugAttach = false;
|
||||
var debugCreated = false;
|
||||
var debugBinding = false;
|
||||
var debugRun = false;
|
||||
/**
|
||||
* Proxy widget to run a selected blox script on the parent widget/node.
|
||||
*
|
||||
* @class xblox/RunScript
|
||||
*/
|
||||
var Impl = {
|
||||
declaredClass: 'xblox/RunScript',
|
||||
targetevent: '',
|
||||
sourceevent: "",
|
||||
sourceeventvaluepath: "",
|
||||
sourceeventnamepath: "",
|
||||
targetproperty: "",
|
||||
targetvariable: "",
|
||||
targetfilter: "",
|
||||
script: "",
|
||||
bidirectional: false,
|
||||
blockGroup: '',
|
||||
block: '',
|
||||
_targetBlock: null,
|
||||
_targetReference: null,
|
||||
_appContext: null,
|
||||
_complete: false,
|
||||
enabled: true,
|
||||
stop: false,
|
||||
_events: [],
|
||||
context: null,
|
||||
accept: '',
|
||||
transform: '',
|
||||
mode: 0,
|
||||
_2wayHandle: null,//the handle
|
||||
binding: null,//the binding
|
||||
/**
|
||||
* soft destroy
|
||||
*/
|
||||
reset: function () {
|
||||
this._destroyHandles();
|
||||
if (this._2wayHandle) {
|
||||
this._2wayHandle.remove();
|
||||
}
|
||||
if (this.binding) {
|
||||
this.binding.destroy();
|
||||
}
|
||||
delete this.binding;
|
||||
this._appContext = null;
|
||||
this._targetReference = null;
|
||||
this._targetBlock = null;
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param newSettings
|
||||
*/
|
||||
onSettingsChanged: function () {
|
||||
this.reset();
|
||||
if (!this.enabled) {
|
||||
return;
|
||||
}
|
||||
this.onAppReady(null);
|
||||
},
|
||||
getChildren: function () {
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
destroy: function () {
|
||||
this.onDestroy && this.onDestroy();
|
||||
this.reset();
|
||||
delete this.binding;
|
||||
delete this.context;
|
||||
},
|
||||
/**
|
||||
* The final execution when 'target event' has been triggered. This
|
||||
* will run the select block.
|
||||
* @param event
|
||||
* @param val
|
||||
*/
|
||||
run: function (event, val) {
|
||||
if (!this.enabled) {
|
||||
return;
|
||||
}
|
||||
var settings = {};
|
||||
//filter, in design mode, we ain't do anything
|
||||
if (this.context && this.context.delegate) {
|
||||
if (this.context.delegate.isDesignMode && this.context.delegate.isDesignMode()) {
|
||||
return;
|
||||
}
|
||||
if (this.context.delegate.getBlockSettings) {
|
||||
settings = this.context.delegate.getBlockSettings();
|
||||
}
|
||||
}
|
||||
//setup variables
|
||||
var block = this._targetBlock,
|
||||
context = this._targetReference,
|
||||
result;
|
||||
|
||||
if (block && context) {
|
||||
block.context = context;
|
||||
block._targetReference = context;
|
||||
if (this.targetvariable && this.targetvariable.length && val != null) {
|
||||
block.override = {
|
||||
variables: {}
|
||||
};
|
||||
block.override.variables[this.targetvariable] = val;
|
||||
}
|
||||
result = block.solve(block.scope, settings);
|
||||
debugRun && console.log('run ' + block.name + ' for even ' + event, result + ' for ' + this.id, this._targetReference);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Callback when the minimum parameters are given: targetReference & targetBlock
|
||||
*/
|
||||
onReady: function () {
|
||||
|
||||
if (!this._targetReference) {
|
||||
this._setupTargetReference();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//resolve 2way binding
|
||||
if (this._targetReference && this['bidirectional'] === true && this.sourceevent && this.sourceevent.length && !this.binding) {
|
||||
this._setup2WayBinding();
|
||||
}
|
||||
|
||||
if (this._complete) {
|
||||
return;
|
||||
}
|
||||
if (!this._targetReference) {
|
||||
console.error('have no target reference');
|
||||
}
|
||||
if (!this._targetBlock) {
|
||||
console.error('have no target block');
|
||||
}
|
||||
|
||||
|
||||
if (this._targetReference && this._targetBlock) {
|
||||
//we trigger on events
|
||||
if (this.targetevent) {
|
||||
this._complete = true;
|
||||
//patch the target
|
||||
utils.mixin(this._targetReference, EventedMixin.prototype);
|
||||
var _target = this._targetReference.domNode || this._targetReference,
|
||||
_event = this.targetevent,
|
||||
_isWidget = this._targetReference.declaredClass || this._targetReference.startup,
|
||||
_hasWidgetCallback = this._targetReference.on != null && this._targetReference['on' + utils.capitalize(_event)] != null,
|
||||
_handle = null,
|
||||
_isDelite = _target.render != null && _target.on != null,
|
||||
thiz = this;
|
||||
|
||||
if (_isWidget && (this._targetReference.baseClass && this._targetReference.baseClass.indexOf('dijitContentPane') != -1) || this._targetReference.render != null || this._targetReference.on != null) {
|
||||
_isWidget = false;//use on
|
||||
}
|
||||
|
||||
if (_target) {
|
||||
debugBinding && console.log('wire success ' + this.id + ' for ' + this.targetevent);
|
||||
if (!_isDelite && (!_hasWidgetCallback || !_isWidget)) {
|
||||
_handle = on(_target, this.targetevent, function (evt) {
|
||||
this.run(this.targetevent);
|
||||
}.bind(this));
|
||||
} else {
|
||||
_target = this._targetReference;
|
||||
var useOn = true;
|
||||
if (useOn) {
|
||||
if (!_isDelite) {
|
||||
var _e = 'on' + utils.capitalize(_event);
|
||||
this._targetReference[_e] = function (val, nada) {
|
||||
if (_target.ignore !== true) {
|
||||
thiz.run(thiz.targetevent, val);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
_handle = _target.on(this.targetevent, function (evt) {
|
||||
if (this.stop) {
|
||||
evt.preventDefault();
|
||||
evt.stopImmediatePropagation();
|
||||
}
|
||||
this.run(this.targetevent, evt.currentTarget.value);
|
||||
}.bind(this));
|
||||
}
|
||||
} else {
|
||||
this._targetReference['on' + utils.capitalize(_event)] = function (val) {
|
||||
if (_target.ignore !== true) {
|
||||
thiz.run(thiz.targetevent, val);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
_handle && this._events.push(_handle);
|
||||
} else {
|
||||
console.error('have no target to wire');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.error('invalid params, abort', this);
|
||||
}
|
||||
if (this.binding) {
|
||||
this.binding.start();
|
||||
}
|
||||
},
|
||||
resolveBlock: function (block) {
|
||||
var ctx = this._appContext;
|
||||
var deviceManager = ctx.getDeviceManager();
|
||||
if (block.indexOf('://') !== -1) {
|
||||
if (!deviceManager) {
|
||||
return;
|
||||
}
|
||||
var _block = deviceManager.getBlock(this.block);
|
||||
if (_block) {
|
||||
return _block;
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param ctx
|
||||
* @private
|
||||
*/
|
||||
_setBlock: function (ctx) {
|
||||
ctx = ctx || window['appContext'];
|
||||
if (!ctx || !ctx.getBlockManager) {
|
||||
debugApp && console.warn('have no context or block manager');
|
||||
return;
|
||||
}
|
||||
this._appContext = ctx;
|
||||
var blockManager = ctx.getBlockManager(),
|
||||
deviceManager = ctx.getDeviceManager(),
|
||||
thiz = this;
|
||||
|
||||
if (!blockManager) {
|
||||
return;
|
||||
}
|
||||
var _block = this.block ? this.block : this.getAttribute('block');
|
||||
if (_block && _block.length > 0) {
|
||||
var parts = utils.parse_url(_block);
|
||||
if (_block.indexOf('://') !== -1) {
|
||||
if (!deviceManager) {
|
||||
debugApp && console.warn('xScript::_setBlock : have no device manager');
|
||||
return;
|
||||
}
|
||||
var _block2 = deviceManager.getBlock(_block);
|
||||
if (_block2) {
|
||||
thiz._targetBlock = _block2;
|
||||
thiz.onReady();
|
||||
} else {
|
||||
debugBinding && console.warn('cant get block : ' + _block);
|
||||
}
|
||||
} else {
|
||||
blockManager.load(parts.scheme, parts.host).then(function (scope) {
|
||||
var block = scope.getBlockById(thiz.blockid);
|
||||
if (block) {
|
||||
thiz._targetBlock = block;
|
||||
thiz.onReady();
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (this.scopeid) {
|
||||
var scope = blockManager.hasScope(thiz.scopeid);
|
||||
if (scope) {
|
||||
var block = scope.getBlockById(thiz.blockid);
|
||||
if (block) {
|
||||
thiz._targetBlock = block;
|
||||
thiz.onReady();
|
||||
} else {
|
||||
block = scope.getVariableById(thiz.blockid);
|
||||
if (block) {
|
||||
thiz._targetBlock = block;
|
||||
thiz.onReady();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.error('have no scope!');
|
||||
}
|
||||
}
|
||||
},
|
||||
initWithReference: function (ref) {
|
||||
if (ref.nodeType !== 1) {
|
||||
return;
|
||||
}
|
||||
this._targetReference = ref;
|
||||
this._setBlock(null);
|
||||
},
|
||||
resolveFilter: function (expression, value, widget) {
|
||||
if (this._targetBlock) {
|
||||
var expressionModel = this._targetBlock.scope.expressionModel;
|
||||
value = expressionModel.parseVariable(this._targetBlock.scope, {
|
||||
value: expression
|
||||
}, '', false, false, widget, [value]);
|
||||
}
|
||||
return value;
|
||||
},
|
||||
/**
|
||||
* setup outbound wire, assumes all parameters are checked
|
||||
* @private
|
||||
*/
|
||||
_setup1WayBinding: function () {
|
||||
debugBinding && console.log('setup 1 way binding');
|
||||
//destroy old handle
|
||||
if (this._2wayHandle) {
|
||||
this._2wayHandle.remove();
|
||||
}
|
||||
|
||||
if (!this._targetBlock) {
|
||||
console.error('invalid params for one way binding');
|
||||
return;
|
||||
}
|
||||
var sourceVariableTitle = this._targetBlock.name;
|
||||
//wire to system event
|
||||
var bindingSource = new EventSource({
|
||||
//listen to variable changes
|
||||
trigger: this.sourceevent,
|
||||
//the path to value, ie: 'item.value'
|
||||
path: this.sourceeventvaluepath,
|
||||
//add an event filter
|
||||
filters: [{
|
||||
// variable title must match,ie: 'item.title'
|
||||
path: this.sourceeventnamepath,
|
||||
// the name of the variable, ie: 'Volume'
|
||||
value: sourceVariableTitle
|
||||
}]
|
||||
});
|
||||
|
||||
|
||||
//now map the event source to a widget
|
||||
var bindingTarget = new WidgetTarget({
|
||||
//the path to value
|
||||
path: this.targetproperty,
|
||||
object: this._targetReference,
|
||||
targetFilter: this.targetfilter,
|
||||
delegate: this
|
||||
});
|
||||
var accept = this._findbyTagAndName('D-SCRIPT', 'accept');
|
||||
var transform = this._findbyTagAndName('D-SCRIPT', 'transform');
|
||||
//construct the binding
|
||||
var binding = new Binding({
|
||||
source: bindingSource,
|
||||
target: bindingTarget,
|
||||
accept: this._findbyTagAndName('D-SCRIPT', 'accept'),
|
||||
transform: this._findbyTagAndName('D-SCRIPT', 'transform')
|
||||
});
|
||||
this.binding = binding;
|
||||
binding.start();
|
||||
},
|
||||
_findbyTagAndName: function (tag, name) {
|
||||
var scripts = $(this).find(tag);
|
||||
for (var i = 0; i < scripts.length; i++) {
|
||||
var script = scripts[i];
|
||||
if ($(script).attr('name') === name) {
|
||||
return script;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
/**
|
||||
* setup inbound wire, assumes all parameters are checked
|
||||
* @private
|
||||
*/
|
||||
_setup2WayBinding: function () {
|
||||
if (this.binding) {
|
||||
return;
|
||||
}
|
||||
debugBinding && console.log('setup 2 way binding');
|
||||
//destroy old handle
|
||||
if (this._2wayHandle) {
|
||||
this._2wayHandle.remove();
|
||||
}
|
||||
//wire to system event
|
||||
var bindingSource = new EventSource({
|
||||
//listen to variable changes
|
||||
trigger: this.sourceevent,
|
||||
//the path to value, ie: 'item.value'
|
||||
path: this.sourceeventvaluepath,
|
||||
//add an event filter
|
||||
filters: [{
|
||||
// variable title must match,ie: 'item.title'
|
||||
path: this.sourceeventnamepath,
|
||||
// the name of the variable, ie: 'Volume'
|
||||
value: this.targetvariable
|
||||
}]
|
||||
});
|
||||
|
||||
//now map the event source to a widget
|
||||
var bindingTarget = new WidgetTarget({
|
||||
//the path to value
|
||||
path: 'value',
|
||||
object: this._targetReference
|
||||
});
|
||||
this.binding = new Binding({
|
||||
source: bindingSource,
|
||||
target: bindingTarget
|
||||
});
|
||||
this.binding.start();
|
||||
},
|
||||
/**
|
||||
* Returns the widget whose DOM tree contains the specified DOMNode, or null if
|
||||
* the node is not contained within the DOM tree of any widget
|
||||
* @param {Element} node
|
||||
*/
|
||||
getEnclosingWidget: function (node) {
|
||||
if (node) {
|
||||
do {
|
||||
if (node.nodeType === 1 && node.render) {
|
||||
return node;
|
||||
}
|
||||
} while ((node = node.parentNode));
|
||||
}
|
||||
return null;
|
||||
},
|
||||
/**
|
||||
* Function to setup the target reference
|
||||
* on the surrounding widget!
|
||||
*
|
||||
*/
|
||||
_setupTargetReference: function () {
|
||||
var i = 0,
|
||||
element = this,
|
||||
widget = null;
|
||||
|
||||
while (i < 2 && !widget) {
|
||||
if (element) {
|
||||
element = element.parentNode;
|
||||
widget = this.getEnclosingWidget(element, "widgetId");
|
||||
if (!widget) {
|
||||
widget = this.getEnclosingWidget(element, "widgetid");
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (widget) {
|
||||
debugWidgets && console.info('have widget reference' + ' : ', widget);
|
||||
this.initWithReference(widget);
|
||||
} else {
|
||||
if (this.domNode && this.domNode.parentNode) {
|
||||
this.initWithReference(this.domNode.parentNode);
|
||||
debugWidgets && console.error('cant find widget reference, using parent node', this._targetReference);
|
||||
} else {
|
||||
if (this.parentNode) {
|
||||
this.initWithReference(this.parentNode);
|
||||
}
|
||||
debugWidgets && console.error('cant find widget reference', this);
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Required in case of dojoConfig.parseOnLoad
|
||||
* @param evt
|
||||
*/
|
||||
onAppReady: function (evt) {
|
||||
debugApp && console.log('-ready');
|
||||
if (this._targetBlock && this._targetBlock.scope && !this._targetBlock.scope.device) {
|
||||
this.reset();
|
||||
this._targetBlock = null;
|
||||
}
|
||||
//resolve target reference
|
||||
if (!this._targetReference) {
|
||||
this._setupTargetReference();
|
||||
}
|
||||
//resolve target block
|
||||
if (!this._targetBlock) {
|
||||
this._setBlock(evt ? evt.context : null);
|
||||
}
|
||||
|
||||
this.mode = this['bidirectional'] === true ? 0 : 1;
|
||||
//normal mode, allows 2-way binding
|
||||
if (this.mode === 0) {
|
||||
//resolve 2way binding
|
||||
if (this._targetBlock && this._targetReference && this['bidirectional'] === true && this.sourceevent && this.sourceevent.length) {
|
||||
this._setup2WayBinding();
|
||||
}
|
||||
|
||||
//if both are valid, run the the init procedure
|
||||
if (this._targetReference && this._targetBlock) {
|
||||
this.onReady();
|
||||
}
|
||||
|
||||
} else if (this.mode === 1 && this._targetBlock) {
|
||||
if (this._targetReference && this.sourceevent && this.sourceevent.length && this.targetproperty && this.targetproperty.length) {
|
||||
this._setup1WayBinding();
|
||||
if (this.binding) {
|
||||
this.binding.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
//track context {xapp/manager/Context}
|
||||
if (evt && evt.context) {
|
||||
this.context = evt.context;
|
||||
}
|
||||
},
|
||||
detachedCallback: function () {
|
||||
debugAttach && console.info('detachedCallback', this);
|
||||
if (this._appContext) {
|
||||
this.destroy();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Delite created callback
|
||||
*/
|
||||
createdCallback: function () {
|
||||
debugCreated && console.info('createdCallback', this);
|
||||
},
|
||||
/**
|
||||
* Delite attached callback
|
||||
*/
|
||||
attachedCallback: function () {
|
||||
debugAttach && console.info('attachedCallback', this);
|
||||
if (this._started) {
|
||||
return;
|
||||
}
|
||||
this.initReload();
|
||||
this.subscribe(Types.EVENTS.ON_APP_READY);
|
||||
this._started = true;
|
||||
|
||||
},
|
||||
detachCallback: function () {
|
||||
},
|
||||
render: function () {
|
||||
|
||||
},
|
||||
postRender: function () {
|
||||
|
||||
},
|
||||
startup: function () {
|
||||
debugAttach && console.log('startup');
|
||||
this.inherited(arguments);
|
||||
this.onAppReady();
|
||||
this.initReload();
|
||||
this.subscribe(Types.EVENTS.ON_APP_READY);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
//package and declare via dcl
|
||||
var _class = dcl([EventedMixin.dcl, ReloadMixin.dcl, Referenced.dcl], Impl);
|
||||
//static access to Impl.
|
||||
_class.Impl = Impl;
|
||||
return register("d-xscript", [HTMLElement, CustomElement, _class]);
|
||||
});
|
||||
83
packages/xblox/ref-control-freak/xblox/StyleState.js
Normal file
83
packages/xblox/ref-control-freak/xblox/StyleState.js
Normal file
@ -0,0 +1,83 @@
|
||||
define([
|
||||
'dcl/dcl',
|
||||
'delite/register',
|
||||
'delite/CustomElement',
|
||||
'xide/factory/Events',
|
||||
'xide/utils/StringUtils',
|
||||
'xide/types/Types',
|
||||
'xblox/_State'
|
||||
], function (dcl,register, CustomElement, Events, utils, Types,_State) {
|
||||
var Impl = {
|
||||
declaredClass: 'xblox/StyleState',
|
||||
_targetReference: null,
|
||||
name:"Default",
|
||||
_widget:null,
|
||||
/**
|
||||
* Convert Style String to an object array, eg: { color:value,.... }
|
||||
* @param styleString
|
||||
* @returns {{}}
|
||||
* @private
|
||||
*/
|
||||
_toObject:function(styleString){
|
||||
if(!styleString){
|
||||
return {};
|
||||
}
|
||||
var _result = {};
|
||||
var _values = styleString.split(';');
|
||||
for (var i = 0; i < _values.length; i++) {
|
||||
var obj = _values[i];
|
||||
if(!obj || obj.length==0 || !obj.split){
|
||||
continue;
|
||||
}
|
||||
var keyVal = obj.split(':');
|
||||
if(!keyVal || !keyVal.length){
|
||||
continue;
|
||||
}
|
||||
var key = obj.substring(0,obj.indexOf(':')).trim();
|
||||
var value = obj.substring(obj.indexOf(':')+1,obj.length).trim();
|
||||
_result[key]=value;
|
||||
}
|
||||
return _result;
|
||||
},
|
||||
_toStyleString:function(values){
|
||||
var _values = [];
|
||||
for(var prop in values){
|
||||
_values.push( prop + ':' + values[prop]);
|
||||
}
|
||||
return _values.join(';') + ';';
|
||||
},
|
||||
onChanged:function () {
|
||||
this.applyTo(this._widget);
|
||||
},
|
||||
attachedCallback: function () {
|
||||
//if($(this).attr('style').indexOf('display')==-1){
|
||||
// this.style.display = 'none';
|
||||
//}
|
||||
//
|
||||
/*
|
||||
console.log('attached ' + has('ide'));
|
||||
if(!has('ide')){
|
||||
var style = $(this).attr('style');
|
||||
var background = utils.getBackgroundUrl(style);
|
||||
console.log('style : '+background,this);
|
||||
}
|
||||
*/
|
||||
},
|
||||
_lastStyle:'',
|
||||
applyTo:function(widget){
|
||||
$(widget).removeClass($(widget).data('_lastCSSState'));
|
||||
$(widget).removeClass($(widget).data('_lastCSSClass'));
|
||||
if(widget && widget._attached){
|
||||
this._widget = widget;
|
||||
var _cssWidget = this._toObject($(widget).attr('style'));
|
||||
var _cssThis = this._toObject($(this).attr('style'));
|
||||
this._lastStyle = _cssThis;
|
||||
widget._lastStyle = _cssThis;
|
||||
var styleOut = utils.mixin(_cssWidget,_cssThis);
|
||||
$(widget).attr('style',this._toStyleString(styleOut));
|
||||
}
|
||||
}
|
||||
};
|
||||
var _class = dcl(_State, Impl);
|
||||
return register("d-xstate-style", [HTMLElement, CustomElement, _class]);
|
||||
});
|
||||
182
packages/xblox/ref-control-freak/xblox/_State.js
Normal file
182
packages/xblox/ref-control-freak/xblox/_State.js
Normal file
@ -0,0 +1,182 @@
|
||||
define([
|
||||
"dojo/_base/lang",
|
||||
"dojo/on",
|
||||
"dcl/dcl",//make sure
|
||||
"delite/register",
|
||||
"delite/CustomElement",
|
||||
//explicit because a bootstrap might not be loaded at some point
|
||||
"xide/factory/Events",
|
||||
//explicit because a bootstrap might not be loaded at some point
|
||||
'xide/utils/StringUtils',
|
||||
'xide/types/Types',
|
||||
'xblox/model/Referenced',
|
||||
'xide/mixins/EventedMixin',
|
||||
'xide/mixins/ReloadMixin',
|
||||
'xwire/Binding',
|
||||
'xwire/EventSource',
|
||||
'xwire/WidgetTarget'
|
||||
], function (lang, on, dcl,register, CustomElement, Events, utils, Types, Referenced, EventedMixin, ReloadMixin, Binding, EventSource, WidgetTarget) {
|
||||
var debugWidgets = false;
|
||||
var debugApp = false;
|
||||
var debugAttach = false;
|
||||
var debugCreated = false;
|
||||
var debugBinding = false;
|
||||
var debugRun = false;
|
||||
/**
|
||||
* Proxy widget to run a selected blox script on the parent widget/node.
|
||||
*
|
||||
* @class xblox/RunScript
|
||||
*/
|
||||
var Impl = {
|
||||
declaredClass: 'xblox/_State',
|
||||
script:"",
|
||||
bidirectional: false,
|
||||
_targetBlock: null,
|
||||
_targetReference: null,
|
||||
_complete: false,
|
||||
enabled: true,
|
||||
stop: false,
|
||||
_events: [],
|
||||
context: null,
|
||||
name:"Default",
|
||||
isState:true,
|
||||
_isState:function(){
|
||||
return true;
|
||||
},
|
||||
/**
|
||||
* soft destroy
|
||||
*/
|
||||
reset:function(){
|
||||
|
||||
},
|
||||
getChildren: function () {
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
destroy: function () {
|
||||
this.onDestroy && this.onDestroy();
|
||||
this.reset();
|
||||
},
|
||||
/**
|
||||
* The final execution when 'target event' has been triggered. This
|
||||
* will run the select block.
|
||||
* @param event
|
||||
* @param val
|
||||
*/
|
||||
run: function (event, val) {
|
||||
if (!this.enabled) {
|
||||
return;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Callback when the minimum parameters are given: targetReference & targetBlock
|
||||
*/
|
||||
onReady: function () {
|
||||
},
|
||||
getEnclosingWidget: function (node) {
|
||||
if(node) {
|
||||
do {
|
||||
if (node.nodeType === 1 && node.render) {
|
||||
return node;
|
||||
}
|
||||
} while ((node = node.parentNode));
|
||||
}
|
||||
return null;
|
||||
},
|
||||
initWithReference: function (ref) {
|
||||
//target node or widget
|
||||
if(ref.nodeType!==1){
|
||||
return;
|
||||
}
|
||||
this._targetReference = ref;
|
||||
},
|
||||
/**
|
||||
* Function to setup the target reference
|
||||
* on the surrounding widget!
|
||||
*
|
||||
*/
|
||||
_setupTargetReference: function () {
|
||||
var i = 0,
|
||||
element = this,
|
||||
widget = null;
|
||||
|
||||
while (i < 2 && !widget) {
|
||||
if (element) {
|
||||
element = element.parentNode;
|
||||
widget = this.getEnclosingWidget(element, "widgetId");
|
||||
if (!widget) {
|
||||
widget = this.getEnclosingWidget(element, "widgetid");
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (widget) {
|
||||
debugWidgets && console.info('have widget reference' + ' : ', [widget,this]);
|
||||
this.initWithReference(widget);
|
||||
if(widget._attached && widget.stateReady){
|
||||
widget.stateReady(this);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (this.domNode && this.domNode.parentNode) {
|
||||
this.initWithReference(this.domNode.parentNode);
|
||||
debugWidgets && console.error('cant find widget reference, using parent node', this._targetReference);
|
||||
} else {
|
||||
if(this.parentNode){
|
||||
this.initWithReference(this.parentNode);
|
||||
}
|
||||
debugWidgets && console.error('cant find widget reference', this);
|
||||
}
|
||||
}
|
||||
},
|
||||
onAppReady: function (evt) {
|
||||
debugApp && console.log('-ready');
|
||||
//resolve target reference
|
||||
//if (!this._targetReference) {
|
||||
this._setupTargetReference();
|
||||
//}
|
||||
|
||||
//track context {xapp/manager/Context}
|
||||
if (evt && evt.context) {
|
||||
this.context = evt.context;
|
||||
}
|
||||
},
|
||||
detachedCallback:function(){
|
||||
debugAttach && console.info('detachedCallback', this);
|
||||
if(this._appContext){
|
||||
this.destroy();
|
||||
}
|
||||
|
||||
},
|
||||
applyTo:function(widget){
|
||||
|
||||
},
|
||||
/**
|
||||
* Delite created callback
|
||||
*/
|
||||
createdCallback: function () {
|
||||
debugCreated && console.info('createdCallback', this);
|
||||
if (!this._targetReference) {
|
||||
this._setupTargetReference();
|
||||
if(this._targetReference && this._targetReference.stateReady){
|
||||
this._targetReference.stateReady(this);
|
||||
}
|
||||
}
|
||||
},
|
||||
attachedCallback: function () {
|
||||
debugAttach && console.info('attachedCallback', this);
|
||||
if (this._started) {
|
||||
return;
|
||||
}
|
||||
this.onAppReady();//emulates
|
||||
this.subscribe(Types.EVENTS.ON_APP_READY);
|
||||
this._started = true;
|
||||
}
|
||||
|
||||
};
|
||||
//package and declare via dcl
|
||||
var _class = dcl([EventedMixin.dcl,Referenced.dcl], Impl);
|
||||
return _class;
|
||||
});
|
||||
78
packages/xblox/ref-control-freak/xblox/_Stated.js
Normal file
78
packages/xblox/ref-control-freak/xblox/_Stated.js
Normal file
@ -0,0 +1,78 @@
|
||||
/** @module delite/_Stated */
|
||||
define([
|
||||
"dcl/dcl",
|
||||
"requirejs-dplugins/has",
|
||||
"xide/utils/CSSUtils"
|
||||
], function (dcl,has,utils) {
|
||||
return dcl(null,{
|
||||
state:'',
|
||||
/**
|
||||
* Returns all direct children of this widget, i.e. all widgets or DOM nodes underneath
|
||||
* `this.containerNode`. Note that it does not return all
|
||||
* descendants, but rather just direct children.
|
||||
*
|
||||
* The result intentionally excludes element outside off `this.containerNode`. So, it is different than
|
||||
* accessing the `children` or `childNode` properties.
|
||||
*
|
||||
* @returns {Element[]}
|
||||
*/
|
||||
_getChildren: function () {
|
||||
// use Array.prototype.slice to transform the live HTMLCollection into an Array
|
||||
return Array.prototype.slice.call(this.children);
|
||||
},
|
||||
_states:null,
|
||||
setState:function(stateName){
|
||||
//can be integer or anything non string
|
||||
var stateName = "" + stateName;
|
||||
var state = _.find(this.getStates(),{
|
||||
name:stateName
|
||||
});
|
||||
state && state.applyTo(this,stateName);
|
||||
},
|
||||
getState:function(_stateName){
|
||||
//can be integer or anything non string
|
||||
var stateName = "" + _stateName;
|
||||
return _.find(this.getStates(),{
|
||||
name:stateName
|
||||
});
|
||||
},
|
||||
attachedCallback: function () {
|
||||
/*
|
||||
console.log('attached ' + has('ide'));
|
||||
if(!has('ide')){
|
||||
var style = $(this).attr('style');
|
||||
var background = utils.getBackgroundUrl(style);
|
||||
console.log('style : '+background,this);
|
||||
}
|
||||
*/
|
||||
},
|
||||
addState:function(state){
|
||||
if(!this._states){
|
||||
this._states = [];
|
||||
}
|
||||
|
||||
if(this._states.indexOf(state)==-1){
|
||||
this._states.push(state);
|
||||
}
|
||||
},
|
||||
removeState:function(state){
|
||||
if(!this._states){
|
||||
this._states = [];
|
||||
}
|
||||
|
||||
if(this._states.indexOf(state)==-1){
|
||||
this._states.splice(this._states.indexOf(state),1);
|
||||
}
|
||||
},
|
||||
|
||||
stateReady:function(state){
|
||||
if(state.name ===this.state){
|
||||
state.applyTo(this,state.name);
|
||||
}
|
||||
this.addState(state);
|
||||
},
|
||||
getStates:function(){
|
||||
return this._states || [];
|
||||
}
|
||||
})
|
||||
});
|
||||
759
packages/xblox/ref-control-freak/xblox/bak/BlocksFileEditor.js
Normal file
759
packages/xblox/ref-control-freak/xblox/bak/BlocksFileEditor.js
Normal file
@ -0,0 +1,759 @@
|
||||
define([
|
||||
'dojo/_base/declare',
|
||||
'dojo/_base/lang',
|
||||
'xide/views/BeanView',
|
||||
'xide/views/BeanTreeView',
|
||||
'xide/factory',
|
||||
'xide/utils',
|
||||
"xide/views/_EditorMixin",
|
||||
"xide/layout/ContentPane",
|
||||
'xblox/views/GroupedBlockView',
|
||||
'xblox/views/BlocksGridViewDefault',
|
||||
'xblox/model/variables/Variable',
|
||||
'dojo/Deferred',
|
||||
'xide/layout/TabContainer',
|
||||
'xide/views/CIActionDialog',
|
||||
'xide/types',
|
||||
'xide/form/FilterSelect'
|
||||
|
||||
], function (declare, lang, BeanView, BeanTreeView, factory, utils, _EditorMixin, ContentPane, GroupedBlockView, BlocksGridViewDefault, Variable, Deferred,TabContainer,CIActionDialog,types,FilterSelect) {
|
||||
|
||||
return declare("xblox.views.BlocksFileEditor", [BeanView, BeanTreeView, _EditorMixin], {
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
//
|
||||
// object instances
|
||||
//
|
||||
|
||||
/**
|
||||
* xFile item, tracked in ::openItem
|
||||
*/
|
||||
_item: null,
|
||||
cssClass: 'bloxEditor',
|
||||
blockManager: null,
|
||||
blockManagerClass: 'xblox.manager.BlockManager',
|
||||
model: null,
|
||||
store: null,
|
||||
tree: null,
|
||||
currentItem: null,
|
||||
didLoad: false,
|
||||
selectable: false,
|
||||
|
||||
beanType: 'BLOCK',
|
||||
newGroupPrefix:'',
|
||||
_debug:false,
|
||||
|
||||
clearGroupViews:function(all){
|
||||
|
||||
|
||||
this.destroyWidgets();
|
||||
return;
|
||||
|
||||
var container = this.getGroupContainer(),
|
||||
thiz = this;
|
||||
|
||||
var panes = container.getChildren();
|
||||
for (var i = 0; i < panes.length; i++) {
|
||||
if(panes[i].isNewTab){
|
||||
container.removeChild(panes[i]);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < panes.length; i++) {
|
||||
|
||||
var pane = panes[i];
|
||||
/*
|
||||
if(pane.title=='Variables' && all!==true){
|
||||
continue;
|
||||
}*/
|
||||
container.removeChild(pane);
|
||||
|
||||
|
||||
}
|
||||
|
||||
this.createNewTab();
|
||||
|
||||
|
||||
|
||||
},
|
||||
|
||||
getContainerLabel:function(group){
|
||||
|
||||
var title = '' + group;
|
||||
console.log('add new block group ' + group);
|
||||
if(utils.isNativeEvent(group)){
|
||||
title = title.replace('on','');
|
||||
}
|
||||
|
||||
|
||||
//device variable changed: onDriverVariableChanged__deviceId__dd2985b9-9071-1682-226c-70b84b481117/9ab3eabe-ef9a-7613-c3c8-099cde54ef39
|
||||
if(group.indexOf(types.EVENTS.ON_DRIVER_VARIABLE_CHANGED)!==-1){
|
||||
|
||||
var deviceManager = this.ctx.getDeviceManager();
|
||||
var parts = group.split('__');
|
||||
var event = parts[0];
|
||||
var deviceId = parts[1];
|
||||
var driverId = parts[2];
|
||||
var variableId = parts[3];
|
||||
var device = deviceManager.getDeviceById(deviceId);
|
||||
|
||||
var driverScope = device ? device.driver : null;
|
||||
|
||||
//not initiated driver!
|
||||
if(driverScope && driverScope.blockScope){
|
||||
driverScope=driverScope.blockScope;
|
||||
}
|
||||
|
||||
if(!driverScope){
|
||||
console.error('have no driver, use driver from DB',group);
|
||||
if(device) {
|
||||
var driverId = deviceManager.getMetaValue(device, types.DEVICE_PROPERTY.CF_DEVICE_DRIVER);
|
||||
//var driverManager = this.ctx.getDriverManager();
|
||||
driverScope = this.ctx.getBlockManager().getScope(driverId);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var deviceTitle = device ? deviceManager.getMetaValue(device, types.DEVICE_PROPERTY.CF_DEVICE_TITLE) : 'Invalid Device';
|
||||
var variable=driverScope ? driverScope.getVariableById(driverId + '/' + variableId) : 'Invalid Variable(Have no driver)';
|
||||
title = 'Variable Changed('+deviceTitle+'/'+ (variable ? variable.title : 'Unknown Variable') +')';
|
||||
|
||||
|
||||
}
|
||||
return title;
|
||||
},
|
||||
|
||||
addNewBlockGroup:function(group){
|
||||
|
||||
if(!group){
|
||||
return;
|
||||
}
|
||||
|
||||
var blockScope = this.blockScope;
|
||||
var container = this.getGroupContainer();
|
||||
|
||||
var title = this.getContainerLabel(group);
|
||||
var contentPane = this.createGroupView(container, title, blockScope,true,'fa-bell');
|
||||
|
||||
var gridViewConstructurArgs = {};
|
||||
|
||||
|
||||
var newGroup = this.newGroupPrefix + group;
|
||||
gridViewConstructurArgs.newRootItemGroup = newGroup;
|
||||
|
||||
if(this._debug) {
|
||||
console.log('add new group:' + newGroup);
|
||||
}
|
||||
|
||||
var view = this.createGroupedBlockView(contentPane.containerNode, newGroup, blockScope, gridViewConstructurArgs);
|
||||
|
||||
container.selectChild(contentPane);
|
||||
},
|
||||
createGroupedBlockView: function (container, group, scope, extra,gridBaseClass) {
|
||||
|
||||
var thiz = this;
|
||||
|
||||
var args = {
|
||||
attachTo: container,
|
||||
beanContextName: this.beanContextName || scope.id,
|
||||
blockGroup: group,
|
||||
title: group,
|
||||
gridViewProto: BlocksGridViewDefault,
|
||||
blockScope: scope,
|
||||
ctx: this.ctx,
|
||||
delegate: this,
|
||||
showAllBlocks: true,
|
||||
open: true,
|
||||
lazy: true,
|
||||
titlePane: false,
|
||||
canToggle: false,
|
||||
gridParams: {
|
||||
cssClass: 'bloxGridView'
|
||||
},
|
||||
gridBaseClass:gridBaseClass
|
||||
};
|
||||
|
||||
if (extra) {
|
||||
args = lang.mixin(args, extra);
|
||||
}
|
||||
|
||||
var view = new GroupedBlockView(args);
|
||||
view.startup();
|
||||
|
||||
return view;
|
||||
},
|
||||
getDeviceVariablesAsEventOptions:function(startIntend){
|
||||
|
||||
var options = [];
|
||||
var _item = function(label,value,intend,selected,displayValue){
|
||||
|
||||
|
||||
var string="<span style=''>" +label + "</span>";
|
||||
var pre = "";
|
||||
if(intend>0){
|
||||
for (var i = 0; i < intend; i++) {
|
||||
pre+=" ";
|
||||
pre+=" ";
|
||||
pre+=" ";
|
||||
}
|
||||
}
|
||||
var _final = pre + string;
|
||||
return {
|
||||
label:_final,
|
||||
label2:displayValue,
|
||||
value:value
|
||||
};
|
||||
};
|
||||
|
||||
var deviceManager = this.ctx.getDeviceManager();
|
||||
var items = deviceManager.getDevices(false,true);
|
||||
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
var device = items[i];
|
||||
var driver = device.driver;
|
||||
if(!driver){
|
||||
continue;
|
||||
}
|
||||
|
||||
var title = deviceManager.getMetaValue(device, types.DEVICE_PROPERTY.CF_DEVICE_TITLE);
|
||||
var id = deviceManager.getMetaValue(device, types.DEVICE_PROPERTY.CF_DEVICE_ID);
|
||||
options.push(_item(title,driver.id+'/' +driver.id,startIntend,false));
|
||||
|
||||
|
||||
var blockScope = driver.blockScope;
|
||||
var variables = blockScope.getVariables();
|
||||
|
||||
console.log(device);
|
||||
|
||||
for (var j = 0; j < variables.length; j++) {
|
||||
var variable = variables[j];
|
||||
var value = types.EVENTS.ON_DRIVER_VARIABLE_CHANGED+ '__' + id+'__'+driver.id + '__'+ variable.id;
|
||||
var selected = false;
|
||||
options.push(_item(variable.title,value,startIntend + 1,selected,title + '/' + variable.title));
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
},
|
||||
openNewGroupDialog:function(){
|
||||
|
||||
//var options = utils.getEventsAsOptions();
|
||||
|
||||
var options = [];
|
||||
|
||||
var _item = function(label,value,intend){
|
||||
|
||||
|
||||
var string="<span style=''>" +label + "</span>";
|
||||
var pre = "";
|
||||
|
||||
if(intend>0){
|
||||
for (var i = 0; i < intend; i++) {
|
||||
pre+=" ";
|
||||
pre+=" ";
|
||||
pre+=" ";
|
||||
}
|
||||
}
|
||||
var _final = pre + string;
|
||||
return {
|
||||
label:_final,
|
||||
value:value,
|
||||
label2:label
|
||||
};
|
||||
};
|
||||
|
||||
options.push( _item('HTML','',0));
|
||||
options = options.concat([
|
||||
_item('onclick','click',1),
|
||||
_item('ondblclick','dblclick',1),
|
||||
_item('onmousedown','mousedown',1),
|
||||
_item('onmouseup','mouseup',1),
|
||||
_item('onmouseover','mouseover',1),
|
||||
_item('onmousemove','mousemove',1),
|
||||
_item('onmouseout','mouseout',1),
|
||||
_item('onkeypress','keypress',1),
|
||||
_item('onkeydown','keydown',1),
|
||||
_item('onkeyup','keyup',1),
|
||||
_item('onfocus','focus',1),
|
||||
_item('onblur','blur',1),
|
||||
_item('load','load',1)
|
||||
]);
|
||||
|
||||
options.push( _item('Device Variable Changed','',0));
|
||||
options = options.concat(this.getDeviceVariablesAsEventOptions(1));
|
||||
|
||||
|
||||
|
||||
var thiz = this;
|
||||
var actionDialog = new CIActionDialog({
|
||||
title: 'Create a new block group',
|
||||
style: 'width:500px;min-height:200px;',
|
||||
resizeable: true,
|
||||
delegate: {
|
||||
onOk: function (dlg, data) {
|
||||
|
||||
var event = data[0].value;
|
||||
thiz.addNewBlockGroup(event);
|
||||
}
|
||||
},
|
||||
cis: [
|
||||
utils.createCI('Event', types.ECIType.ENUMERATION, '',
|
||||
{
|
||||
group: 'Event',
|
||||
delegate: null,
|
||||
options:options,
|
||||
value:'HTML',
|
||||
widget:{
|
||||
"class":"xide.form.FilterSelect"
|
||||
}
|
||||
}
|
||||
|
||||
)
|
||||
],
|
||||
viewArgs:{
|
||||
inserts: [{
|
||||
query: '.dijitDialogPaneContent',
|
||||
insert: '<div><span class="simpleText">Select the event for the new group:</span></div>',
|
||||
place: 'first'
|
||||
}]
|
||||
}
|
||||
});
|
||||
actionDialog.show();
|
||||
},
|
||||
createNewTab:function(){
|
||||
|
||||
var thiz=this;
|
||||
utils.addWidget(ContentPane,{
|
||||
iconClass:'fa-magic',
|
||||
canSelect:false,
|
||||
isNewTab:true,
|
||||
onSelect:function(){
|
||||
thiz.openNewGroupDialog();
|
||||
}
|
||||
},this,this.getGroupContainer(),true,'',null,false);
|
||||
|
||||
},
|
||||
onGroupsCreated:function(){
|
||||
|
||||
if(this.canAddGroups){
|
||||
this.createNewTab();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Current Blox Scope {xblox.model.Scope}
|
||||
*/
|
||||
blockScope: null,
|
||||
//////////////////////////////////////////////////////////
|
||||
//
|
||||
// Widget Instances
|
||||
//
|
||||
groupContainer: null,
|
||||
|
||||
getTabContainer:function(){
|
||||
return this.groupContainer;
|
||||
},
|
||||
|
||||
canAddGroups:true,
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// item bean protocol
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
hasItemActions: function () {
|
||||
return true;
|
||||
},
|
||||
/**
|
||||
* Returns item actions
|
||||
* @returns {Array}
|
||||
*/
|
||||
getItemActions: function () {
|
||||
return this.inherited(arguments);//done in xide/bean/Grouped
|
||||
},
|
||||
//////////////////////////////////////////////////////////
|
||||
//
|
||||
// Public API
|
||||
//
|
||||
onReloaded: function () {
|
||||
this.destroyWidgets();
|
||||
this.openItem(this._item);
|
||||
},
|
||||
/**
|
||||
* default entry when opening a file item through xfile
|
||||
* @param item
|
||||
*/
|
||||
openItem: function (item) {
|
||||
|
||||
var dfd = new Deferred();
|
||||
this._item = item;
|
||||
var thiz = this;
|
||||
|
||||
var blockManager = this.getBlockManager();
|
||||
|
||||
blockManager.load(item.mount, item.path).then(function (scope) {
|
||||
thiz.initWithScope(scope);
|
||||
dfd.resolve(thiz);
|
||||
|
||||
});
|
||||
|
||||
return dfd;
|
||||
|
||||
},
|
||||
/**
|
||||
* Init with serialized string, forward to
|
||||
* @param content
|
||||
*/
|
||||
initWithContent: function (content) {
|
||||
|
||||
var data = null;
|
||||
try {
|
||||
data = utils.getJson(content);
|
||||
} catch (e) {
|
||||
console.error('invalid block data');
|
||||
}
|
||||
|
||||
if (data) {
|
||||
this.initWithData(data);
|
||||
}
|
||||
|
||||
},
|
||||
/**
|
||||
* Entry point when a blox scope is fully parsed
|
||||
* @param blockScope
|
||||
*/
|
||||
initWithScope: function (blockScope) {
|
||||
|
||||
this.blockScope = blockScope;
|
||||
var allBlockGroups = blockScope.allGroups(),
|
||||
thiz = this;
|
||||
|
||||
//console.log(' block groups', allBlockGroups);
|
||||
|
||||
if (allBlockGroups.indexOf('Variables') == -1) {
|
||||
allBlockGroups.push('Variables');
|
||||
}
|
||||
if (allBlockGroups.indexOf('Events') == -1) {
|
||||
allBlockGroups.push('Events');
|
||||
}
|
||||
if (allBlockGroups.indexOf('On Load') == -1) {
|
||||
allBlockGroups.push('On Load');
|
||||
}
|
||||
thiz.renderGroups(allBlockGroups, blockScope);
|
||||
|
||||
this.onLoaded();
|
||||
|
||||
},
|
||||
getScopeUserData: function () {
|
||||
return {
|
||||
owner: this
|
||||
};
|
||||
},
|
||||
initWithData: function (data) {
|
||||
|
||||
if(this._debug) {
|
||||
console.log('init with data', data);
|
||||
}
|
||||
|
||||
this.onLoaded();
|
||||
|
||||
var scopeId = utils.createUUID(),
|
||||
blockInData = data,
|
||||
variableInData = data;
|
||||
|
||||
//check structure
|
||||
if (lang.isArray(data)) {// a flat list of blocks
|
||||
|
||||
} else if (lang.isObject(data)) {
|
||||
scopeId = data.scopeId || scopeId;
|
||||
blockInData = data.blocks || [];
|
||||
variableInData = data.variables || [];
|
||||
}
|
||||
|
||||
var blockManager = this.getBlockManager();
|
||||
this.blockManager = blockManager;
|
||||
var scopeUserData = this.getScopeUserData();
|
||||
|
||||
var blockScope = blockManager.getScope(scopeId, scopeUserData, true);
|
||||
var allBlocks = blockScope.blocksFromJson(blockInData);
|
||||
|
||||
for (var i = 0; i < allBlocks.length; i++) {
|
||||
var obj = allBlocks[i];
|
||||
|
||||
obj._lastRunSettings = {
|
||||
force: false,
|
||||
highlight: true
|
||||
}
|
||||
}
|
||||
|
||||
var allVariables = blockScope.variablesFromJson(variableInData);
|
||||
blockManager.onBlocksReady(blockScope);
|
||||
if(this._debug) {
|
||||
console.log(' got blocks', allBlocks);
|
||||
console.log(' got variables', allVariables);
|
||||
}
|
||||
if (allBlocks) {
|
||||
return this.initWithScope(blockScope);
|
||||
}
|
||||
/**
|
||||
* a blocks file must be in that structure :
|
||||
*/
|
||||
},
|
||||
//////////////////////////////////////////////////////////
|
||||
//
|
||||
// utils
|
||||
//
|
||||
destroyWidgets: function () {
|
||||
utils.destroyWidget(this.groupContainer);
|
||||
if (this.blockManager && this.blockScope) {
|
||||
this.blockManager.removeScope(this.blockScope.id);
|
||||
}
|
||||
this.groupContainer = null;
|
||||
this.blockManager = null;
|
||||
},
|
||||
destroy: function () {
|
||||
this.destroyWidgets();
|
||||
this.inherited(arguments);
|
||||
},
|
||||
/**
|
||||
* Get/Create a block manager implicit
|
||||
* @returns {xblox.manager.BlockManager}
|
||||
*/
|
||||
getBlockManager: function () {
|
||||
|
||||
if (!this.blockManager) {
|
||||
|
||||
if (this.ctx.blockManager) {
|
||||
return this.ctx.blockManager;
|
||||
}
|
||||
|
||||
this.blockManager = factory.createInstance(this.blockManagerClass, {
|
||||
ctx: this.ctx
|
||||
});
|
||||
if(this._debug) {
|
||||
console.log('_createBlockManager ', this.blockManager);
|
||||
}
|
||||
}
|
||||
return this.blockManager;
|
||||
},
|
||||
//////////////////////////////////////////////////////////
|
||||
//
|
||||
// UI - Factory
|
||||
//
|
||||
createGroupContainer: function () {
|
||||
|
||||
var tabContainer = utils.addWidget(TabContainer, {
|
||||
tabStrip: true,
|
||||
tabPosition: "top",
|
||||
/*splitter: true,*/
|
||||
style: "min-width:450px;min-height:400px;height:inherit;padding:0px;"
|
||||
}, this, this.containerNode, true,'ui-widget-content');
|
||||
return tabContainer;
|
||||
},
|
||||
getGroupContainer: function () {
|
||||
if (this.groupContainer) {
|
||||
return this.groupContainer;
|
||||
}
|
||||
this.groupContainer = this.createGroupContainer();
|
||||
return this.groupContainer;
|
||||
},
|
||||
createGroupView: function (groupContainer, group,scope,closable,iconClass,select) {
|
||||
|
||||
return utils.addWidget(ContentPane, {
|
||||
delegate: this,
|
||||
iconClass:iconClass || '',
|
||||
title: group,
|
||||
allowSplit:true,
|
||||
closable:closable,
|
||||
style: 'padding:0px',
|
||||
cssClass: 'blocksEditorPane',
|
||||
blockView: null,
|
||||
onSelect: function () {
|
||||
if (this.blockView) {
|
||||
this.blockView.onShow();
|
||||
}
|
||||
}
|
||||
}, this, groupContainer, true,null,null,select,null);
|
||||
},
|
||||
renderGroup:function(group,blockScope,gridBaseClass){
|
||||
|
||||
|
||||
blockScope = blockScope || this.blockScope;
|
||||
|
||||
|
||||
var groupContainer = this.getGroupContainer(),
|
||||
thiz = this;
|
||||
|
||||
|
||||
|
||||
var title = group.replace(this.newGroupPrefix,'');
|
||||
if(utils.isNativeEvent(group)){
|
||||
title = title.replace('on','');
|
||||
}
|
||||
|
||||
|
||||
title = this.getContainerLabel(group.replace(this.newGroupPrefix,''));
|
||||
if(this._debug) {
|
||||
console.log('render group : ' + title);
|
||||
}
|
||||
|
||||
var isVariableView = group === 'Variables';
|
||||
|
||||
var contentPane = this.createGroupView(groupContainer, title, blockScope,!isVariableView,isVariableView ? ' fa-info-circle' : 'fa-bell',!isVariableView);
|
||||
|
||||
var gridViewConstructurArgs = {};
|
||||
|
||||
if (group === 'Variables') {
|
||||
|
||||
gridViewConstructurArgs.newRootItemFunction = function () {
|
||||
try {
|
||||
var newItem = new Variable({
|
||||
title: 'No-Title-Yet',
|
||||
type: 13,
|
||||
value: 'No Value',
|
||||
enumType: 'VariableType',
|
||||
save: false,
|
||||
initialize: '',
|
||||
group: 'Variables',
|
||||
id: utils.createUUID(),
|
||||
scope: blockScope
|
||||
});
|
||||
} catch (e) {
|
||||
debugger;
|
||||
}
|
||||
};
|
||||
|
||||
gridViewConstructurArgs.onGridDataChanged = function (evt) {
|
||||
|
||||
var item = evt.item;
|
||||
if (item) {
|
||||
item[evt.field] = evt.newValue;
|
||||
}
|
||||
thiz.save();
|
||||
};
|
||||
gridViewConstructurArgs.showAllBlocks = false;
|
||||
gridViewConstructurArgs.newRootItemLabel = 'New Variable';
|
||||
gridViewConstructurArgs.newRootItemIcon = 'fa-code';
|
||||
gridViewConstructurArgs.storeField = 'variableStore';
|
||||
gridViewConstructurArgs.gridParams ={
|
||||
cssClass: 'bloxGridView',
|
||||
getColumns:function(){
|
||||
return [
|
||||
{
|
||||
label: "Name",
|
||||
field: "title",
|
||||
sortable: true
|
||||
|
||||
},
|
||||
{
|
||||
label: "Value",
|
||||
field: "value",
|
||||
sortable: false
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
gridViewConstructurArgs.newRootItemGroup = group;
|
||||
|
||||
var view = this.createGroupedBlockView(contentPane.containerNode, group, blockScope, gridViewConstructurArgs,gridBaseClass);
|
||||
contentPane.blockView = view;
|
||||
view.parentContainer = contentPane;
|
||||
|
||||
return view;
|
||||
|
||||
|
||||
},
|
||||
renderGroups: function (_array, blockScope) {
|
||||
|
||||
var groupContainer = this.getGroupContainer();
|
||||
var lastChild = null, thiz = this;
|
||||
|
||||
for (var i = 0; i < _array.length; i++) {
|
||||
|
||||
var group = _array[i];
|
||||
|
||||
if(this.newGroupPrefix=='' && group.indexOf('__')!==-1){
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
var title = group.replace(this.newGroupPrefix,'');
|
||||
|
||||
var groupBlocks = blockScope.getBlocks({
|
||||
group: group
|
||||
});
|
||||
|
||||
if (group !== 'Variables' && (!groupBlocks || !groupBlocks.length)) {//skip empty
|
||||
continue;
|
||||
}
|
||||
|
||||
this.renderGroup(group,blockScope);
|
||||
|
||||
|
||||
} catch (e) {
|
||||
debugger;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
groupContainer.resize();
|
||||
setTimeout(function () {
|
||||
if (thiz.parentContainer) {
|
||||
thiz.parentContainer.resize();
|
||||
}
|
||||
}, 500);
|
||||
|
||||
this.onGroupsCreated();
|
||||
|
||||
},
|
||||
onSave: function (groupedBlockView) {
|
||||
this.save();
|
||||
},
|
||||
//////////////////////////////////////////////////////////
|
||||
//
|
||||
// Editor related
|
||||
//
|
||||
save: function () {
|
||||
|
||||
if (this.blockScope) {
|
||||
|
||||
var all = {
|
||||
blocks: null,
|
||||
variables: null
|
||||
};
|
||||
var blocks = this.blockScope.blocksToJson();
|
||||
try {
|
||||
//test integrity
|
||||
dojo.fromJson(JSON.stringify(blocks));
|
||||
} catch (e) {
|
||||
console.error('invalid data');
|
||||
return;
|
||||
}
|
||||
|
||||
var _onSaved = function () {};
|
||||
|
||||
var variables = this.blockScope.variablesToJson();
|
||||
try {
|
||||
//test integrity
|
||||
dojo.fromJson(JSON.stringify(variables));
|
||||
} catch (e) {
|
||||
console.error('invalid data');
|
||||
return;
|
||||
}
|
||||
all.blocks = blocks;
|
||||
all.variables = variables;
|
||||
this.saveContent(JSON.stringify(all, null, 2), this._item, _onSaved);
|
||||
}
|
||||
},
|
||||
onGridKeyEnter: function () {
|
||||
this.editBlock(this.getItem());
|
||||
},
|
||||
onGridMouseDoubleClick: function () {
|
||||
this.editBlock(this.getItem());
|
||||
}
|
||||
});
|
||||
});
|
||||
861
packages/xblox/ref-control-freak/xblox/bak/BlocksFileEditor.js2
Normal file
861
packages/xblox/ref-control-freak/xblox/bak/BlocksFileEditor.js2
Normal file
@ -0,0 +1,861 @@
|
||||
define([
|
||||
'dcl/dcl',
|
||||
'dojo/_base/lang',
|
||||
'dojo/_base/declare',
|
||||
'xide/factory',
|
||||
'xide/utils',
|
||||
'xblox/model/variables/Variable',
|
||||
'dojo/Deferred',
|
||||
'xide/views/_CIDialog',
|
||||
'xide/types',
|
||||
'xide/views/_LayoutMixin',
|
||||
'xblox/views/BlockGrid',
|
||||
'xaction/ActionProvider',
|
||||
'xide/layout/_TabContainer',
|
||||
'xide/layout/Container'
|
||||
], function (dcl,lang,declare, factory, utils, Variable, Deferred,_CIDialog,types,_LayoutMixin,BlockGrid,ActionProvider,_TabContainer,Container) {
|
||||
|
||||
var GridClass = declare('BlockGrid',BlockGrid,{
|
||||
_refresh:function(args){
|
||||
//var res = this.inherited(arguments);
|
||||
var history = this.getHistory();
|
||||
var now = history.getNow();
|
||||
if(now){
|
||||
//debugger;
|
||||
this.setParentBlock(now);
|
||||
}
|
||||
return res;
|
||||
},
|
||||
editBlock:function(_item,changedCB,select) {
|
||||
|
||||
var selection = this.getSelection(),
|
||||
item = selection[0] || _item;
|
||||
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
var head = new Deferred(),
|
||||
children = item.getChildren();
|
||||
|
||||
if(children && children.length){
|
||||
|
||||
console.log('--p');
|
||||
|
||||
var history = this.getHistory(),
|
||||
self = this,
|
||||
select = true;
|
||||
|
||||
this.setParentBlock(item);
|
||||
var isBack = false;
|
||||
head.resolve({
|
||||
select: select !== false ? ( isBack ? item : self.getRows()[0]) : null,
|
||||
focus: true,
|
||||
append: false,
|
||||
delay: 200
|
||||
});
|
||||
|
||||
return head;
|
||||
}
|
||||
},
|
||||
__select:function(items){
|
||||
var item = items[0] || {};
|
||||
return this.inherited(arguments);
|
||||
},
|
||||
/**
|
||||
* Step/Move Down & Step/Move Up action
|
||||
* @param dir
|
||||
*/
|
||||
move: function (dir) {
|
||||
|
||||
var items =this.getSelection();
|
||||
|
||||
console.log('move ' + dir,_.pluck(items,'id'));
|
||||
|
||||
if (!items || !items.length /*|| !item.parentId*/) {
|
||||
console.log('cant move, no selection or parentId', items);
|
||||
return;
|
||||
}
|
||||
var thiz = this;
|
||||
|
||||
if(dir===1){
|
||||
//items.reverse();
|
||||
}
|
||||
|
||||
_.each(items,function(item){
|
||||
item.move(item, dir);
|
||||
});
|
||||
|
||||
thiz.refreshRoot();
|
||||
thiz.refreshCurrent();
|
||||
|
||||
|
||||
this.select(items,null,true,{
|
||||
focus:true,
|
||||
delay:10
|
||||
}).then(function(){
|
||||
thiz.refreshActions();
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
reParentBlock:function(dir){
|
||||
|
||||
var item = this.getSelection()[0];
|
||||
if (!item) {
|
||||
console.log('cant move, no selection or parentId', item);
|
||||
return false;
|
||||
}
|
||||
var thiz = this;
|
||||
if(dir==-1) {
|
||||
item.unparent(thiz.blockGroup);
|
||||
}else{
|
||||
item.reparent();
|
||||
}
|
||||
|
||||
|
||||
thiz.deselectAll();
|
||||
thiz.refreshRoot();
|
||||
this.refreshCurrent();
|
||||
var dfd = new Deferred();
|
||||
var defaultSelectArgs = {
|
||||
focus: true,
|
||||
append: false,
|
||||
delay: 100,
|
||||
select:item,
|
||||
expand:true
|
||||
};
|
||||
dfd.resolve(defaultSelectArgs);
|
||||
return dfd;
|
||||
},
|
||||
defaultActionResult:function(items){
|
||||
var dfd = new Deferred();
|
||||
var defaultSelectArgs = {
|
||||
focus: true,
|
||||
append: false,
|
||||
delay: 0,
|
||||
select:items,
|
||||
expand:true
|
||||
};
|
||||
dfd.resolve(defaultSelectArgs);
|
||||
return dfd;
|
||||
},
|
||||
runAction: function (action) {
|
||||
var thiz = this;
|
||||
var sel = this.getSelection();
|
||||
|
||||
var selection = this.getSelection(),
|
||||
item = selection[0];
|
||||
switch (action.command){
|
||||
/*
|
||||
case 'Step/Move Left':
|
||||
{
|
||||
return this.reParentBlock(-1);
|
||||
}
|
||||
case 'Step/Move Right':
|
||||
{
|
||||
return this.reParentBlock(1);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if(action) {
|
||||
//console.error('run action ' + action.command);
|
||||
}
|
||||
|
||||
return this.inherited(arguments);
|
||||
}
|
||||
});
|
||||
var Module = dcl([Container,_LayoutMixin.dcl,ActionProvider.dcl],{
|
||||
declaredClass:"xblox.views.BlocksFileEditor",
|
||||
registerView:false,
|
||||
_item: null,
|
||||
cssClass: 'bloxEditor',
|
||||
blockManager: null,
|
||||
blockManagerClass: 'xblox.manager.BlockManager',
|
||||
model: null,
|
||||
store: null,
|
||||
tree: null,
|
||||
currentItem: null,
|
||||
didLoad: false,
|
||||
selectable: false,
|
||||
beanType: 'BLOCK',
|
||||
newGroupPrefix:'',
|
||||
_debug:false,
|
||||
blockScope: null,
|
||||
groupContainer: null,
|
||||
canAddGroups:true,
|
||||
gridClass:GridClass,
|
||||
activeGrid:null,
|
||||
activeTab:null,
|
||||
constructor:function(options,container){
|
||||
utils.mixin(this,options);
|
||||
},
|
||||
onGridAction:function(evt){
|
||||
var action = evt.action,
|
||||
command = action.command,
|
||||
result = evt.result,
|
||||
ACTION = types.ACTION;
|
||||
|
||||
switch (command){
|
||||
case ACTION.SAVE:{
|
||||
return this.save();
|
||||
}
|
||||
}
|
||||
//console.log('on after action '+evt.action.command);
|
||||
|
||||
},
|
||||
clearGroupViews:function(all){
|
||||
|
||||
var container = this.getGroupContainer(),
|
||||
thiz = this;
|
||||
|
||||
|
||||
container.empty();
|
||||
|
||||
|
||||
this.destroyWidgets();
|
||||
return;
|
||||
|
||||
var container = this.getGroupContainer(),
|
||||
thiz = this;
|
||||
|
||||
var panes = container.getChildren();
|
||||
for (var i = 0; i < panes.length; i++) {
|
||||
if(panes[i].isNewTab){
|
||||
container.removeChild(panes[i]);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < panes.length; i++) {
|
||||
|
||||
var pane = panes[i];
|
||||
/*
|
||||
if(pane.title=='Variables' && all!==true){
|
||||
continue;
|
||||
}*/
|
||||
container.removeChild(pane);
|
||||
|
||||
|
||||
}
|
||||
|
||||
this.createNewTab();
|
||||
|
||||
|
||||
|
||||
},
|
||||
getContainerLabel:function(group){
|
||||
|
||||
var title = '' + group;
|
||||
if(utils.isNativeEvent(group)){
|
||||
title = title.replace('on','');
|
||||
}
|
||||
//device variable changed: onDriverVariableChanged__deviceId__dd2985b9-9071-1682-226c-70b84b481117/9ab3eabe-ef9a-7613-c3c8-099cde54ef39
|
||||
if(group.indexOf(types.EVENTS.ON_DRIVER_VARIABLE_CHANGED)!==-1){
|
||||
|
||||
var deviceManager = this.ctx.getDeviceManager();
|
||||
var parts = group.split('__');
|
||||
var deviceId = parts[1];
|
||||
var driverId = parts[2];
|
||||
var variableId = parts[3];
|
||||
var device = deviceManager.getDeviceById(deviceId);
|
||||
|
||||
var driverScope = device ? device.driver : null;
|
||||
|
||||
//not initiated driver!
|
||||
if(driverScope && driverScope.blockScope){
|
||||
driverScope=driverScope.blockScope;
|
||||
}
|
||||
|
||||
if(!driverScope){
|
||||
console.error('have no driver, use driver from DB',group);
|
||||
if(device) {
|
||||
var driverId = deviceManager.getMetaValue(device, types.DEVICE_PROPERTY.CF_DEVICE_DRIVER);
|
||||
//var driverManager = this.ctx.getDriverManager();
|
||||
driverScope = this.ctx.getBlockManager().getScope(driverId);
|
||||
|
||||
}
|
||||
}
|
||||
var deviceTitle = device ? deviceManager.getMetaValue(device, types.DEVICE_PROPERTY.CF_DEVICE_TITLE) : 'Invalid Device';
|
||||
var variable=driverScope ? driverScope.getVariableById(driverId + '/' + variableId) : 'Invalid Variable(Have no driver)';
|
||||
title = 'Variable Changed('+deviceTitle+'/'+ (variable ? variable.title : 'Unknown Variable') +')';
|
||||
|
||||
}
|
||||
return title;
|
||||
},
|
||||
addNewBlockGroup:function(group){
|
||||
if(!group){
|
||||
return;
|
||||
}
|
||||
var blockScope = this.blockScope;
|
||||
var container = this.getGroupContainer();
|
||||
var title = this.getContainerLabel(group);
|
||||
var contentPane = this.createGroupView(container, title, blockScope,true,'fa-bell');
|
||||
var gridViewConstructurArgs = {};
|
||||
var newGroup = this.newGroupPrefix + group;
|
||||
gridViewConstructurArgs.newRootItemGroup = newGroup;
|
||||
var view = this.createGroupedBlockView(contentPane.containerNode, newGroup, blockScope, gridViewConstructurArgs);
|
||||
contentPane.grid=view;
|
||||
container.selectChild(contentPane);
|
||||
view.resize();
|
||||
},
|
||||
createGroupedBlockView: function (container, group, scope, extra,gridBaseClass){
|
||||
var thiz = this;
|
||||
gridBaseClass = gridBaseClass || this.gridClass;
|
||||
var store = scope.blockStore;
|
||||
|
||||
var gridArgs = {
|
||||
_docker:this.getDocker(),
|
||||
__right:this.getRightPanel(),
|
||||
ctx:this.ctx,
|
||||
blockScope: scope,
|
||||
blockGroup: group,
|
||||
attachDirect:true,
|
||||
resizeToParent:true,
|
||||
collection: store.filter({
|
||||
group: group
|
||||
}),
|
||||
_parent:container
|
||||
};
|
||||
|
||||
|
||||
extra && lang.mixin(gridArgs, extra);
|
||||
var view = utils.addWidget(gridBaseClass,gridArgs,null,container,false);
|
||||
|
||||
if(!view.__editorActions){
|
||||
view.__editorActions=true;
|
||||
this.addGridActions(view,view);
|
||||
}
|
||||
|
||||
//view.startup();
|
||||
|
||||
container.grid = view;
|
||||
view._on('selectionChanged',function(evt){
|
||||
thiz._emit('selectionChanged',evt);
|
||||
});
|
||||
|
||||
view._on('onAfterAction',function(e){
|
||||
thiz.onGridAction(e);
|
||||
});
|
||||
|
||||
if(this.registerView && this.ctx){
|
||||
|
||||
}
|
||||
//this.ctx.getWindowManager().registerView(view,true);
|
||||
|
||||
if(!container._widgets){
|
||||
container._widgets=[];
|
||||
}
|
||||
container._widgets.push(view);
|
||||
//utils.resizeTo(container,view,true,true);
|
||||
//view.showToolbar(true);
|
||||
return view;
|
||||
},
|
||||
getDeviceVariablesAsEventOptions:function(startIntend){
|
||||
var options = [];
|
||||
var _item = function(label,value,intend,selected,displayValue){
|
||||
|
||||
var string="<span style=''>" +label + "</span>";
|
||||
var pre = "";
|
||||
if(intend>0){
|
||||
for (var i = 0; i < intend; i++) {
|
||||
pre+=" ";
|
||||
pre+=" ";
|
||||
pre+=" ";
|
||||
}
|
||||
}
|
||||
var _final = pre + string;
|
||||
return {
|
||||
label:_final,
|
||||
label2:displayValue,
|
||||
value:value
|
||||
};
|
||||
};
|
||||
|
||||
var deviceManager = this.ctx.getDeviceManager();
|
||||
var items = deviceManager.getDevices(false,true);
|
||||
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
var device = items[i];
|
||||
var driver = device.driver;
|
||||
if(!driver){
|
||||
continue;
|
||||
}
|
||||
|
||||
var title = deviceManager.getMetaValue(device, types.DEVICE_PROPERTY.CF_DEVICE_TITLE);
|
||||
var id = deviceManager.getMetaValue(device, types.DEVICE_PROPERTY.CF_DEVICE_ID);
|
||||
options.push(_item(title,driver.id+'/' +driver.id,startIntend,false));
|
||||
|
||||
|
||||
var blockScope = driver.blockScope;
|
||||
var variables = blockScope.getVariables();
|
||||
for (var j = 0; j < variables.length; j++) {
|
||||
var variable = variables[j];
|
||||
var value = types.EVENTS.ON_DRIVER_VARIABLE_CHANGED+ '__' + id+'__'+driver.id + '__'+ variable.id;
|
||||
var selected = false;
|
||||
options.push(_item(variable.name,value,startIntend + 1,selected,title + '/' + variable.name));
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
},
|
||||
openNewGroupDialog:function(){
|
||||
var options = [];
|
||||
var _item = function(label,value,intend,isHTML){
|
||||
var string= isHTML !==true ? "<span style=''>" +label + "</span>" : label;
|
||||
var pre = "";
|
||||
if(intend>0){
|
||||
for (var i = 0; i < intend; i++) {
|
||||
pre+=" ";
|
||||
pre+=" ";
|
||||
pre+=" ";
|
||||
}
|
||||
}
|
||||
var _final = pre + string;
|
||||
return {
|
||||
label:_final,
|
||||
value:value,
|
||||
label2:label
|
||||
};
|
||||
};
|
||||
|
||||
options.push( _item('HTML','',0));
|
||||
options = options.concat([
|
||||
_item('onclick','click',1),
|
||||
_item('ondblclick','dblclick',1),
|
||||
_item('onmousedown','mousedown',1),
|
||||
_item('onmouseup','mouseup',1),
|
||||
_item('onmouseover','mouseover',1),
|
||||
_item('onmousemove','mousemove',1),
|
||||
_item('onmouseout','mouseout',1),
|
||||
_item('onkeypress','keypress',1),
|
||||
_item('onkeydown','keydown',1),
|
||||
_item('onkeyup','keyup',1),
|
||||
_item('onfocus','focus',1),
|
||||
_item('onblur','blur',1),
|
||||
_item('load','load',1)
|
||||
]);
|
||||
|
||||
options.push( _item('<span class="text-default">Device Variable Changed</span>','',0,true));
|
||||
options = options.concat(this.getDeviceVariablesAsEventOptions(1));
|
||||
|
||||
var thiz = this;
|
||||
var actionDialog = new _CIDialog({
|
||||
title: 'Create a new block group',
|
||||
style: 'width:500px;min-height:200px;',
|
||||
size: types.DIALOG_SIZE.SIZE_NORMAL,
|
||||
resizeable: true,
|
||||
onOk: function () {
|
||||
thiz.addNewBlockGroup(this.getField('Event'));
|
||||
},
|
||||
cis: [
|
||||
utils.createCI('Event', types.ECIType.ENUMERATION, '', {
|
||||
group: 'Event',
|
||||
delegate: null,
|
||||
options:options,
|
||||
value:'HTML',
|
||||
title:'Select an event ',
|
||||
widget:{
|
||||
search:true,
|
||||
"class":"xide.form.FilterSelect"
|
||||
}
|
||||
}
|
||||
)
|
||||
]
|
||||
});
|
||||
this.add(actionDialog,null,false);
|
||||
|
||||
return actionDialog.show();
|
||||
},
|
||||
onGroupsCreated:function(){
|
||||
//this.ctx.getWindowManager().registerView(this,true);
|
||||
},
|
||||
getActionStore:function(){
|
||||
if(this.activeGrid){
|
||||
return this.activeGrid.getActionStore();
|
||||
}
|
||||
return null;
|
||||
},
|
||||
getTabContainer:function(){
|
||||
return this.groupContainer;
|
||||
},
|
||||
onReloaded: function () {
|
||||
this.destroyWidgets();
|
||||
this.openItem(this._item);
|
||||
},
|
||||
/**
|
||||
* default entry when opening a file item through xfile
|
||||
* @param item
|
||||
*/
|
||||
openItem: function (item) {
|
||||
|
||||
var dfd = new Deferred();
|
||||
this._item = item;
|
||||
var thiz = this;
|
||||
|
||||
var blockManager = this.getBlockManager();
|
||||
|
||||
blockManager.load(item.mount, item.path).then(function (scope) {
|
||||
thiz.initWithScope(scope);
|
||||
dfd.resolve(thiz);
|
||||
});
|
||||
|
||||
return dfd;
|
||||
|
||||
},
|
||||
/**
|
||||
* Init with serialized string, forward to
|
||||
* @param content
|
||||
*/
|
||||
initWithContent: function (content) {
|
||||
|
||||
var data = null;
|
||||
try {
|
||||
data = utils.getJson(content);
|
||||
} catch (e) {
|
||||
console.error('invalid block data');
|
||||
}
|
||||
|
||||
if (data) {
|
||||
this.initWithData(data);
|
||||
}
|
||||
|
||||
},
|
||||
/**
|
||||
* Entry point when a blox scope is fully parsed
|
||||
* @param blockScope
|
||||
*/
|
||||
initWithScope: function (blockScope) {
|
||||
|
||||
this.blockScope = blockScope;
|
||||
|
||||
|
||||
var allBlockGroups = blockScope.allGroups(),
|
||||
thiz = this;
|
||||
|
||||
if (allBlockGroups.indexOf('Variables') == -1) {
|
||||
allBlockGroups.push('Variables');
|
||||
}
|
||||
if (allBlockGroups.indexOf('Events') == -1) {
|
||||
allBlockGroups.push('Events');
|
||||
}
|
||||
if (allBlockGroups.indexOf('On Load') == -1) {
|
||||
allBlockGroups.push('On Load');
|
||||
}
|
||||
|
||||
thiz.renderGroups(allBlockGroups, blockScope);
|
||||
|
||||
},
|
||||
getScopeUserData: function () {
|
||||
return {
|
||||
owner: this
|
||||
};
|
||||
},
|
||||
initWithData: function (data) {
|
||||
|
||||
if(this._debug) {
|
||||
console.log('init with data', data);
|
||||
}
|
||||
|
||||
this.onLoaded();
|
||||
|
||||
var scopeId = utils.createUUID(),
|
||||
blockInData = data,
|
||||
variableInData = data;
|
||||
|
||||
//check structure
|
||||
if (lang.isArray(data)) {// a flat list of blocks
|
||||
|
||||
} else if (lang.isObject(data)) {
|
||||
scopeId = data.scopeId || scopeId;
|
||||
blockInData = data.blocks || [];
|
||||
variableInData = data.variables || [];
|
||||
}
|
||||
|
||||
var blockManager = this.getBlockManager();
|
||||
this.blockManager = blockManager;
|
||||
var scopeUserData = this.getScopeUserData();
|
||||
|
||||
var blockScope = blockManager.getScope(scopeId, scopeUserData, true);
|
||||
var allBlocks = blockScope.blocksFromJson(blockInData);
|
||||
|
||||
for (var i = 0; i < allBlocks.length; i++) {
|
||||
var obj = allBlocks[i];
|
||||
|
||||
obj._lastRunSettings = {
|
||||
force: false,
|
||||
highlight: true
|
||||
}
|
||||
}
|
||||
|
||||
var allVariables = blockScope.variablesFromJson(variableInData);
|
||||
blockManager.onBlocksReady(blockScope);
|
||||
if(this._debug) {
|
||||
console.log(' got blocks', allBlocks);
|
||||
console.log(' got variables', allVariables);
|
||||
}
|
||||
if (allBlocks) {
|
||||
return this.initWithScope(blockScope);
|
||||
}
|
||||
/**
|
||||
* a blocks file must be in that structure :
|
||||
*/
|
||||
},
|
||||
destroyWidgets: function () {
|
||||
if (this.blockManager && this.blockScope) {
|
||||
this.blockManager.removeScope(this.blockScope.id);
|
||||
}
|
||||
//this.groupContainer = null;
|
||||
this.blockManager = null;
|
||||
},
|
||||
destroy: function () {
|
||||
this.destroyWidgets();
|
||||
},
|
||||
getBlockManager: function () {
|
||||
if (!this.blockManager) {
|
||||
if (this.ctx.blockManager) {
|
||||
return this.ctx.blockManager;
|
||||
}
|
||||
this.blockManager = factory.createInstance(this.blockManagerClass, {
|
||||
ctx: this.ctx
|
||||
});
|
||||
if(this._debug) {
|
||||
console.log('_createBlockManager ', this.blockManager);
|
||||
}
|
||||
}
|
||||
return this.blockManager;
|
||||
},
|
||||
createGroupContainer: function () {
|
||||
var tabContainer = utils.addWidget(_TabContainer, {
|
||||
tabStrip: true,
|
||||
tabPosition: "top",
|
||||
direction:'below',
|
||||
style: "min-width:450px;min-height:400px;padding:0px;",
|
||||
resizeToParent:true
|
||||
},this,this.containerNode,true);
|
||||
this.add(tabContainer,null,false);
|
||||
return tabContainer;
|
||||
},
|
||||
getGroupContainer: function () {
|
||||
if (this.groupContainer) {
|
||||
return this.groupContainer;
|
||||
}
|
||||
this.groupContainer = this.createGroupContainer();
|
||||
return this.groupContainer;
|
||||
},
|
||||
getActiveGrid:function(){
|
||||
return this.activeGrid;
|
||||
},
|
||||
runAction:function(action){
|
||||
if(action.command=='File/New Group'){
|
||||
this.openNewGroupDialog();
|
||||
return null;
|
||||
}
|
||||
return this.getActiveGrid().runAction(arguments);
|
||||
},
|
||||
addGridActions:function(grid,who){
|
||||
var result = [];
|
||||
var thiz = this;
|
||||
var defaultMixin = { addPermission: true };
|
||||
result.push(thiz.createAction({
|
||||
label: 'New Group',
|
||||
command: 'File/New Group',
|
||||
icon: 'fa-magic',
|
||||
tab: 'Home',
|
||||
group: 'File',
|
||||
keycombo: ['f7'],
|
||||
mixin: utils.mixin({quick:true},defaultMixin)
|
||||
}));
|
||||
result.push(thiz.createAction({
|
||||
label: 'Delete Group',
|
||||
command: 'File/Delete Group',
|
||||
icon: 'fa-remove',
|
||||
tab: 'Home',
|
||||
group: 'File',
|
||||
keycombo: ['ctrl f7'],
|
||||
mixin: utils.mixin({quick:true},defaultMixin)
|
||||
}));
|
||||
(who || this).addActions(result);
|
||||
},
|
||||
onShowGrid:function(grid){
|
||||
|
||||
if(this._isCreating){
|
||||
return;
|
||||
}
|
||||
this.ctx.getWindowManager().clearView(null);
|
||||
if(!grid.__editorActions){
|
||||
grid.__editorActions=true;
|
||||
this.addGridActions(grid);
|
||||
}
|
||||
|
||||
//this.groupContainer.resize();
|
||||
//grid.resize();
|
||||
setTimeout(function(){
|
||||
grid.resize();
|
||||
},100);
|
||||
this.ctx.getWindowManager().registerView(grid);
|
||||
},
|
||||
createGroupView: function (groupContainer, group,scope,closable,iconClass,selected) {
|
||||
var tab = groupContainer.createTab(group,iconClass,selected,_TabContainer.tabClass,{
|
||||
delegate: this,
|
||||
iconClass:iconClass || '',
|
||||
title: group,
|
||||
allowSplit:true,
|
||||
closable:closable,
|
||||
style: 'padding:0px',
|
||||
cssClass: 'blocksEditorPane',
|
||||
blockView: null
|
||||
});
|
||||
tab._on('show',function(tab){
|
||||
if(tab.grid) {
|
||||
this.activeTab = tab;
|
||||
this.activeGrid = tab.grid;
|
||||
this.onShowGrid(tab.grid); }
|
||||
},this);
|
||||
|
||||
return tab;
|
||||
},
|
||||
renderGroup:function(group,blockScope,gridBaseClass){
|
||||
|
||||
blockScope = blockScope || this.blockScope;
|
||||
var groupContainer = this.getGroupContainer(),
|
||||
thiz = this;
|
||||
|
||||
|
||||
var title = group.replace(this.newGroupPrefix,'');
|
||||
if(utils.isNativeEvent(group)){
|
||||
title = title.replace('on','');
|
||||
}
|
||||
|
||||
|
||||
title = this.getContainerLabel(group.replace(this.newGroupPrefix,''));
|
||||
var isVariableView = group === 'Variables';
|
||||
var contentPane = this.createGroupView(groupContainer, title, blockScope,!isVariableView,isVariableView ? ' fa-info-circle' : 'fa-bell',!isVariableView);
|
||||
//groupContainer.resize();
|
||||
var gridViewConstructurArgs = {};
|
||||
if (group === 'Variables') {
|
||||
|
||||
gridViewConstructurArgs.newRootItemFunction = function () {
|
||||
try {
|
||||
var newItem = new Variable({
|
||||
title: 'No-Title-Yet',
|
||||
type: 13,
|
||||
value: 'No Value',
|
||||
enumType: 'VariableType',
|
||||
save: false,
|
||||
initialize: '',
|
||||
group: 'Variables',
|
||||
id: utils.createUUID(),
|
||||
scope: blockScope
|
||||
});
|
||||
} catch (e) {
|
||||
debugger;
|
||||
}
|
||||
};
|
||||
|
||||
gridViewConstructurArgs.onGridDataChanged = function (evt) {
|
||||
|
||||
var item = evt.item;
|
||||
if (item) {
|
||||
item[evt.field] = evt.newValue;
|
||||
}
|
||||
thiz.save();
|
||||
};
|
||||
gridViewConstructurArgs.showAllBlocks = false;
|
||||
gridViewConstructurArgs.newRootItemLabel = 'New Variable';
|
||||
gridViewConstructurArgs.newRootItemIcon = 'fa-code';
|
||||
gridViewConstructurArgs.storeField = 'variableStore';
|
||||
gridViewConstructurArgs.gridParams ={
|
||||
cssClass: 'bloxGridView',
|
||||
getColumns:function(){
|
||||
return [
|
||||
{
|
||||
label: "Name",
|
||||
field: "title",
|
||||
sortable: true
|
||||
|
||||
},
|
||||
{
|
||||
label: "Value",
|
||||
field: "value",
|
||||
sortable: false
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
gridViewConstructurArgs.newRootItemGroup = group;
|
||||
|
||||
var view = this.createGroupedBlockView(contentPane, group, blockScope, gridViewConstructurArgs,gridBaseClass);
|
||||
contentPane.blockView = view;
|
||||
view.parentContainer = contentPane;
|
||||
|
||||
!this.activeGrid && (this.activeGrid=view);
|
||||
//groupContainer.resize();
|
||||
//contentPane.resize();
|
||||
setTimeout(function(){
|
||||
//view.showToolbar(true);
|
||||
},200);
|
||||
//view.resize();
|
||||
//contentPane.resize();
|
||||
//console.log('render group '+group);
|
||||
return view;
|
||||
|
||||
|
||||
},
|
||||
renderGroups: function (_array, blockScope) {
|
||||
this._isCreating = true;
|
||||
this.activeGrid = null;
|
||||
var groupContainer = this.getGroupContainer();
|
||||
for (var i = 0; i < _array.length; i++) {
|
||||
var group = _array[i];
|
||||
if(this.newGroupPrefix=='' && group.indexOf('__')!==-1){
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
var groupBlocks = blockScope.getBlocks({
|
||||
group: group
|
||||
});
|
||||
|
||||
if (group !== 'Variables' && (!groupBlocks || !groupBlocks.length)) {//skip empty
|
||||
continue;
|
||||
}
|
||||
this.renderGroup(group,blockScope);
|
||||
} catch (e) {
|
||||
logError(e);
|
||||
}
|
||||
}
|
||||
var firstTab = groupContainer.selectChild(0);
|
||||
this.onGroupsCreated();
|
||||
//groupContainer.resize();
|
||||
//groupContainer.resize();
|
||||
var thiz = this;
|
||||
//firstTab.resize();
|
||||
setTimeout(function(){
|
||||
thiz._isCreating = false;
|
||||
},1000);
|
||||
|
||||
},
|
||||
onSave: function (groupedBlockView) {
|
||||
this.save();
|
||||
},
|
||||
save: function () {
|
||||
if (this.blockScope) {
|
||||
//this.saveContent(this.blockScope.toString());
|
||||
|
||||
var fileManager = this.ctx.getFileManager(),
|
||||
item = this.item;
|
||||
|
||||
fileManager.setContent(item.mount,item.path,this.blockScope.toString(),function(){
|
||||
console.log('saved blocks! to ' + item.path);
|
||||
});
|
||||
|
||||
|
||||
}else{
|
||||
console.warn('BlocksFileEditor::save : have no block scope');
|
||||
}
|
||||
}
|
||||
});
|
||||
return Module;
|
||||
});
|
||||
68
packages/xblox/ref-control-freak/xblox/component.js
Normal file
68
packages/xblox/ref-control-freak/xblox/component.js
Normal file
@ -0,0 +1,68 @@
|
||||
define([
|
||||
"dcl/dcl",
|
||||
"xdojo/has",
|
||||
"xide/model/Component"
|
||||
], function (dcl,has,Component) {
|
||||
|
||||
/**
|
||||
* @class xblox.component
|
||||
* @inheritDoc
|
||||
*/
|
||||
return dcl(Component, {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
beanType:'BLOCK',
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Implement base interface
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
_load:function(){
|
||||
},
|
||||
hasEditors:function(){
|
||||
return ['xblox'];
|
||||
},
|
||||
getDependencies:function(){
|
||||
if(has('xblox-ui')) {
|
||||
return [
|
||||
'xide/xide',
|
||||
'xblox/types/Types',
|
||||
'xblox/manager/BlockManager',
|
||||
'xblox/manager/BlockManagerUI',
|
||||
'xblox/embedded_ui',
|
||||
'xblox/views/BlockGridPalette',
|
||||
'xide/widgets/ExpressionJavaScript',
|
||||
'xide/widgets/Expression',
|
||||
'xide/widgets/RichTextWidget',
|
||||
'xide/widgets/ExpressionEditor',
|
||||
'xide/widgets/WidgetReference'
|
||||
//'xide/widgets/DomStyleProperties',
|
||||
//'xblox/views/BlocksFileEditor'
|
||||
//'xide/widgets/BlockPickerWidget',
|
||||
//'xide/widgets/BlockSettingsWidget'
|
||||
];
|
||||
}else{
|
||||
return [
|
||||
'xide/xide',
|
||||
'xblox/types/Types',
|
||||
'xblox/manager/BlockManager',
|
||||
'xblox/embedded'
|
||||
];
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getLabel: function () {
|
||||
return 'xblox';
|
||||
},
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getBeanType:function(){
|
||||
return this.beanType;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
72
packages/xblox/ref-control-freak/xblox/data/Store.js
Normal file
72
packages/xblox/ref-control-freak/xblox/data/Store.js
Normal file
@ -0,0 +1,72 @@
|
||||
/** @module xblox/data/Store **/
|
||||
define([
|
||||
"dojo/_base/declare",
|
||||
'xide/data/TreeMemory',
|
||||
'xide/data/ObservableStore',
|
||||
'dstore/Trackable',
|
||||
'dojo/Deferred'
|
||||
], function (declare, TreeMemory, ObservableStore, Trackable, Deferred) {
|
||||
return declare("xblox.data.Store", [TreeMemory, Trackable, ObservableStore], {
|
||||
idProperty: 'id',
|
||||
parentField: 'parentId',
|
||||
parentProperty: 'parentId',
|
||||
filter: function (data) {
|
||||
var _res = this.inherited(arguments);
|
||||
delete this._state.filter;
|
||||
this._state.filter = data;
|
||||
return _res;
|
||||
},
|
||||
getRootItem:function(){
|
||||
return {
|
||||
canAdd:function(){
|
||||
return true
|
||||
},
|
||||
id:this.id +'_root',
|
||||
group:null,
|
||||
name:'root',
|
||||
isRoot:true,
|
||||
parentId:null
|
||||
}
|
||||
},
|
||||
getChildren: function (object) {
|
||||
return this.root.filter({parentId: this.getIdentity(object)});
|
||||
},
|
||||
_fetchRange: function (kwArgs) {
|
||||
var deferred = new Deferred();
|
||||
var _res = this.fetchRangeSync(kwArgs);
|
||||
var _items;
|
||||
if (this._state.filter) {
|
||||
//the parent query
|
||||
if (this._state.filter['parentId']) {
|
||||
var _item = this.getSync(this._state.filter.parentId);
|
||||
if (_item) {
|
||||
this.reset();
|
||||
_items = _item.items;
|
||||
if (_item.getChildren) {
|
||||
_items = _item.getChildren();
|
||||
}
|
||||
deferred.resolve(_items);
|
||||
_res = _items;
|
||||
}
|
||||
}
|
||||
|
||||
//the group query
|
||||
if (this._state && this._state.filter && this._state.filter['group']) {
|
||||
_items = this.getSync(this._state.filter.parent);
|
||||
if (_item) {
|
||||
this.reset();
|
||||
_res = _item.items;
|
||||
}
|
||||
}
|
||||
}
|
||||
deferred.resolve(_res);
|
||||
return deferred;
|
||||
},
|
||||
mayHaveChildren: function (parent) {
|
||||
if (parent.mayHaveChildren) {
|
||||
return parent.mayHaveChildren(parent);
|
||||
}
|
||||
return parent.items != null && parent.items.length > 0;
|
||||
}
|
||||
});
|
||||
});
|
||||
76
packages/xblox/ref-control-freak/xblox/docs/Command.md
Normal file
76
packages/xblox/ref-control-freak/xblox/docs/Command.md
Normal file
@ -0,0 +1,76 @@
|
||||
## Description
|
||||
|
||||
The command block is meant for holding a string to be send to a device.
|
||||
|
||||
|
||||
|
||||
## Parameters
|
||||
|
||||
**Enabled**
|
||||
|
||||
Field Name : "enabled"
|
||||
|
||||
Type : Boolean
|
||||
|
||||
Remarks:
|
||||
|
||||
- If disabled at run-time, it will stop the block and cancels also the interval timer.
|
||||
|
||||
<hr/>
|
||||
|
||||
|
||||
**Send on Startup**
|
||||
|
||||
If true, this block will be executed when the device is connected.
|
||||
|
||||
Field Name: "startup"
|
||||
|
||||
Type: Boolean
|
||||
|
||||
<hr/>
|
||||
|
||||
**Interval**
|
||||
|
||||
If greater than 0, the block will be looped by that interval in ms.
|
||||
|
||||
Field Name: "interval"
|
||||
|
||||
Type: Boolean
|
||||
|
||||
<hr/>
|
||||
|
||||
|
||||
**Has Response**
|
||||
|
||||
Some protocols like the built-in SSH return standard execution marks, like std-error, std-data.
|
||||
When this setting is on, the system will mark the command as running but not finished.
|
||||
As soon such command receives and "end" from the server, it will mark the command as finished and proceeds
|
||||
with sub blocks.
|
||||
|
||||
Field Name: "waitForResponse"
|
||||
|
||||
Type: Boolean
|
||||
|
||||
<hr/>
|
||||
|
||||
**Flags**
|
||||
|
||||
|
||||
*"Dont parse"* : will send the string in "Send" as is.
|
||||
|
||||
*"Expression"* : This flag is on by default! When on, the string in "Send" will be treated and evaluated as Javascript.
|
||||
|
||||
|
||||
Field Name: "flags"
|
||||
|
||||
Type: integer
|
||||
|
||||
*Remarks*:
|
||||
|
||||
-When "Expression" is on, it will replace variables in "Send"
|
||||
|
||||
-When "Expression" is on, it will add "return" in front of what's in "Send" if missing
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
106
packages/xblox/ref-control-freak/xblox/docs/Events/OnEvent.md
Normal file
106
packages/xblox/ref-control-freak/xblox/docs/Events/OnEvent.md
Normal file
@ -0,0 +1,106 @@
|
||||
## Description
|
||||
|
||||
This block enables to subscribe to system events.
|
||||
|
||||
|
||||
## Parameters
|
||||
|
||||
**Enabled**
|
||||
|
||||
Field Name : "enabled"
|
||||
|
||||
Type : Boolean
|
||||
|
||||
<hr/>
|
||||
|
||||
**Filter Path**
|
||||
|
||||
|
||||
Every event comes with its own payload object and its own structure differs per event.
|
||||
|
||||
This field enables to specify the path to a value inside that payload. This needs be set only if the
|
||||
|
||||
payload is an object, and not already primitive.
|
||||
|
||||
|
||||
So this field enables you to filter events and the block will only be triggered if *Filter Value* matches the value inside the payload path.
|
||||
|
||||
**Example**
|
||||
|
||||
We want to subscribe to "Driver Variable Changed", but only for a certain variable: "Volume".
|
||||
|
||||
The event payload object for "onDriverVariableChanged" looks like this:
|
||||
|
||||
```
|
||||
{
|
||||
item:variable
|
||||
}
|
||||
```
|
||||
|
||||
where the variable object looks like this:
|
||||
|
||||
```
|
||||
{
|
||||
value:"variable value",
|
||||
name:"Volume"
|
||||
}
|
||||
```
|
||||
|
||||
To trigger this block only for "Volume", this field needs to be set to: item.name
|
||||
|
||||
<hr/>
|
||||
|
||||
**Filter Value**
|
||||
|
||||
Needs to be set when the block should only trigger if the event payload contains a certain value, specified by "Filter Path"
|
||||
|
||||
|
||||
|
||||
**Example**
|
||||
|
||||
We want to subscribe to "Driver Variable Changed", but only for a certain variable: "Volume".
|
||||
|
||||
The event payload object for "onDriverVariableChanged" looks like this:
|
||||
|
||||
```
|
||||
{
|
||||
item:variable
|
||||
}
|
||||
```
|
||||
|
||||
where the variable object looks like this:
|
||||
|
||||
```
|
||||
{
|
||||
value:"variable value",
|
||||
name:"Volume"
|
||||
}
|
||||
```
|
||||
|
||||
To trigger this block only for "Volume", this field needs to be set to: "Volume", and the "Filter Path" needs
|
||||
to be set to "item.name"
|
||||
|
||||
<hr/>
|
||||
|
||||
**Value Path**
|
||||
|
||||
The path to the value to be forward to sub blocks within the payload.
|
||||
|
||||
**Example**
|
||||
|
||||
If we want to forward the variable's value to sub blocks, this field needs to be set to "item.value"
|
||||
|
||||
For instance, you can access this value in sub blocks with arguments[0];
|
||||
|
||||
<hr/>
|
||||
|
||||
### Tips:
|
||||
|
||||
Attach a Run Script block with this code:
|
||||
|
||||
```
|
||||
console.log(arguments);
|
||||
```
|
||||
|
||||
to see the event payload in the Dev-Tools console
|
||||
|
||||
63
packages/xblox/ref-control-freak/xblox/docs/File/ReadJSON.md
Normal file
63
packages/xblox/ref-control-freak/xblox/docs/File/ReadJSON.md
Normal file
@ -0,0 +1,63 @@
|
||||
## Description
|
||||
|
||||
The block reads JSON data from a file
|
||||
|
||||
|
||||
|
||||
## Parameters
|
||||
|
||||
**Enabled**
|
||||
|
||||
Field Name : "enabled"
|
||||
|
||||
Type : Boolean
|
||||
|
||||
Remarks:
|
||||
|
||||
- If disabled at run-time, it will stop the block and cancels also the interval timer.
|
||||
|
||||
<hr/>
|
||||
|
||||
|
||||
**Path**
|
||||
|
||||
Field Name : "path"
|
||||
|
||||
Type : String
|
||||
|
||||
Description : An absolute path. This path must exist on the device server.
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
|
||||
**Select**
|
||||
|
||||
Field Name : "jsonPath"
|
||||
|
||||
Type : String
|
||||
|
||||
Description : A path within the data. If set, the selected data will be forwarded to child blocks.
|
||||
|
||||
For instance, if the data is:
|
||||
```json
|
||||
{
|
||||
"boolean":true,
|
||||
"number":10.0,
|
||||
"array":[1,2,3],
|
||||
"myField":"my field value"
|
||||
}
|
||||
```
|
||||
|
||||
You can select the value of "myField" by using 'myField' which returns my field value.
|
||||
|
||||
You can select the second field of "array" by using 'array.2' which returns 2.
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
|
||||
**Tips**:
|
||||
|
||||
In child blocks you can retrieve the data by using "return arguments[0]".
|
||||
|
||||
5
packages/xblox/ref-control-freak/xblox/docs/_index.md
Normal file
5
packages/xblox/ref-control-freak/xblox/docs/_index.md
Normal file
@ -0,0 +1,5 @@
|
||||
### XBlocks Reference
|
||||
|
||||
### Driver related
|
||||
|
||||
[Command](Blocks/Command)
|
||||
74
packages/xblox/ref-control-freak/xblox/embedded.js
Normal file
74
packages/xblox/ref-control-freak/xblox/embedded.js
Normal file
@ -0,0 +1,74 @@
|
||||
define([
|
||||
'dojo/_base/declare',
|
||||
'xide/types',
|
||||
'xblox/types/Types',
|
||||
'xide/factory',
|
||||
'xide/utils',
|
||||
'xide/mixins/ReloadMixin',
|
||||
'xide/mixins/EventedMixin',
|
||||
"xblox/model/logic/CaseBlock",
|
||||
"xblox/model/Block",
|
||||
"xblox/model/functions/CallBlock",
|
||||
"xblox/model/code/CallMethod",
|
||||
"xblox/model/code/RunScript",
|
||||
"xblox/model/code/RunBlock",
|
||||
"xblox/model/loops/ForBlock",
|
||||
"xblox/model/loops/WhileBlock",
|
||||
"xblox/model/variables/VariableAssignmentBlock",
|
||||
"xblox/model/logic/IfBlock",
|
||||
"xblox/model/logic/ElseIfBlock",
|
||||
"xblox/model/logic/SwitchBlock",
|
||||
"xblox/model/variables/VariableSwitch",
|
||||
"xblox/model/events/OnEvent",
|
||||
"xblox/model/events/OnKey",
|
||||
"xblox/model/logging/Log",
|
||||
"xblox/model/html/SetStyle",
|
||||
"xblox/model/html/SetCSS",
|
||||
"xblox/model/html/SetStyle",
|
||||
"xblox/manager/BlockManager",
|
||||
"xblox/factory/Blocks",
|
||||
"xdojo/has!xblox-ui?xblox/model/Block_UI"
|
||||
], function () {
|
||||
if(!Array.prototype.remove){
|
||||
Array.prototype.remove= function(){
|
||||
var what, a= arguments, L= a.length, ax;
|
||||
while(L && this.length){
|
||||
what= a[--L];
|
||||
if(this.indexOf==null){
|
||||
break;
|
||||
}
|
||||
while((ax= this.indexOf(what))!= -1){
|
||||
this.splice(ax, 1);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
}
|
||||
if(!Array.prototype.swap){
|
||||
Array.prototype.swap = function (x,y) {
|
||||
var b = this[x];
|
||||
this[x] = this[y];
|
||||
this[y] = b;
|
||||
return this;
|
||||
};
|
||||
}
|
||||
|
||||
if ( typeof String.prototype.startsWith != 'function' ) {
|
||||
String.prototype.startsWith = function( str ) {
|
||||
return this.substring( 0, str.length ) === str;
|
||||
};
|
||||
}
|
||||
|
||||
if ( typeof String.prototype.endsWith != 'function' ) {
|
||||
String.prototype.endsWith = function( str ) {
|
||||
return this.substring( this.length - str.length, this.length ) === str;
|
||||
};
|
||||
}
|
||||
|
||||
if(!Function.prototype.bind) {
|
||||
// Cheap polyfill to approximate bind(), make Safari happy
|
||||
Function.prototype.bind = Function.prototype.bind || function (that) {
|
||||
return dojo.hitch(that, this);
|
||||
};
|
||||
}
|
||||
});
|
||||
6
packages/xblox/ref-control-freak/xblox/embedded_ui.js
Normal file
6
packages/xblox/ref-control-freak/xblox/embedded_ui.js
Normal file
@ -0,0 +1,6 @@
|
||||
define([
|
||||
'xblox/embedded',
|
||||
'xblox/factory/Blocks',
|
||||
'xide/widgets/ScriptWidget'
|
||||
], function () {
|
||||
});
|
||||
542
packages/xblox/ref-control-freak/xblox/factory/Blocks.js
Normal file
542
packages/xblox/ref-control-freak/xblox/factory/Blocks.js
Normal file
@ -0,0 +1,542 @@
|
||||
define([
|
||||
'xide/factory',
|
||||
'xide/utils',
|
||||
'xide/types',
|
||||
'xide/mixins/ReloadMixin',
|
||||
'xide/mixins/EventedMixin',
|
||||
"xblox/model/logic/CaseBlock",
|
||||
"xblox/model/Block",
|
||||
"xblox/model/functions/CallBlock",
|
||||
"xblox/model/functions/StopBlock",
|
||||
"xblox/model/functions/PauseBlock",
|
||||
"xblox/model/functions/SetProperties",
|
||||
"xblox/model/code/CallMethod",
|
||||
"xblox/model/code/RunScript",
|
||||
"xblox/model/loops/ForBlock",
|
||||
"xblox/model/loops/WhileBlock",
|
||||
"xblox/model/variables/VariableAssignmentBlock",
|
||||
"xblox/model/logic/IfBlock",
|
||||
"xblox/model/logic/ElseIfBlock",
|
||||
"xblox/model/logic/SwitchBlock",
|
||||
"xblox/model/variables/VariableSwitch",
|
||||
"xblox/model/logging/Log",
|
||||
"xblox/model/server/RunServerMethod",
|
||||
"xblox/model/server/Shell",
|
||||
"xblox/model/code/RunBlock",
|
||||
"xblox/model/events/OnEvent",
|
||||
"xblox/model/events/OnKey",
|
||||
"xblox/model/mqtt/Subscribe",
|
||||
"xblox/model/mqtt/Publish",
|
||||
"xblox/model/File/ReadJSON",
|
||||
"xcf/factory/Blocks"
|
||||
], function (factory,
|
||||
utils,
|
||||
types,
|
||||
ReloadMixin, EventedMixin,
|
||||
CaseBlock,
|
||||
Block,
|
||||
CallBlock,
|
||||
StopBlock,
|
||||
PauseBlock,
|
||||
SetProperties,
|
||||
CallMethod,
|
||||
RunScript,
|
||||
ForBlock,
|
||||
WhileBlock,
|
||||
VariableAssignmentBlock,
|
||||
IfBlock,
|
||||
ElseIfBlock,
|
||||
SwitchBlock,
|
||||
VariableSwitch,
|
||||
Log,
|
||||
RunServerMethod,
|
||||
Shell,
|
||||
RunBlock,
|
||||
OnEvent,
|
||||
OnKey,
|
||||
Subscribe,
|
||||
Publish,
|
||||
ReadJSON) {
|
||||
|
||||
var cachedAll = null;
|
||||
/***
|
||||
*
|
||||
* @param mixed String|Prototype
|
||||
* @param ctorArgs
|
||||
* @param baseClasses
|
||||
* @param publish
|
||||
*/
|
||||
factory.createBlock = function (mixed, ctorArgs, baseClasses, publish) {
|
||||
//complete missing arguments:
|
||||
Block.prototype.prepareArgs(ctorArgs);
|
||||
var block = factory.createInstance(mixed, ctorArgs, baseClasses);
|
||||
block.ctrArgs = null;
|
||||
var newBlock;
|
||||
try {
|
||||
if (block && block.init) {
|
||||
block.init();
|
||||
}
|
||||
//add to scope
|
||||
if (block.scope) {
|
||||
newBlock = block.scope.registerBlock(block, publish);
|
||||
}
|
||||
if (block.initReload) {
|
||||
block.initReload();
|
||||
}
|
||||
} catch (e) {
|
||||
logError(e, 'create block');
|
||||
}
|
||||
return newBlock || block;
|
||||
};
|
||||
factory.clearVariables = function () {
|
||||
};
|
||||
factory.getAllBlocks = function (scope, owner, target, group, allowCache) {
|
||||
if (allowCache !== false && cachedAll != null) {
|
||||
return cachedAll;
|
||||
} else if (allowCache == false) {
|
||||
cachedAll = null;
|
||||
}
|
||||
var items = factory._getFlowBlocks(scope, owner, target, group);
|
||||
items = items.concat(factory._getLoopBlocks(scope, owner, target, group));
|
||||
items = items.concat(factory._getCommandBlocks(scope, owner, target, group));
|
||||
items = items.concat(factory._getCodeBlocks(scope, owner, target, group));
|
||||
items = items.concat(factory._getEventBlocks(scope, owner, target, group));
|
||||
items = items.concat(factory._getLoggingBlocks(scope, owner, target, group));
|
||||
items = items.concat(factory._getServerBlocks(scope, owner, target, group));
|
||||
items = items.concat(factory._getMQTTBlocks(scope, owner, target, group));
|
||||
items = items.concat(factory._getFileBlocks(scope, owner, target, group));
|
||||
cachedAll = items;
|
||||
return items;
|
||||
};
|
||||
factory._getMQTTBlocks = function (scope, owner, target, group) {
|
||||
var items = [];
|
||||
items.push({
|
||||
name: 'MQTT',
|
||||
iconClass: 'fa-cloud',
|
||||
items: [
|
||||
{
|
||||
name: 'Subscribe',
|
||||
owner: owner,
|
||||
iconClass: 'fa-bell',
|
||||
proto: Subscribe,
|
||||
target: target,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Publish',
|
||||
owner: owner,
|
||||
iconClass: 'fa-send',
|
||||
proto: Publish,
|
||||
target: target,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
//tell everyone
|
||||
factory.publish(types.EVENTS.ON_BUILD_BLOCK_INFO_LIST, {
|
||||
items: items,
|
||||
group: 'MQTT'
|
||||
});
|
||||
return items;
|
||||
|
||||
};
|
||||
|
||||
factory._getFileBlocks = function (scope, owner, target, group) {
|
||||
var items = [];
|
||||
items.push({
|
||||
name: 'File',
|
||||
iconClass: 'fa-file',
|
||||
items: [
|
||||
{
|
||||
name: '%%Read JSON',
|
||||
owner: owner,
|
||||
iconClass: 'fa-file',
|
||||
proto: ReadJSON,
|
||||
target: target,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
//tell everyone
|
||||
factory.publish(types.EVENTS.ON_BUILD_BLOCK_INFO_LIST, {
|
||||
items: items,
|
||||
group: 'File'
|
||||
});
|
||||
return items;
|
||||
|
||||
};
|
||||
|
||||
factory._getServerBlocks = function (scope, owner, target, group) {
|
||||
var items = [];
|
||||
items.push({
|
||||
name: 'Server',
|
||||
iconClass: 'el-icon-repeat',
|
||||
items: [
|
||||
{
|
||||
name: 'Run Server Method',
|
||||
owner: owner,
|
||||
iconClass: 'fa-plug',
|
||||
proto: RunServerMethod,
|
||||
target: target,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Shell',
|
||||
owner: owner,
|
||||
iconClass: 'fa-code',
|
||||
proto: Shell,
|
||||
target: target,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
//tell everyone
|
||||
factory.publish(types.EVENTS.ON_BUILD_BLOCK_INFO_LIST, {
|
||||
items: items,
|
||||
group: 'Server'
|
||||
});
|
||||
return items;
|
||||
};
|
||||
factory._getVariableBlocks = function (scope, owner, target, group) {
|
||||
var items = [];
|
||||
items.push({
|
||||
name: 'Flow',
|
||||
iconClass: 'el-icon-random',
|
||||
items: [
|
||||
{
|
||||
name: 'If...Else',
|
||||
owner: owner,
|
||||
iconClass: 'el-icon-fork',
|
||||
proto: IfBlock,
|
||||
target: target,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group,
|
||||
condition: "[value]=='PW'"
|
||||
}
|
||||
}/*,
|
||||
{
|
||||
name:'Switch',
|
||||
owner:owner,
|
||||
iconClass:'el-icon-fork',
|
||||
proto:SwitchBlock,
|
||||
target:target,
|
||||
ctrArgs:{
|
||||
scope:scope,
|
||||
group:group
|
||||
}
|
||||
}
|
||||
*/
|
||||
]
|
||||
});
|
||||
|
||||
return items;
|
||||
};
|
||||
factory._getEventBlocks = function (scope, owner, target, group) {
|
||||
var items = [];
|
||||
items.push({
|
||||
name: 'Events',
|
||||
iconClass: 'fa-bell',
|
||||
items: [
|
||||
{
|
||||
name: 'On Event',
|
||||
owner: owner,
|
||||
iconClass: 'fa-bell',
|
||||
proto: OnEvent,
|
||||
target: target,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'On Key',
|
||||
owner: owner,
|
||||
iconClass: 'fa-keyboard-o',
|
||||
proto: OnKey,
|
||||
target: target,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
//tell everyone
|
||||
factory.publish(types.EVENTS.ON_BUILD_BLOCK_INFO_LIST, {
|
||||
items: items,
|
||||
group: 'Events'
|
||||
});
|
||||
|
||||
return items;
|
||||
};
|
||||
factory._getLoggingBlocks = function (scope, owner, target, group) {
|
||||
var items = [];
|
||||
items.push({
|
||||
name: 'Logging',
|
||||
iconClass: 'fa-bug',
|
||||
items: [
|
||||
{
|
||||
name: 'Log',
|
||||
owner: owner,
|
||||
iconClass: 'fa-bug',
|
||||
proto: Log,
|
||||
target: target,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
//tell everyone
|
||||
factory.publish(types.EVENTS.ON_BUILD_BLOCK_INFO_LIST, {
|
||||
items: items,
|
||||
group: 'Logging'
|
||||
});
|
||||
|
||||
return items;
|
||||
};
|
||||
factory._getCodeBlocks = function (scope, owner, target, group) {
|
||||
var items = [];
|
||||
items.push({
|
||||
name: 'Code',
|
||||
iconClass: 'fa-code',
|
||||
items: [
|
||||
{
|
||||
name: 'Call Method',
|
||||
owner: owner,
|
||||
iconClass: 'el-icon-video',
|
||||
proto: CallMethod,
|
||||
target: target,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Run Script',
|
||||
owner: owner,
|
||||
iconClass: 'fa-code',
|
||||
proto: RunScript,
|
||||
target: target,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Run Block',
|
||||
owner: owner,
|
||||
iconClass: 'fa-code',
|
||||
proto: RunBlock,
|
||||
target: target,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Set Properties',
|
||||
owner: owner,
|
||||
iconClass: 'fa-code',
|
||||
proto: SetProperties,
|
||||
target: target,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
//tell everyone
|
||||
factory.publish(types.EVENTS.ON_BUILD_BLOCK_INFO_LIST, {
|
||||
items: items,
|
||||
group: 'Code'
|
||||
});
|
||||
return items;
|
||||
};
|
||||
factory._getFlowBlocks = function (scope, owner, target, group) {
|
||||
var items = [];
|
||||
items.push({
|
||||
name: 'Flow',
|
||||
iconClass: 'el-icon-random',
|
||||
items: [
|
||||
{
|
||||
name: 'If...Else',
|
||||
owner: owner,
|
||||
iconClass: 'el-icon-fork',
|
||||
proto: IfBlock,
|
||||
target: target,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group,
|
||||
condition: "[value]=='PW'"
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Switch',
|
||||
owner: owner,
|
||||
iconClass: 'el-icon-fork',
|
||||
proto: SwitchBlock,
|
||||
target: target,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Variable Switch',
|
||||
owner: owner,
|
||||
iconClass: 'el-icon-fork',
|
||||
proto: VariableSwitch,
|
||||
target: target,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
//tell everyone
|
||||
factory.publish(types.EVENTS.ON_BUILD_BLOCK_INFO_LIST, {
|
||||
items: items,
|
||||
group: 'Flow'
|
||||
});
|
||||
return items;
|
||||
};
|
||||
factory._getLoopBlocks = function (scope, owner, target, group) {
|
||||
var items = [];
|
||||
items.push({
|
||||
name: 'Loops',
|
||||
iconClass: 'el-icon-repeat',
|
||||
items: [
|
||||
{
|
||||
name: 'While',
|
||||
owner: owner,
|
||||
iconClass: 'el-icon-repeat',
|
||||
proto: WhileBlock,
|
||||
target: target,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group,
|
||||
condition: "[Volume]<=100"
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'For',
|
||||
owner: owner,
|
||||
iconClass: 'el-icon-repeat',
|
||||
proto: ForBlock,
|
||||
target: target,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group,
|
||||
initial: '1',
|
||||
comparator: "<=",
|
||||
"final": '5',
|
||||
modifier: '+1',
|
||||
counterName: 'value'
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
//tell everyone
|
||||
factory.publish(types.EVENTS.ON_BUILD_BLOCK_INFO_LIST, {
|
||||
items: items,
|
||||
group: 'Loops'
|
||||
});
|
||||
return items;
|
||||
};
|
||||
factory._getMathBlocks = function (scope, owner, dstItem, group) {
|
||||
var items = [];
|
||||
items.push({
|
||||
name: 'Math',
|
||||
owner: this,
|
||||
iconClass: 'el-icon-qrcode',
|
||||
dstItem: dstItem,
|
||||
items: [
|
||||
{
|
||||
name: 'If...Else',
|
||||
owner: dstItem,
|
||||
iconClass: 'el-icon-compass',
|
||||
proto: IfBlock,
|
||||
item: dstItem,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
return items;
|
||||
};
|
||||
factory._getTimeBlocks = function (scope, owner, dstItem, group) {
|
||||
var items = [];
|
||||
items.push({
|
||||
name: 'Time',
|
||||
owner: this,
|
||||
iconClass: 'el-icon-qrcode',
|
||||
dstItem: dstItem,
|
||||
items: [
|
||||
{
|
||||
name: 'If...Else',
|
||||
owner: dstItem,
|
||||
iconClass: 'el-icon-time',
|
||||
proto: IfBlock,
|
||||
item: dstItem,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
});
|
||||
return items;
|
||||
};
|
||||
factory._getTransformBlocks = function (scope, owner, dstItem, group) {
|
||||
var items = [];
|
||||
items.push({
|
||||
name: 'Time',
|
||||
owner: this,
|
||||
iconClass: 'el-icon-magic',
|
||||
dstItem: dstItem,
|
||||
items: [
|
||||
{
|
||||
name: 'If...Else',
|
||||
owner: dstItem,
|
||||
iconClass: 'el-icon-time',
|
||||
proto: IfBlock,
|
||||
item: dstItem,
|
||||
ctrArgs: {
|
||||
scope: scope,
|
||||
group: group
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
return items;
|
||||
};
|
||||
return factory;
|
||||
});
|
||||
@ -0,0 +1,88 @@
|
||||
define([
|
||||
'dojo/_base/declare',
|
||||
'dojo/_base/array',
|
||||
'./_Base'
|
||||
],function(declare,array,_Base)
|
||||
{
|
||||
/**
|
||||
* Javascript code generator
|
||||
*/
|
||||
return declare("xblox.generator.Javascript",_Base,
|
||||
{
|
||||
/***
|
||||
* Print a set of variables as Javascript
|
||||
*
|
||||
* Supported modes:
|
||||
*
|
||||
* 1. output variables straight forward as they are, no evaluation
|
||||
* 2. evaluated : means it actually evaluates the variables and then prints the result!
|
||||
* this for now!
|
||||
*
|
||||
* @param scope {xblox.model.Scope}
|
||||
* @param variables {Array}
|
||||
* @param resolve {Boolean}
|
||||
* @returns {string}
|
||||
*/
|
||||
printVariables:function(scope,variables,resolve){
|
||||
|
||||
var result='';
|
||||
for(var i = 0 ; i < variables.length ; i++){
|
||||
|
||||
var _var = variables[i];
|
||||
var _varVal = ''+_var.value;
|
||||
if(_varVal.length==0){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(resolve===true){
|
||||
_varVal = scope.expressionModel.parseVariable(scope,_var);//
|
||||
}
|
||||
|
||||
result+="var " + _var.title + " = " + _varVal + ";";
|
||||
result+="\n";
|
||||
}
|
||||
return result;
|
||||
},
|
||||
/***
|
||||
* Print a set of blocks, in the order as in the array
|
||||
*
|
||||
* Supported modes:
|
||||
* 1. output variables straight forward as they are, no evaluation
|
||||
*
|
||||
* @param scope {xblox.model.Scope}
|
||||
* @param blocks {Array}
|
||||
* @returns {string}
|
||||
*/
|
||||
printBlocks:function(scope,blocks){
|
||||
var result='';
|
||||
for(var i = 0 ; i < blocks.length ; i++){
|
||||
var block = blocks[i];
|
||||
|
||||
|
||||
/***
|
||||
* Variant 1: 'Create the Code here'
|
||||
*/
|
||||
|
||||
//simple example : if block
|
||||
if(block.declaredClass=='xblox.model.logic.IfBlock'){
|
||||
|
||||
//start
|
||||
result+='if(' + block.condition + '){';
|
||||
|
||||
//iterate over blocks in 'consequent'
|
||||
array.forEach(block.consequent,function(item){
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/***
|
||||
* Variant 2: 'Let the block create the code
|
||||
*/
|
||||
result+=block.toCode('Javascript');
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,5 @@
|
||||
define([
|
||||
'dojo/_base/declare'
|
||||
],function(declare){
|
||||
return declare("xblox.generator._Base", null,{});
|
||||
});
|
||||
163
packages/xblox/ref-control-freak/xblox/layer.profile.js
Normal file
163
packages/xblox/ref-control-freak/xblox/layer.profile.js
Normal file
@ -0,0 +1,163 @@
|
||||
/**
|
||||
* This is a new Dojo 1.7 style build profile. Look at util/build/buildControlDefault.js if you want to explore the
|
||||
* default Dojo build profile options.
|
||||
*/
|
||||
|
||||
// This function is used to determine whether or not a resource should be tagged as copy-only. See the resourceTags
|
||||
// property below for more information.
|
||||
function copyOnly(mid) {
|
||||
return mid in {
|
||||
// There are no modules right now in dojo boilerplate that are copy-only. If you have some, though, just add
|
||||
// them here like this:
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
var profile = {
|
||||
packages: [
|
||||
{
|
||||
name:"xblox",
|
||||
location:"xblox"
|
||||
}
|
||||
],
|
||||
// basePath is relative to the directory containing this profile file; in this case, it is being set to the
|
||||
// src/ directory, which is the same place as the baseUrl directory in the loader configuration. (If you change
|
||||
// this, you will also need to update run.js).
|
||||
basePath: '../',
|
||||
|
||||
// This is the directory within the release directory where built packages will be placed. The release directory
|
||||
// itself is defined by build.sh. You really probably should not use this; it is a legacy option from very old
|
||||
// versions of Dojo (like, version 0.1). If you do use it, you will need to update build.sh, too.
|
||||
// releaseName: '',
|
||||
|
||||
// Builds a new release.
|
||||
action: 'release',
|
||||
|
||||
// Strips all comments from CSS files.
|
||||
cssOptimize: 'comments',
|
||||
|
||||
// Excludes tests, demos, and original template files from being included in the built version.
|
||||
mini: true,
|
||||
|
||||
// Uses Closure Compiler as the JavaScript minifier. This can also be set to "shrinksafe" to use ShrinkSafe.
|
||||
// Note that you will probably get some “errors” with CC; these are generally safe to ignore, and will be
|
||||
// fixed in a later version of Dojo. This defaults to "" (no compression) if not provided.
|
||||
optimize: 'closure',
|
||||
|
||||
// We’re building layers, so we need to set the minifier to use for those, too. This defaults to "shrinksafe" if
|
||||
// it is not provided.
|
||||
layerOptimize: 'closure',
|
||||
|
||||
// Strips all calls to console functions within the code. You can also set this to "warn" to strip everything
|
||||
// but console.error, and any other truthy value to strip everything but console.warn and console.error.
|
||||
stripConsole: 'warn',
|
||||
|
||||
// The default selector engine is not included by default in a dojo.js build in order to make mobile builds
|
||||
// smaller. We add it back here to avoid that extra HTTP request. There is also a "lite" selector available; if
|
||||
// you use that, you’ll need to set selectorEngine in app/run.js too. (The "lite" engine is only suitable if you
|
||||
// are not supporting IE7 and earlier.)
|
||||
selectorEngine: 'lite',
|
||||
|
||||
// Builds can be split into multiple different JavaScript files called “layers”. This allows applications to
|
||||
// defer loading large sections of code until they are actually required while still allowing multiple modules to
|
||||
// be compiled into a single file.
|
||||
layers: {
|
||||
// This is the main loader module. It is a little special because it is treated like an AMD module even though
|
||||
// it is actually just plain JavaScript. There is some extra magic in the build system specifically for this
|
||||
// module ID.
|
||||
'xblox/xblox': {
|
||||
exclude:[
|
||||
"dojo/dojo",
|
||||
"xblox/build"
|
||||
],
|
||||
// In addition to the loader (dojo/dojo) and the loader configuration file (app/run), we’re also including
|
||||
// the main application (app/main) and the dojo/i18n and dojo/domReady modules because they are one of the
|
||||
// conditional dependencies in app/main (the other being app/Dialog) but we don’t want to have to make
|
||||
// extra HTTP requests for such tiny files.
|
||||
// By default, the build system will try to include dojo/main in the built dojo/dojo layer, which adds a
|
||||
// bunch of stuff we don’t want or need. We want the initial script load to be as small and quick as
|
||||
// possible, so we configure it as a custom, bootable base.
|
||||
include: [
|
||||
'xblox/main',
|
||||
'xblox/component',
|
||||
'xblox/types/Types',
|
||||
'xblox/embedded',
|
||||
'xblox/embedded_ui',
|
||||
'xblox/views/BlockGrid',
|
||||
'xblox/manager/BlockManagerUI',
|
||||
//'xblox/views/BlockEditDialog',
|
||||
//'xblox/views/BlockTreeView',
|
||||
'xblox/views/BlocksFileEditor',
|
||||
'xblox/model/Block_UI',
|
||||
'xblox/manager/BlockManagerUI',
|
||||
'xblox/RunScript',
|
||||
'xblox/CSSState',
|
||||
'xblox/model/html/SetState',
|
||||
'xblox/views/BlockGridPalette'
|
||||
],
|
||||
boot: false,
|
||||
customBase: false
|
||||
}
|
||||
},
|
||||
|
||||
// Providing hints to the build system allows code to be conditionally removed on a more granular level than
|
||||
// simple module dependencies can allow. This is especially useful for creating tiny mobile builds.
|
||||
// Keep in mind that dead code removal only happens in minifiers that support it! Currently, ShrinkSafe does not
|
||||
// support dead code removal; Closure Compiler and UglifyJS do.
|
||||
staticHasFeatures: {
|
||||
// The trace & log APIs are used for debugging the loader, so we don’t need them in the build
|
||||
'dojo-trace-api':0,
|
||||
'dojo-log-api':0,
|
||||
// This causes normally private loader data to be exposed for debugging, so we don’t need that either
|
||||
'dojo-publish-privates':0,
|
||||
// We’re fully async, so get rid of the legacy loader
|
||||
'dojo-sync-loader':0,
|
||||
// dojo-xhr-factory relies on dojo-sync-loader
|
||||
'dojo-xhr-factory':0,
|
||||
// We aren’t loading tests in production
|
||||
'dojo-test-sniff':0,
|
||||
'xblox-ui':1,
|
||||
'xblox':1,
|
||||
'xreload':1,
|
||||
'xideve':1,
|
||||
'xnode':1
|
||||
},
|
||||
|
||||
// Resource tags are functions that provide hints to the compiler about a given file. The first argument is the
|
||||
// filename of the file, and the second argument is the module ID for the file.
|
||||
resourceTags: {
|
||||
// Files that contain test code.
|
||||
test: function (filename, mid) {
|
||||
if( filename.indexOf('/test')!=-1 ||
|
||||
filename.indexOf('/tests')!=-1 ||
|
||||
filename.indexOf('/out')!=-1 ||
|
||||
filename.indexOf('/bak/')!=-1 ||
|
||||
filename.indexOf('/build')!=-1 ||
|
||||
filename.indexOf('/xblox/bak')!=-1 ||
|
||||
filename.indexOf('/Gruntfile')!=-1
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
// Files that should be copied as-is without being modified by the build system.
|
||||
copyOnly: function (filename, mid) {
|
||||
return copyOnly(mid);
|
||||
},
|
||||
|
||||
// Files that are AMD modules.
|
||||
amd: function (filename, mid) {
|
||||
return !copyOnly(mid) && /\.js$/.test(filename);
|
||||
},
|
||||
|
||||
// Files that should not be copied when the “mini” compiler flag is set to true.
|
||||
miniExclude: function (filename, mid) {
|
||||
return mid in {
|
||||
'XPLUGIN/profile': 1
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
5
packages/xblox/ref-control-freak/xblox/main.js
Normal file
5
packages/xblox/ref-control-freak/xblox/main.js
Normal file
@ -0,0 +1,5 @@
|
||||
define([
|
||||
"dojo/_base/kernel"
|
||||
], function(){
|
||||
return dojo.xblox;
|
||||
});
|
||||
30
packages/xblox/ref-control-freak/xblox/mainr.js
Normal file
30
packages/xblox/ref-control-freak/xblox/mainr.js
Normal file
@ -0,0 +1,30 @@
|
||||
define([
|
||||
"xblox/component",
|
||||
"xblox/embedded",
|
||||
"xblox/model/Block",
|
||||
"xblox/model/logic/CaseBlock",
|
||||
"xblox/model/functions/CallBlock",
|
||||
"xblox/model/code/CallMethod",
|
||||
"xblox/model/code/RunScript",
|
||||
"xblox/model/code/RunBlock",
|
||||
"xblox/model/loops/ForBlock",
|
||||
"xblox/model/loops/WhileBlock",
|
||||
"xblox/model/variables/VariableAssignmentBlock",
|
||||
"xblox/model/logic/IfBlock",
|
||||
"xblox/model/logic/ElseIfBlock",
|
||||
"xblox/model/logic/SwitchBlock",
|
||||
"xblox/model/variables/VariableSwitch",
|
||||
"xblox/model/events/OnEvent",
|
||||
"xblox/model/events/OnKey",
|
||||
"xblox/model/logging/Log",
|
||||
"xblox/model/html/SetStyle",
|
||||
"xblox/model/html/SetCSS",
|
||||
"xblox/model/html/SetState",
|
||||
"xblox/manager/BlockManager",
|
||||
"xblox/factory/Blocks",
|
||||
"xblox/model/Referenced",
|
||||
"xblox/types/Types",
|
||||
"xblox/RunScript",
|
||||
"xblox/CSSState",
|
||||
"xblox/StyleState"
|
||||
], function(){});
|
||||
330
packages/xblox/ref-control-freak/xblox/manager/BlockManager.js
Normal file
330
packages/xblox/ref-control-freak/xblox/manager/BlockManager.js
Normal file
@ -0,0 +1,330 @@
|
||||
define([
|
||||
'dcl/dcl',
|
||||
'dojo/has',
|
||||
'dojo/Deferred',
|
||||
'dojo/promise/all',
|
||||
'xide/types',
|
||||
'xide/utils',
|
||||
'xide/factory',
|
||||
'xblox/model/ModelBase',
|
||||
'xblox/model/Scope',
|
||||
'xblox/model/BlockModel',
|
||||
'xide/mixins/ReloadMixin',
|
||||
'xide/manager/ManagerBase',
|
||||
'xblox/data/Store',
|
||||
"xdojo/has!xblox-ui?xblox/manager/BlockManagerUI",
|
||||
"xide/lodash"
|
||||
],function (dcl,has,Deferred,all,types,utils,factory,ModelBase,Scope,BlockModel,ReloadMixin,ManagerBase,Store,BlockManagerUI,_){
|
||||
|
||||
var bases = has('host-browser') && has("xblox-ui") ? [BlockManagerUI,ManagerBase,ReloadMixin.dcl] : [ManagerBase,ReloadMixin.dcl];
|
||||
var debug = false;
|
||||
|
||||
return dcl(bases,{
|
||||
declaredClass:"xblox/manager/BlockManager",
|
||||
serviceObject:null,
|
||||
loaded:{},
|
||||
test:function(){
|
||||
|
||||
},
|
||||
/***
|
||||
* scope: storage for all registered variables / commands
|
||||
*/
|
||||
scope:null,
|
||||
scopes:null,
|
||||
//track original create block function
|
||||
_createBlock:null,
|
||||
_registerActions:function(){},
|
||||
toScope:function(data){
|
||||
try {
|
||||
data = utils.getJson(data);
|
||||
} catch (e) {
|
||||
console.error('BlockManager::toScope: failed,err='+e);
|
||||
return null;
|
||||
}
|
||||
|
||||
if(!data){
|
||||
console.error('correct data');
|
||||
data = {
|
||||
"blocks": [
|
||||
],
|
||||
"variables": []
|
||||
};
|
||||
}
|
||||
var scopeId = utils.createUUID();
|
||||
var blockInData = data;
|
||||
//check structure
|
||||
if (_.isArray(data)) {// a flat list of blocks
|
||||
|
||||
} else if (_.isObject(data)) {
|
||||
scopeId = data.scopeId || scopeId;
|
||||
blockInData = data.blocks || [];
|
||||
}
|
||||
var scopeUserData = {
|
||||
owner:this
|
||||
};
|
||||
var blockScope = this.getScope(scopeId, scopeUserData, true);
|
||||
var allBlocks = blockScope.blocksFromJson(blockInData);
|
||||
for (var i = 0; i < allBlocks.length; i++) {
|
||||
var obj = allBlocks[i];
|
||||
obj._lastRunSettings = {
|
||||
force: false,
|
||||
highlight: true
|
||||
};
|
||||
}
|
||||
blockScope.serviceObject = this.serviceObject;
|
||||
return blockScope;
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param files{Object[]} array of items to load in this format
|
||||
* @example:
|
||||
* @returns {Deferred.promise}
|
||||
*/
|
||||
loadFiles:function(files){
|
||||
|
||||
var thiz=this,
|
||||
_createDfd = function(mount,path,force,publish)
|
||||
{
|
||||
return thiz.load(mount,path,force);
|
||||
},
|
||||
_promises = [],
|
||||
dfd = new Deferred();
|
||||
|
||||
//build promise chain for 'all'
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var item = files[i];
|
||||
_promises.push(_createDfd(item.mount, item.path, item.force, item.publish));
|
||||
}
|
||||
|
||||
//run and resolve head
|
||||
all(_promises).then(function(results){
|
||||
debug && console.log('got all block files ',results);
|
||||
dfd.resolve(results);
|
||||
});
|
||||
|
||||
return dfd.promise;
|
||||
},
|
||||
load:function(mount,path,forceReload){
|
||||
var dfd = new Deferred(),
|
||||
thiz = this,
|
||||
_mount = utils.replaceAll('/','',mount),
|
||||
_path = utils.replaceAll('./','',path);
|
||||
|
||||
var full = _mount + _path;
|
||||
full = full.trim();
|
||||
|
||||
if(this.loaded[full] && forceReload===true){
|
||||
this.removeScope(this.loaded[full].id);
|
||||
this.loaded[full]=null;
|
||||
}
|
||||
|
||||
if(forceReload !==true && this.loaded[full]){
|
||||
dfd.resolve(this.loaded[full]);
|
||||
return dfd.promise;
|
||||
}
|
||||
var _ready = function(data){
|
||||
var scope = thiz.toScope(data);
|
||||
if(scope){
|
||||
thiz.loaded[full] = scope;
|
||||
|
||||
scope.mount = mount;//track file info
|
||||
scope.path = path;
|
||||
}
|
||||
dfd.resolve(scope);
|
||||
};
|
||||
this.ctx.getFileManager().getContent(_mount,_path,_ready,false);
|
||||
return dfd.promise;
|
||||
},
|
||||
onBlocksReady:function(scope){
|
||||
var blocks = scope.allBlocks();
|
||||
for (var i = 0; i < blocks.length; i++) {
|
||||
var obj = blocks[i];
|
||||
this.setScriptFunctions(obj,scope,this);
|
||||
}
|
||||
/**
|
||||
* pick 'On Load' blocks
|
||||
*/
|
||||
|
||||
var loadBlocks = scope.getBlocks({
|
||||
group:'On Load'
|
||||
});
|
||||
if(loadBlocks && loadBlocks.length>0){
|
||||
for (var i = 0; i < loadBlocks.length; i++) {
|
||||
var loadBlock = loadBlocks[i];
|
||||
if(loadBlock.onLoad){
|
||||
loadBlock.onLoad();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
getBlock:function(){
|
||||
|
||||
},
|
||||
setScriptFunctions:function(obj,scope,owner){
|
||||
|
||||
var thiz=owner;
|
||||
//scope.context = obj;//set the context of the blox scope
|
||||
if(!obj.blockScope) {
|
||||
obj.blockScope = scope;
|
||||
}
|
||||
debug && console.log('set script functions ' + scope.id,obj);
|
||||
scope.serviceObject = this.serviceObject;
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Variables
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Add 'setVariable'
|
||||
* @param title
|
||||
* @param value
|
||||
*/
|
||||
if(!obj.setVariable) {
|
||||
obj.setVariable = function (title, value, save, publish, source) {
|
||||
var _scope = this.blockScope;
|
||||
var _variable = _scope.getVariable(title);
|
||||
if (_variable) {
|
||||
_variable.value = value;
|
||||
debug && console.log('setting variable '+title + ' to ' + value);
|
||||
} else {
|
||||
debug && console.log('no such variable : ' + title);
|
||||
return;
|
||||
}
|
||||
if (publish !== false) {
|
||||
|
||||
thiz.publish(types.EVENTS.ON_VARIABLE_CHANGED, {
|
||||
item: _variable,
|
||||
scope: scope,
|
||||
driver: obj,
|
||||
owner: thiz,
|
||||
save: save === true,
|
||||
source: source || types.MESSAGE_SOURCE.BLOX //for prioritizing
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Add getVariable
|
||||
* @param title
|
||||
*/
|
||||
if(!obj.getVariable) {
|
||||
obj.getVariable = function (title) {
|
||||
var _scope = this.blockScope;
|
||||
var _variable = _scope.getVariable(title);
|
||||
if (_variable) {
|
||||
return _variable.value;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
}
|
||||
|
||||
},
|
||||
hasScope:function(id) {
|
||||
if (!this.scopes) {
|
||||
this.scopes = {};
|
||||
}
|
||||
if (this.scopes[id]) {
|
||||
return this.scopes[id];
|
||||
}
|
||||
return null;
|
||||
},
|
||||
getScope:function(id,userData,publish){
|
||||
if(!this.scopes){
|
||||
this.scopes={};
|
||||
}
|
||||
if(!this.scopes[id]){
|
||||
this.scopes[id]=this.createScope({
|
||||
id:id,
|
||||
ctx:this.ctx
|
||||
});
|
||||
this.scopes[id].userData=userData;
|
||||
if(publish!==false){
|
||||
try{
|
||||
factory.publish(types.EVENTS.ON_SCOPE_CREATED,this.scopes[id]);
|
||||
}catch(e){
|
||||
console.error('bad, scope creation failed ' +e ,e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.scopes[id];
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param id
|
||||
* @returns {null}
|
||||
*/
|
||||
removeScope:function(id){
|
||||
if(!this.scopes){
|
||||
this.scopes={};
|
||||
}
|
||||
for (var scopeId in this.loaded){
|
||||
if(this.loaded[scopeId].id==id){
|
||||
delete this.loaded[scopeId];
|
||||
}
|
||||
}
|
||||
if (this.scopes[id]) {
|
||||
this.scopes[id]._destroy();
|
||||
delete this.scopes[id];
|
||||
}
|
||||
return null;
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param mixed
|
||||
* @param data
|
||||
* @returns {*}
|
||||
*/
|
||||
createScope:function(mixed,data,errorCB){
|
||||
data = data || [];
|
||||
var blockStore = new Store({
|
||||
data: [],
|
||||
Model:BlockModel,
|
||||
id:utils.createUUID(),
|
||||
__events:{
|
||||
|
||||
},
|
||||
observedProperties:[
|
||||
"name",
|
||||
"enabled",
|
||||
"value"
|
||||
],
|
||||
getLabel:function(item){
|
||||
return item.name;
|
||||
},
|
||||
labelAttr:'name'
|
||||
});
|
||||
blockStore.reset();
|
||||
blockStore.setData([]);
|
||||
var args = {
|
||||
owner:this,
|
||||
blockStore:blockStore,
|
||||
serviceObject:this.serviceObject,
|
||||
config:this.config
|
||||
};
|
||||
utils.mixin(args,mixed);
|
||||
try {
|
||||
var scope = new Scope(args);
|
||||
data && scope.initWithData(data,errorCB);
|
||||
scope.init();
|
||||
}catch(e){
|
||||
logError(e,'error creating scope, data:',mixed);
|
||||
}
|
||||
|
||||
return scope;
|
||||
},
|
||||
onReloaded:function(){
|
||||
debug && console.log('on reloaded');
|
||||
},
|
||||
init:function() {
|
||||
this.scope = {
|
||||
variables:[],
|
||||
blocks: []
|
||||
};
|
||||
ModelBase.prototype.types=types;
|
||||
ModelBase.prototype.factory=factory;
|
||||
if(this.onReady){
|
||||
this.onReady();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,14 @@
|
||||
/** module xblox/manager/BlockManagerUI **/
|
||||
define([
|
||||
'dcl/dcl',
|
||||
"xide/manager/BeanManager"
|
||||
], function (dcl, BeanManager) {
|
||||
/**
|
||||
* @mixin module:xblox/manager/BlockManagerUI
|
||||
* @extends {module:xide/manager/BeanManager}
|
||||
*/
|
||||
return dcl(BeanManager, {
|
||||
declaredClass: "xblox/manager/BlockManagerUI",
|
||||
init: function () {}
|
||||
});
|
||||
});
|
||||
70
packages/xblox/ref-control-freak/xblox/min/component.js
Normal file
70
packages/xblox/ref-control-freak/xblox/min/component.js
Normal file
@ -0,0 +1,70 @@
|
||||
define([
|
||||
"dojo/_base/declare",
|
||||
"dojo/has",
|
||||
"xide/model/Component"
|
||||
|
||||
], function (declare,has,Component) {
|
||||
/**
|
||||
* @class xblox.component
|
||||
* @inheritDoc
|
||||
*/
|
||||
return declare([Component], {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
beanType:'BLOCK',
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Implement base interface
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
_load:function(){
|
||||
},
|
||||
hasEditors:function(){
|
||||
return ['xblox'];
|
||||
},
|
||||
getDependencies:function(){
|
||||
if(has('xblox-ui')) {
|
||||
return [
|
||||
'xide/xide',
|
||||
'xblox/types/Types',
|
||||
'xblox/manager/BlockManager',
|
||||
'xblox/manager/BlockManagerUI',
|
||||
'xblox/embedded_ui',
|
||||
'xide/widgets/ExpressionJavaScript',
|
||||
'xide/widgets/ImageWidget',
|
||||
'xide/widgets/Expression',
|
||||
'xide/widgets/ArgumentsWidget',
|
||||
'xide/widgets/RichTextWidget',
|
||||
'xide/widgets/JSONEditorWidget',
|
||||
'xide/widgets/ExpressionEditor',
|
||||
'xide/widgets/WidgetReference',
|
||||
'xide/widgets/DomStyleProperties',
|
||||
'xblox/views/BlocksFileEditor'
|
||||
//'xide/widgets/BlockPickerWidget',
|
||||
//'xide/widgets/BlockSettingsWidget'
|
||||
];
|
||||
}else{
|
||||
return [
|
||||
'xide/xide',
|
||||
'xblox/types/Types',
|
||||
'xblox/manager/BlockManager',
|
||||
'xblox/embedded'
|
||||
];
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getLabel: function () {
|
||||
return 'xblox';
|
||||
},
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getBeanType:function(){
|
||||
return this.beanType;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
0
packages/xblox/ref-control-freak/xblox/min/xblox.js
Normal file
0
packages/xblox/ref-control-freak/xblox/min/xblox.js
Normal file
1036
packages/xblox/ref-control-freak/xblox/model/Block.js
Normal file
1036
packages/xblox/ref-control-freak/xblox/model/Block.js
Normal file
File diff suppressed because it is too large
Load Diff
33
packages/xblox/ref-control-freak/xblox/model/BlockModel.js
Normal file
33
packages/xblox/ref-control-freak/xblox/model/BlockModel.js
Normal file
@ -0,0 +1,33 @@
|
||||
define([
|
||||
'dcl/dcl',
|
||||
'xdojo/declare',
|
||||
'xide/data/Model',
|
||||
'xide/data/Source'
|
||||
], function(dcl,declare,Model,Source){
|
||||
/**
|
||||
* Contains provides implements functions to deal with sub blocks.
|
||||
*/
|
||||
return declare('xblox.model.BlockModel',[Model,Source],{
|
||||
declaredClass:'xblox.model.BlockModel',
|
||||
icon:'fa-play',
|
||||
/**
|
||||
* Store function override
|
||||
* @param parent
|
||||
* @returns {boolean}
|
||||
*/
|
||||
mayHaveChildren: function (parent) {
|
||||
return this.items != null && this.items.length > 0;
|
||||
},
|
||||
/**
|
||||
* Store function override
|
||||
* @param parent
|
||||
* @returns {Array}
|
||||
*/
|
||||
getChildren: function (parent) {
|
||||
return this.items;
|
||||
},
|
||||
getBlockIcon:function(){
|
||||
return '<span class="' +this.icon + '"></span>';
|
||||
}
|
||||
});
|
||||
});
|
||||
424
packages/xblox/ref-control-freak/xblox/model/Block_UI.js
Normal file
424
packages/xblox/ref-control-freak/xblox/model/Block_UI.js
Normal file
@ -0,0 +1,424 @@
|
||||
/** @module xblox/model/Block_UI **/
|
||||
define([
|
||||
'dcl/dcl',
|
||||
"xide/utils",
|
||||
"xide/types",
|
||||
"xide/data/Source",
|
||||
"xaction/ActionProvider"
|
||||
], function (dcl,utils, types,Source,ActionProvider) {
|
||||
/**
|
||||
* All ui - related addons/interfaces for blocks
|
||||
* Please read {@link module:xide/types}
|
||||
* @class module:xblox/model/Block_UI
|
||||
* @lends module:xblox/model/Block
|
||||
*/
|
||||
return dcl([Source.dcl,ActionProvider.dcl],{
|
||||
declaredClass:"xblox.model.Block_UI",
|
||||
_statusIcon:null,
|
||||
/**
|
||||
* hash-map per scope - id
|
||||
*/
|
||||
_statusClass:null,
|
||||
/**
|
||||
* The blocks internal user description
|
||||
* Description is used for the interface. This should be short and expressive and supports plain and html text.
|
||||
*
|
||||
* @todo: same as name, move that in user space, combine that with a template system, so any block ui parts gets off from here!
|
||||
* @type {string}
|
||||
* @default 'No Description'
|
||||
* @required true
|
||||
*/
|
||||
description: 'No Description',
|
||||
/**
|
||||
* UI flag, prevents that a block can be deleted.
|
||||
* @todo, move to block flags
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
canDelete: true,
|
||||
renderBlockIcon: true,
|
||||
/**
|
||||
* Return current status icon
|
||||
* @returns {string|null}
|
||||
*/
|
||||
getStatusIcon:function(){
|
||||
return this._statusIcon;
|
||||
},
|
||||
/**
|
||||
* Returns the stored highlight class per scope-id
|
||||
* @param scopeId {string}
|
||||
* @returns {object|null}
|
||||
*/
|
||||
getStatusClass:function(scopeId){
|
||||
if(this._statusClass){
|
||||
return this._statusClass[scopeId];
|
||||
}
|
||||
return null;
|
||||
},
|
||||
/**
|
||||
* Store the highlight class per scope id
|
||||
* @param scopeId
|
||||
* @param statusClass
|
||||
*/
|
||||
setStatusClass:function(scopeId,statusClass){
|
||||
if(!this._statusClass){
|
||||
this._statusClass = {};
|
||||
}
|
||||
delete this._statusClass[scopeId];
|
||||
statusClass && (this._statusClass[scopeId]=statusClass);
|
||||
},
|
||||
_getText: function (url) {
|
||||
var result;
|
||||
dojo.xhrGet({
|
||||
url: url,
|
||||
sync: true,
|
||||
handleAs: 'text',
|
||||
load: function (text) {
|
||||
result = text;
|
||||
}
|
||||
});
|
||||
return '' + result + '';
|
||||
},
|
||||
/**
|
||||
* implements
|
||||
*/
|
||||
getHelp:function(){
|
||||
},
|
||||
/**
|
||||
* provides
|
||||
* @param which
|
||||
* @param style
|
||||
* @param after
|
||||
* @returns {string}
|
||||
*/
|
||||
getIcon:function(which,style,after){
|
||||
return '<span style="' + (style||"")+'" class="'+which+'"></span> ' + (after || "");
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param field
|
||||
* @param pos
|
||||
* @param type
|
||||
* @param title
|
||||
* @param mode: inline | popup
|
||||
* @returns {string}
|
||||
*/
|
||||
makeEditable2:function(field,pos,type,title,mode){
|
||||
return "<a tabIndex=\"-1\" pos='" + pos +"' display-mode='" + (mode||'popup') + "' display-type='" + (type || 'text') +"' data-prop='" + field + "' data-title='" + title + "' class='editable' href='#'>" + this[field] +"</a>";
|
||||
},
|
||||
makeEditable:function(field,pos,type,title,mode){
|
||||
var editableClass = this.canEdit() ? 'editable' : 'disabled';
|
||||
return "<a data-value='" + this[field] + "' tabIndex='-1' pos='" + pos +"' display-mode='" + (mode||'popup') + "' display-type='" + (type || 'text') +"' data-prop='" + field + "' data-title='" + title + "' class='" +editableClass + "' href='#'>" + this[field] +"</a>";
|
||||
},
|
||||
/**
|
||||
* Called by UI, determines whether a block can be moved up or down
|
||||
* @param item
|
||||
* @param dir
|
||||
* @returns {boolean}
|
||||
*/
|
||||
canMove: function (item, dir) {
|
||||
item = item || this;
|
||||
if (!item) {
|
||||
return false;
|
||||
}
|
||||
var parent = item.getParent(),
|
||||
items = null;
|
||||
if (parent) {
|
||||
items = parent[parent._getContainer(item)];
|
||||
if (!items || items.length < 2 || !this.containsItem(items, item)) {
|
||||
return false;
|
||||
}
|
||||
var cIndex = this.indexOf(items, item);
|
||||
if (cIndex + (dir) < 0) {
|
||||
return false;
|
||||
}
|
||||
var upperItem = items[cIndex + (dir)];
|
||||
if (!upperItem) {
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
var store = this._store;
|
||||
items = store.storage.fullData;
|
||||
var _next = this.next(items,dir);
|
||||
return _next!=null;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
/**
|
||||
* Moves an item up/down in the container list
|
||||
* @param item
|
||||
* @param dir
|
||||
* @returns {boolean}
|
||||
*/
|
||||
move: function (item, dir) {
|
||||
item = item || this;
|
||||
if (!item) {
|
||||
return false;
|
||||
}
|
||||
var parent = item.getParent();
|
||||
var items = null;
|
||||
var store = item._store;
|
||||
if(parent) {
|
||||
items = parent[parent._getContainer(item)];
|
||||
if (!items || items.length < 2 || !this.containsItem(items, item)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var cIndex = this.indexOf(items, item);
|
||||
if (cIndex + (dir) < 0) {
|
||||
return false;
|
||||
}
|
||||
var upperItem = items[cIndex + (dir)];
|
||||
if (!upperItem) {
|
||||
return false;
|
||||
}
|
||||
items[cIndex + (dir)] = item;
|
||||
items[cIndex] = upperItem;
|
||||
return true;
|
||||
|
||||
}else{
|
||||
if(store && item.group){
|
||||
items = store.storage.fullData;
|
||||
}
|
||||
var _dstIndex = 0;
|
||||
var step = 1;
|
||||
function _next(item,items,dir){
|
||||
var cIndex = item.indexOf(items, item);
|
||||
var upperItem = items[cIndex + (dir * step)];
|
||||
if(upperItem){
|
||||
if(!upperItem.parentId && upperItem.group && upperItem.group===item.group){
|
||||
|
||||
_dstIndex = cIndex + (dir * step);
|
||||
return upperItem;
|
||||
}else{
|
||||
step++;
|
||||
return _next(item,items,dir);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
var cIndex = this.indexOf(items, item);
|
||||
if (cIndex + (dir) < 0) {
|
||||
return false;
|
||||
}
|
||||
var next = _next(item,items,dir);
|
||||
if (!next) {
|
||||
return false;
|
||||
}
|
||||
items[_dstIndex]=item;
|
||||
items[cIndex] = next;
|
||||
store._reindex();
|
||||
return true;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* provides
|
||||
* @param block
|
||||
* @param settings
|
||||
* @param event
|
||||
* @param args
|
||||
*/
|
||||
onActivity: function (block, settings, event,args) {
|
||||
args = args || {};
|
||||
args.target = block;
|
||||
this._emit(event, args, block);
|
||||
this.publish(event,args,block);
|
||||
},
|
||||
/**
|
||||
* provides
|
||||
* @param block
|
||||
* @param settings
|
||||
*/
|
||||
onRun: function (block, settings,args) {
|
||||
var highlight = settings && settings.highlight;
|
||||
if (block && highlight) {
|
||||
this.onActivity(block, settings, types.EVENTS.ON_RUN_BLOCK,args);
|
||||
}
|
||||
this._statusIcon = 'text-info fa-spinner fa-spin';
|
||||
},
|
||||
/**
|
||||
* provides
|
||||
* @param block
|
||||
* @param settings
|
||||
* @param args
|
||||
*/
|
||||
onFailed: function (block, settings,args) {
|
||||
var highlight = settings && settings.highlight;
|
||||
if (block && highlight) {
|
||||
this.onActivity(block, settings, types.EVENTS.ON_RUN_BLOCK_FAILED,args);
|
||||
}
|
||||
this._statusIcon = 'text-danger fa-exclamation';
|
||||
},
|
||||
/**
|
||||
* provides
|
||||
* @param block
|
||||
* @param settings
|
||||
* @param args
|
||||
*/
|
||||
onSuccess: function (block, settings,args) {
|
||||
var highlight = settings && settings.highlight;
|
||||
if (block && highlight) {
|
||||
this.onActivity(block, settings, types.EVENTS.ON_RUN_BLOCK_SUCCESS,args);
|
||||
}
|
||||
this._statusIcon = 'text-success fa-check';
|
||||
},
|
||||
/**
|
||||
* implements
|
||||
* @returns {boolean}
|
||||
*/
|
||||
canDisable: function () {
|
||||
return true;
|
||||
},
|
||||
/**
|
||||
* provides defaults
|
||||
* @param icon {boolean=true}
|
||||
* @param share {boolean=true}
|
||||
* @param outlets {boolean=true}
|
||||
* @returns {Array}
|
||||
*/
|
||||
getDefaultFields: function (icon,share,outlets) {
|
||||
var fields = [];
|
||||
if (this.canDisable && this.canDisable() !== false) {
|
||||
fields.push(
|
||||
utils.createCI('enabled', 0, this.enabled, {
|
||||
group: 'General',
|
||||
title: 'Enabled',
|
||||
dst: 'enabled',
|
||||
actionTarget:'value',
|
||||
order:210
|
||||
})
|
||||
);
|
||||
}
|
||||
fields.push(utils.createCI('description', 26, this.description, {
|
||||
group: 'Description',
|
||||
title: 'Description',
|
||||
dst: 'description',
|
||||
useACE: false
|
||||
}));
|
||||
|
||||
icon!==false && fields.push(utils.createCI('icon', 17, this.icon, {
|
||||
group: 'General',
|
||||
title: 'Icon',
|
||||
dst: 'icon',
|
||||
useACE: false,
|
||||
order:206
|
||||
}));
|
||||
|
||||
outlets!==false && fields.push(utils.createCI('outlet', 5, this.outlet, {
|
||||
group: 'Special',
|
||||
title: 'Type',
|
||||
dst: 'outlet',
|
||||
order:205,
|
||||
data:[
|
||||
{
|
||||
value: 0x00000001,
|
||||
label: 'Progress',
|
||||
title: 'Executed when progress'
|
||||
},
|
||||
{
|
||||
value: 0x00000002,
|
||||
label: 'Error',
|
||||
title: "Executed when errors"
|
||||
},
|
||||
{
|
||||
value: 0x00000004,
|
||||
label: 'Paused',
|
||||
title: "Executed when paused"
|
||||
},
|
||||
{
|
||||
value: 0x00000008,
|
||||
label: 'Finish',
|
||||
title: "Executed when finish"
|
||||
},
|
||||
{
|
||||
value: 0x00000010,
|
||||
label: 'Stopped',
|
||||
title: "Executed when stopped"
|
||||
}
|
||||
],
|
||||
widget:{
|
||||
hex:true
|
||||
}
|
||||
}));
|
||||
if (this.sharable) {
|
||||
fields.push(
|
||||
utils.createCI('enabled', 13, this.shareTitle, {
|
||||
group: 'Share',
|
||||
title: 'Title',
|
||||
dst: 'shareTitle',
|
||||
toolTip: 'Enter an unique name to share this block!'
|
||||
})
|
||||
);
|
||||
}
|
||||
return fields;
|
||||
},
|
||||
/**
|
||||
* implements
|
||||
* @returns {*|Array}
|
||||
*/
|
||||
getFields: function () {
|
||||
return this.getDefaultFields();
|
||||
},
|
||||
/**
|
||||
* util
|
||||
* @param str
|
||||
* @returns {*}
|
||||
*/
|
||||
toFriendlyName: function (str) {
|
||||
var special = ["[", "]", "(", ")", "{", "}"];
|
||||
for (var n = 0; n < special.length; n++) {
|
||||
str = str.replace(special[n], '');
|
||||
}
|
||||
str = utils.replaceAll('==', ' equals ', str);
|
||||
str = utils.replaceAll('<', ' is less than ', str);
|
||||
str = utils.replaceAll('=<', ' is less than ', str);
|
||||
str = utils.replaceAll('>', ' is greater than ', str);
|
||||
str = utils.replaceAll('>=', ' is greater than ', str);
|
||||
str = utils.replaceAll("'", '', str);
|
||||
return str;
|
||||
},
|
||||
/**
|
||||
* implements
|
||||
* @returns {string}
|
||||
*/
|
||||
getIconClass: function () {
|
||||
return this.icon;
|
||||
},
|
||||
/**
|
||||
* implements
|
||||
* @param symbol
|
||||
* @returns {string}
|
||||
*/
|
||||
getBlockIcon: function (symbol) {
|
||||
symbol = symbol || '';
|
||||
return this.renderBlockIcon == true ? '<span class="xBloxIcon ' + this.icon + '">' + symbol + '</span>' : '';
|
||||
},
|
||||
/**
|
||||
* provides
|
||||
* @param block
|
||||
* @param cis
|
||||
*/
|
||||
onFieldsRendered: function (block, cis) {
|
||||
},
|
||||
/**
|
||||
* inherited
|
||||
* @param field
|
||||
* @param newValue
|
||||
*/
|
||||
onChangeField: function (field, newValue) {
|
||||
if (field == 'enabled') {
|
||||
if (newValue == true) {
|
||||
this.activate();
|
||||
} else {
|
||||
this.deactivate();
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* implements
|
||||
*/
|
||||
destroy:function(){
|
||||
this.setStatusClass(this.getScope().id,null);
|
||||
}
|
||||
});
|
||||
});
|
||||
107
packages/xblox/ref-control-freak/xblox/model/Contains.js
Normal file
107
packages/xblox/ref-control-freak/xblox/model/Contains.js
Normal file
@ -0,0 +1,107 @@
|
||||
define([
|
||||
'dcl/dcl',
|
||||
"dojo/promise/all",
|
||||
"xide/types"
|
||||
], function (dcl, all, types) {
|
||||
/**
|
||||
* Contains provides implements functions to deal with sub blocks.
|
||||
*/
|
||||
return dcl(null, {
|
||||
declaredClass: 'xblox.model.Contains',
|
||||
runByType: function (outletType, settings) {
|
||||
var items = this.getItemsByType(outletType);
|
||||
if (items.length) {
|
||||
this.runFrom(items, 0, settings);
|
||||
}
|
||||
},
|
||||
getItemsByType: function (outletType) {
|
||||
var items = this.items;
|
||||
if (!outletType) {
|
||||
return items;
|
||||
}
|
||||
var result = [];
|
||||
_.each(items, function (item) {
|
||||
if (item.outlet & outletType) {
|
||||
result.push(item);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
},
|
||||
getContainer: function () {
|
||||
return this[this._getContainer()];
|
||||
},
|
||||
/**
|
||||
* Store is asking this!
|
||||
* @param parent
|
||||
* @returns {boolean}
|
||||
*/
|
||||
mayHaveChildren: function (parent) {
|
||||
var items = this[this._getContainer()];
|
||||
return items != null && items.length > 0;
|
||||
},
|
||||
/**
|
||||
* Store function
|
||||
* @param parent
|
||||
* @returns {Array}
|
||||
*/
|
||||
getChildren: function (parent) {
|
||||
return this[this._getContainer()];
|
||||
},
|
||||
// standard call from interface
|
||||
canAdd: function () {
|
||||
return [];
|
||||
},
|
||||
/***
|
||||
* Generic: run sub blocks
|
||||
* @param scope
|
||||
* @param settings
|
||||
* @param run
|
||||
* @param error
|
||||
* @returns {Array}
|
||||
*/
|
||||
_solve: function (scope, settings, run, error) {
|
||||
if (!this._lastRunSettings && settings) {
|
||||
this._lastRunSettings = settings;
|
||||
}
|
||||
settings = this._lastRunSettings || settings;
|
||||
this._currentIndex = 0;
|
||||
this._return = [];
|
||||
var ret = [], items = this[this._getContainer()];
|
||||
if (items.length) {
|
||||
var res = this.runFrom(items, 0, settings);
|
||||
this.onSuccess(this, settings);
|
||||
return res;
|
||||
} else {
|
||||
this.onSuccess(this, settings);
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
onDidRunItem: function (dfd, result) {
|
||||
this._emit(types.EVENTS.ON_RUN_BLOCK_SUCCESS, this);
|
||||
dfd.resolve(result);
|
||||
},
|
||||
onDidRunItemError: function (dfd, result) {
|
||||
dfd.reject(result);
|
||||
},
|
||||
onRunThis: function () {
|
||||
this._emit(types.EVENTS.ON_RUN_BLOCK, this);
|
||||
},
|
||||
onDidRunThis: function (dfd, result, items, settings) {
|
||||
var thiz = this;
|
||||
//more blocks?
|
||||
if (items && items.length) {
|
||||
var subDfds = thiz.runFrom(items, 0, settings);
|
||||
all(subDfds).then(function () {
|
||||
thiz.onDidRunItem(dfd, result, settings);
|
||||
}, function (err) {
|
||||
thiz.onDidRunItem(dfd, err, settings);
|
||||
});
|
||||
|
||||
} else {
|
||||
thiz.onDidRunItem(dfd, result, settings);
|
||||
}
|
||||
},
|
||||
___solve: function (scope, settings, run, error) {
|
||||
}
|
||||
});
|
||||
});
|
||||
251
packages/xblox/ref-control-freak/xblox/model/Expression.js
Normal file
251
packages/xblox/ref-control-freak/xblox/model/Expression.js
Normal file
@ -0,0 +1,251 @@
|
||||
/** @module xblox/model/Expression */
|
||||
define([
|
||||
"xdojo/declare",
|
||||
"xdojo/has",
|
||||
"xide/utils",
|
||||
"xide/types",
|
||||
"xblox/model/ModelBase"
|
||||
], function (declare, has, utils, types, ModelBase, tracer, _console) {
|
||||
'use strict';
|
||||
var isServer = has('host-node');
|
||||
var console = typeof window !== 'undefined' ? window.console : global.console;
|
||||
if (isServer && tracer && console && console.error) {
|
||||
console = _console;
|
||||
}
|
||||
var _debug = false;
|
||||
/**
|
||||
* The expression
|
||||
* @class module:xblox.model.Expression
|
||||
* @extends module:xblox/model/ModelBase
|
||||
*/
|
||||
return declare("xblox.model.Expression", [ModelBase], {
|
||||
id: null,
|
||||
context: null,
|
||||
// Constants
|
||||
variableDelimiters: {
|
||||
begin: "[",
|
||||
end: "]"
|
||||
},
|
||||
blockCallDelimiters: {
|
||||
begin: "{",
|
||||
end: "}"
|
||||
},
|
||||
expressionCache: null,
|
||||
variableFuncCache: null,
|
||||
constructor: function () {
|
||||
this.reset();
|
||||
},
|
||||
reset: function () {
|
||||
this.expressionCache = {};
|
||||
this.variableFuncCache = {};
|
||||
},
|
||||
/**
|
||||
* Replace variable calls width variable values
|
||||
* @param scope
|
||||
* @param expression
|
||||
* @param _evaluate
|
||||
* @param _escape
|
||||
* @param variableOverrides
|
||||
* @returns {*}
|
||||
*/
|
||||
replaceVariables: function (scope, expression, _evaluate, _escape, variableOverrides, useVariableGetter, variableDelimiters, flags) {
|
||||
var FLAG = types.CIFLAG;
|
||||
variableDelimiters = variableDelimiters || this.variableDelimiters;
|
||||
flags = flags || FLAG.NONE;
|
||||
if (flags & FLAG.DONT_ESCAPE) {
|
||||
_escape = false;
|
||||
}
|
||||
if (flags & FLAG.DONT_PARSE) {
|
||||
_evaluate = false;
|
||||
}
|
||||
var occurrence = this.findOccurrences(expression, variableDelimiters);
|
||||
if (occurrence) {
|
||||
for (var n = 0; n < occurrence.length; n++) {
|
||||
// Replace each variable call width the variable value
|
||||
var oc = occurrence[n];
|
||||
oc = oc.replace(variableDelimiters.begin, '');
|
||||
oc = oc.replace(variableDelimiters.end, '');
|
||||
var _var = this._getVar(scope, oc);
|
||||
if (_var && _var.flags & FLAG.DONT_PARSE) {
|
||||
_evaluate = false;
|
||||
}
|
||||
var value = null;
|
||||
if (_var) {
|
||||
if (useVariableGetter) {
|
||||
expression = expression.replace(occurrence[n], 'this.getVariable(\'' + _var.name + '\')');
|
||||
continue;
|
||||
}
|
||||
value = this.getValue(_var.value);
|
||||
if (variableOverrides && _var.name in variableOverrides) {
|
||||
value = variableOverrides[_var.name];
|
||||
}
|
||||
if (this.isScript(value) && _evaluate !== false) {
|
||||
try {
|
||||
//put other variables on the stack: should be avoided
|
||||
var _otherVariables = scope.variablesToJavascript(_var, true);
|
||||
if (_otherVariables) {
|
||||
value = _otherVariables + value;
|
||||
}
|
||||
var _parsed = (new Function("{\n" + value + "\n}")).call(scope.context || {});
|
||||
//wasnt a script
|
||||
if (_parsed === 'undefined' || typeof _parsed === 'undefined') {
|
||||
value = '' + _var.value;
|
||||
} else {
|
||||
value = _parsed;
|
||||
!(flags & FLAG.DONT_ESCAPE) && (value = "'" + value + "'");
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(' parsed variable expression failed \n' + value, e);
|
||||
}
|
||||
} else {
|
||||
if (!this.isNumber(value)) {
|
||||
if (_escape !== false) {
|
||||
value = "'" + value + "'";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_debug && console.log(' expression failed, no such variable :' + occurrence[n] + ' ! setting to default ' + '');
|
||||
value = occurrence[n];
|
||||
}
|
||||
expression = expression.replace(occurrence[n], value);
|
||||
}
|
||||
}
|
||||
return expression;
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param scope
|
||||
* @param expression
|
||||
* @param addVariables
|
||||
* @param runCallback
|
||||
* @param errorCallback
|
||||
* @param context
|
||||
* @param variableOverrides
|
||||
* @param args {[*]}
|
||||
* @param flags {CIFLAGS}
|
||||
* @returns {*}
|
||||
*/
|
||||
parse: function (scope, expression, addVariables, runCallback, errorCallback, context, variableOverrides, args, flags) {
|
||||
expression = this.replaceAll("''", "'", expression);
|
||||
var expressionContext = context || scope.context || scope.getContext() || {};
|
||||
var useVariableGetter = expressionContext['getVariable'] != null;
|
||||
expression = this.replaceVariables(scope, expression, null, null, variableOverrides, useVariableGetter, null, flags);
|
||||
var isExpression = this.isScript(expression);
|
||||
if (!isExpression && (this.isString(expression) || this.isNumber(expression))) {
|
||||
if (runCallback) {
|
||||
runCallback('Expression ' + expression + ' evaluates to ' + expression);
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
if (expression.indexOf('return') == -1 && isExpression) {
|
||||
expression = 'return ' + expression;
|
||||
}
|
||||
addVariables = false;
|
||||
if (addVariables === true) {
|
||||
var _otherVariables = scope.variablesToJavascript(null, expression);
|
||||
if (_otherVariables) {
|
||||
expression = _otherVariables + expression;
|
||||
expression = this.replaceAll("''", "'", expression);//weird!
|
||||
}
|
||||
}
|
||||
var parsed = this;
|
||||
try {
|
||||
expression = this.replaceAll("''", "'", expression);
|
||||
var _function = this.expressionCache[expression];
|
||||
if (!_function) {
|
||||
_debug && console.log('create function ' + expression);
|
||||
_function = new Function("{" + expression + "; }");
|
||||
this.expressionCache[expression] = _function;
|
||||
} else {
|
||||
|
||||
}
|
||||
parsed = _function.apply(expressionContext, args);
|
||||
} catch (e) {
|
||||
console.error('invalid expression : \n' + expression, e);
|
||||
if (errorCallback) {
|
||||
errorCallback('invalid expression : \n' + expression + ': ' + e, e);
|
||||
}
|
||||
parsed = '' + expression;
|
||||
return parsed;
|
||||
}
|
||||
if (parsed === true) {
|
||||
_debug && console.log('expression return true! : ' + expression);
|
||||
}
|
||||
|
||||
if (runCallback) {
|
||||
runCallback('Expression ' + expression + ' evaluates to ' + parsed);
|
||||
}
|
||||
return parsed;
|
||||
},
|
||||
parseVariable: function (scope, _var, _prefix, escape, allowCache, context, args) {
|
||||
var value = '' + _var.value;
|
||||
_prefix = _prefix || '';
|
||||
if (allowCache !== false) {
|
||||
var _function = this.variableFuncCache[scope.id + '|' + _var.title];
|
||||
if (!_function) {
|
||||
_function = new Function("{" + _prefix + value + "}");
|
||||
this.variableFuncCache[scope.id + '|' + _var.title] = _function;
|
||||
}
|
||||
} else {
|
||||
_function = new Function("{" + _prefix + value + "}");
|
||||
}
|
||||
var _parsed = _function.apply(context || scope.context || {}, args || []);
|
||||
if (_parsed === 'undefined' || typeof _parsed === 'undefined') {
|
||||
value = '' + _var.value;
|
||||
} else {
|
||||
if (!this.isNumber(_parsed) && escape !== false) {
|
||||
value = '' + _parsed;
|
||||
value = "'" + value + "'";
|
||||
} else {
|
||||
value = _parsed;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
},
|
||||
// Replace block call with block result
|
||||
replaceBlockCalls: function (scope, expression) {
|
||||
var occurrences = this.findOccurrences(expression, this.blockCallDelimiters);
|
||||
if (occurrences) {
|
||||
for (var n = 0; n < occurrences.length; n++) {
|
||||
// Replace each block call with block result
|
||||
var blockName = this._removeDelimiters(occurrences[n], this.blockCallDelimiters);
|
||||
var blockResult = scope.solveBlock(blockName).join("\n");
|
||||
expression = expression.replace(occurrences[n], blockResult);
|
||||
}
|
||||
}
|
||||
return expression;
|
||||
},
|
||||
// gets a variable from the scope using text [variableName]
|
||||
_getVar: function (scope, string) {
|
||||
return scope.getVariable(this._getVarName(string));
|
||||
},
|
||||
_getVarName: function (string) {
|
||||
return this._removeDelimiters(string, this.variableDelimiters);
|
||||
},
|
||||
_removeDelimiters: function (text, delimiters) {
|
||||
return text.replace(delimiters.begin, '').replace(delimiters.end, '');
|
||||
},
|
||||
// escape regular expressions special chars
|
||||
_escapeRegExp: function (string) {
|
||||
var special = ["[", "]", "(", ")", "{", "}", "*", "+", "."];
|
||||
for (var n = 0; n < special.length; n++) {
|
||||
string = string.replace(special[n], "\\" + special[n]);
|
||||
}
|
||||
return string;
|
||||
},
|
||||
/**
|
||||
* Finds a term in an expression by start and end delimiters
|
||||
* @param expression
|
||||
* @param delimiters
|
||||
* @private
|
||||
*/
|
||||
findOccurrences: function (expression, delimiters) {
|
||||
var d = {
|
||||
begin: this._escapeRegExp(delimiters.begin),
|
||||
end: this._escapeRegExp(delimiters.end)
|
||||
};
|
||||
return expression.match(new RegExp(d.begin + "(" + "[^" + d.end + "]*" + ")" + d.end, 'g'));
|
||||
}
|
||||
});
|
||||
});
|
||||
177
packages/xblox/ref-control-freak/xblox/model/File/ReadJSON.js
Normal file
177
packages/xblox/ref-control-freak/xblox/model/File/ReadJSON.js
Normal file
@ -0,0 +1,177 @@
|
||||
/** @module xblox/model/File/ReadJSON **/
|
||||
define([
|
||||
'dcl/dcl',
|
||||
"dojo/Deferred",
|
||||
"xblox/model/Block",
|
||||
'xide/utils',
|
||||
'xblox/model/Contains',
|
||||
'xide/types',
|
||||
"xdojo/has!xblox-ui?xfile/data/DriverStore",
|
||||
'xdojo/has!xblox-ui?xfile/views/FileGridLight'
|
||||
], function (dcl, Deferred, Block, utils, Contains, types, DriverStore, FileGridLight) {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param ext
|
||||
* @param config
|
||||
* @param options
|
||||
* @param fileServer
|
||||
* @returns {*}
|
||||
*/
|
||||
function createStore(ext,options,fileServer) {
|
||||
return new DriverStore({
|
||||
data: [],
|
||||
config: {},
|
||||
mount: 'none',
|
||||
options: options,
|
||||
driver: fileServer,
|
||||
micromatch: "(*.json)|!(*.*)", // Only folders and json files
|
||||
//micromatch: "(*.mp3)|(*.wav)|(*.webm)|!(*.*)", // Only folders and json files
|
||||
glob: ext
|
||||
});
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @class module:xblox/model/code/RunScript
|
||||
* @extends module:xblox/model/Block
|
||||
* @augments module:xblox/model/Block_UI
|
||||
*/
|
||||
return dcl([Block, Contains], {
|
||||
declaredClass: "xblox.model.File.ReadJSON",
|
||||
name: 'Read JSON',
|
||||
deferred: false,
|
||||
sharable: false,
|
||||
context: null,
|
||||
icon: 'fa-file',
|
||||
observed: [
|
||||
'path'
|
||||
],
|
||||
getContext: function () {
|
||||
return this.context || (this.scope.getContext ? this.scope.getContext() : this);
|
||||
},
|
||||
getFileContent: function (path) {
|
||||
var scope = this.getScope();
|
||||
var ctx = scope.ctx;
|
||||
var deviceManager = ctx.getDeviceManager();
|
||||
var fileServer = deviceManager.getInstanceByName('File-Server');
|
||||
return fileServer.callCommand('GetProg', {
|
||||
override: {
|
||||
args: [path]
|
||||
}
|
||||
});
|
||||
},
|
||||
processJSON: function (data, settings) {
|
||||
var path = this.jsonPath;
|
||||
if (path) {
|
||||
this._lastResult = utils.getAt(data, path);
|
||||
} else {
|
||||
this._lastResult = data;
|
||||
}
|
||||
this.onSuccess(this, settings);
|
||||
this.runByType(types.BLOCK_OUTLET.FINISH, settings);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param scope
|
||||
* @param settings
|
||||
* @param isInterface
|
||||
* @param run
|
||||
* @param error
|
||||
* @returns {Deferred}
|
||||
*/
|
||||
solve: function (scope, settings, isInterface, run, error) {
|
||||
this._currentIndex = 0;
|
||||
this._return = [];
|
||||
settings = this._lastSettings = settings || this._lastSettings || {};
|
||||
var _script = ('' + this._get('path')),
|
||||
thiz = this,
|
||||
dfd = new Deferred(),
|
||||
self = this;
|
||||
|
||||
this.onRunThis(settings);
|
||||
var expression = scope.expressionModel.replaceVariables(scope, _script, null, null);
|
||||
var getDfd = this.getFileContent(expression);
|
||||
getDfd.then(function (data) {
|
||||
var content = data.content;
|
||||
if (content) {
|
||||
content = utils.getJson(content, true);
|
||||
if (content) {
|
||||
self.processJSON(content, settings);
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
try {
|
||||
if (run) {
|
||||
run('Expression ' + _script + ' evaluates to ' + expression);
|
||||
}
|
||||
} catch (e) {
|
||||
thiz.onDidRunItemError(dfd, e, settings);
|
||||
thiz.onFailed(thiz, settings);
|
||||
if (error) {
|
||||
error('invalid expression : \n' + _script + ': ' + e);
|
||||
}
|
||||
}
|
||||
return dfd;
|
||||
},
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UI impl.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
toText: function () {
|
||||
var result = '<span style="">' + this.getBlockIcon() + ' ' + this.name + ' :: ' + '</span>';
|
||||
if (this.path) {
|
||||
result += this.path.substr(0, 50);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
// standard call from interface
|
||||
canAdd: function () {
|
||||
return [];
|
||||
},
|
||||
// standard call for editing
|
||||
getFields: function () {
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
var scope = this.getScope();
|
||||
var ctx = scope.ctx;
|
||||
var deviceManager = ctx.getDeviceManager();
|
||||
var fileServer = deviceManager.getInstanceByName('File-Server');//system's default
|
||||
var permissions = utils.clone(types.DEFAULT_FILE_GRID_PERMISSIONS);
|
||||
if (fileServer && DriverStore) {
|
||||
var FilePickerOptions = {
|
||||
ctx: ctx,
|
||||
owner: this,
|
||||
selection: '/',
|
||||
resizeToParent: true,
|
||||
Module: FileGridLight,
|
||||
permissions: permissions
|
||||
},
|
||||
options = {
|
||||
fields: types.FIELDS.SHOW_ISDIR | types.FIELDS.SHOW_OWNER | types.FIELDS.SHOW_SIZE |
|
||||
types.FIELDS.SHOW_FOLDER_SIZE |
|
||||
types.FIELDS.SHOW_MIME |
|
||||
types.FIELDS.SHOW_PERMISSIONS |
|
||||
types.FIELDS.SHOW_TIME |
|
||||
types.FIELDS.SHOW_MEDIA_INFO
|
||||
};
|
||||
FilePickerOptions.leftStore = createStore("/*",options,fileServer);
|
||||
FilePickerOptions.rightStore = createStore("/*",options,fileServer);
|
||||
fields.push(utils.createCI('path', 4, this.path, {
|
||||
group: 'General',
|
||||
title: 'Path',
|
||||
dst: 'path',
|
||||
filePickerOptions: FilePickerOptions,
|
||||
widget: {
|
||||
item: this
|
||||
}
|
||||
}));
|
||||
}
|
||||
fields.push(utils.createCI('jsonPath', 13, this.jsonPath, {
|
||||
group: 'General',
|
||||
title: 'Select',
|
||||
dst: 'jsonPath'
|
||||
}));
|
||||
return fields;
|
||||
}
|
||||
});
|
||||
});
|
||||
168
packages/xblox/ref-control-freak/xblox/model/ModelBase.js
Normal file
168
packages/xblox/ref-control-freak/xblox/model/ModelBase.js
Normal file
@ -0,0 +1,168 @@
|
||||
/** @module xblox/model/ModelBase
|
||||
* @description The base for block related classes, this must be kept small and light as possible
|
||||
*/
|
||||
define([
|
||||
'dcl/dcl',
|
||||
"xide/utils",
|
||||
"xide/types",
|
||||
"xide/mixins/EventedMixin",
|
||||
"xide/lodash"
|
||||
], function(dcl,utils,types,EventedMixin,_){
|
||||
/**
|
||||
* The model mixin for a block
|
||||
* @class module:xblox.model.ModelBase
|
||||
*/
|
||||
var Module = dcl(EventedMixin.dcl,{
|
||||
declaredClass:'xblox.model.ModelBase',
|
||||
id:null,
|
||||
description:'',
|
||||
parent:null,
|
||||
parentId:null,
|
||||
group:null,
|
||||
order:0,
|
||||
_store:null,
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Functions to expose out & in - lets
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
/**
|
||||
*
|
||||
* Implmented by the subclass. Each block must provide an output signature.
|
||||
* The format is currently the same as Dojo SMD
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
outputs:function(){
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
* Implemented by the subclass. Each block must provide an input signature.
|
||||
* The format is currently the same as Dojo SMD
|
||||
* @returns {Array}
|
||||
*/
|
||||
takes:function(){
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
* Implemented by the subclass. Each block must provide an needed input signature.
|
||||
* The format is currently the same as Dojo SMD. This is a filtered version of
|
||||
* 'takes'
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
needs:function(){
|
||||
return [];
|
||||
},
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Functions to expose outlets
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
/***
|
||||
* Standard constructor for all sub classing blocks
|
||||
* @param {array} args
|
||||
*/
|
||||
constructor: function(args){
|
||||
//simple mixin of constructor arguments
|
||||
for (var prop in args) {
|
||||
if (args.hasOwnProperty(prop)) {
|
||||
this[prop] = args[prop];
|
||||
}
|
||||
}
|
||||
if(!this.id){
|
||||
this.id = this.createUUID();
|
||||
}
|
||||
//short cuts
|
||||
this.utils=utils;
|
||||
this.types=types;
|
||||
},
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Standard tools
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
keys: function (a) {
|
||||
var b = [];
|
||||
for (var c in a) {
|
||||
b.push(c);
|
||||
}
|
||||
return b;
|
||||
},
|
||||
values: function (b) {
|
||||
var a = [];
|
||||
for (var c in b) {
|
||||
a.push(b[c]);
|
||||
}
|
||||
return a;
|
||||
},
|
||||
toArray: function () {
|
||||
return this.map();
|
||||
},
|
||||
size: function () {
|
||||
return this.toArray().length;
|
||||
},
|
||||
createUUID:utils.createUUID,
|
||||
canEdit:function(){
|
||||
return true;
|
||||
},
|
||||
getFields:function(){
|
||||
return null;
|
||||
},
|
||||
isString: function (a) {
|
||||
return typeof a == "string"
|
||||
},
|
||||
isNumber: function (a) {
|
||||
return typeof a == "number"
|
||||
},
|
||||
isBoolean: function (a) {
|
||||
return typeof a == "boolean"
|
||||
},
|
||||
isObject:_.isObject,
|
||||
isArray:_.isArray,
|
||||
getValue:function(val){
|
||||
var _float = parseFloat(val);
|
||||
if(!isNaN(_float)){
|
||||
return _float;
|
||||
}
|
||||
if(val==='true' || val===true){
|
||||
return true;
|
||||
}
|
||||
if(val==='false' || val===false){
|
||||
return false;
|
||||
}
|
||||
return val;
|
||||
},
|
||||
isScript:function(val){
|
||||
return this.isString(val) &&(
|
||||
val.indexOf('return')!=-1||
|
||||
val.indexOf(';')!=-1||
|
||||
val.indexOf('(')!=-1||
|
||||
val.indexOf('+')!=-1||
|
||||
val.indexOf('-')!=-1||
|
||||
val.indexOf('<')!=-1||
|
||||
val.indexOf('*')!=-1||
|
||||
val.indexOf('/')!=-1||
|
||||
val.indexOf('%')!=-1||
|
||||
val.indexOf('=')!=-1||
|
||||
val.indexOf('==')!=-1||
|
||||
val.indexOf('>')!=-1||
|
||||
val.indexOf('[')!=-1||
|
||||
val.indexOf('{')!=-1||
|
||||
val.indexOf('}')!=-1
|
||||
);
|
||||
},
|
||||
replaceAll:function(find, replace, str) {
|
||||
if(this.isString(str)){
|
||||
return str.split(find).join(replace);
|
||||
}
|
||||
return str;
|
||||
},
|
||||
isInValidState:function(){
|
||||
return true;
|
||||
},
|
||||
destroy:function(){}
|
||||
});
|
||||
dcl.chainAfter(Module,'destroy');
|
||||
return Module;
|
||||
});
|
||||
11
packages/xblox/ref-control-freak/xblox/model/Reference.js
Normal file
11
packages/xblox/ref-control-freak/xblox/model/Reference.js
Normal file
@ -0,0 +1,11 @@
|
||||
define([
|
||||
"dojo/_base/declare",
|
||||
"xide/utils"
|
||||
], function(declare,utils){
|
||||
/**
|
||||
* Holds information to locate an object by string or direct reference!
|
||||
*/
|
||||
return declare('xblox.model.Reference',null,{
|
||||
reference:null
|
||||
});
|
||||
});
|
||||
35
packages/xblox/ref-control-freak/xblox/model/Referenced.js
Normal file
35
packages/xblox/ref-control-freak/xblox/model/Referenced.js
Normal file
@ -0,0 +1,35 @@
|
||||
define([
|
||||
'dcl/dcl',
|
||||
"dojo/_base/declare",
|
||||
"xide/mixins/ReferenceMixin",
|
||||
"xide/utils"
|
||||
], function (dcl,declare, ReferenceMixin,utils) {
|
||||
var Implementation = {
|
||||
/**
|
||||
* JSON String in that format : reference(string) | mode (string)
|
||||
*/
|
||||
reference: null,
|
||||
/**
|
||||
* 'reference' is a JSON structure
|
||||
* @param value
|
||||
* @returns {*}
|
||||
*/
|
||||
deserialize: function (value) {
|
||||
if (!value || value.length == 0) {
|
||||
return {};
|
||||
}
|
||||
try {
|
||||
return utils.fromJson(value);
|
||||
} catch (e) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Holds information to locate an object by string or direct reference.
|
||||
* This must be used as mixin rather as base class!
|
||||
*/
|
||||
var Module = declare('xblox.model.Referenced', [ReferenceMixin],Implementation);
|
||||
Module.dcl = dcl(ReferenceMixin.dcl,Implementation);
|
||||
return Module;
|
||||
});
|
||||
1332
packages/xblox/ref-control-freak/xblox/model/Scope.bak.js
Normal file
1332
packages/xblox/ref-control-freak/xblox/model/Scope.bak.js
Normal file
File diff suppressed because it is too large
Load Diff
1646
packages/xblox/ref-control-freak/xblox/model/Scope.js
Normal file
1646
packages/xblox/ref-control-freak/xblox/model/Scope.js
Normal file
File diff suppressed because it is too large
Load Diff
28
packages/xblox/ref-control-freak/xblox/model/Statement.js
Normal file
28
packages/xblox/ref-control-freak/xblox/model/Statement.js
Normal file
@ -0,0 +1,28 @@
|
||||
define([
|
||||
"dcl/dcl",
|
||||
"xblox/model/Block"
|
||||
], function(dcl,Block){
|
||||
|
||||
// summary:
|
||||
// The statement block is only a wrapper for items like in 'else'
|
||||
|
||||
// module:
|
||||
// xblox.model.Statement
|
||||
return dcl(Block,{
|
||||
declaredClass:"xblox.model.Statement",
|
||||
/**
|
||||
* Return block name
|
||||
* @returns {name|*}
|
||||
*/
|
||||
toText:function(){
|
||||
return this.name;
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @returns {items|*}
|
||||
*/
|
||||
getChildren:function(){
|
||||
return this.items;
|
||||
}
|
||||
});
|
||||
});
|
||||
12
packages/xblox/ref-control-freak/xblox/model/Targeted.js
Normal file
12
packages/xblox/ref-control-freak/xblox/model/Targeted.js
Normal file
@ -0,0 +1,12 @@
|
||||
define([
|
||||
"dojo/_base/declare",
|
||||
"./Referenced"
|
||||
], function(declare,Referenced){
|
||||
|
||||
/**
|
||||
* Targeted provides functions to get an object through various ways
|
||||
*/
|
||||
return declare('xblox.model.Targeted',[Referenced],{
|
||||
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,94 @@
|
||||
define([
|
||||
'dcl/dcl',
|
||||
"xblox/model/Block",
|
||||
'xide/utils'
|
||||
], function(dcl,Block,utils){
|
||||
|
||||
// summary:
|
||||
// The Call Block model.
|
||||
// This block makes calls to another blocks in the same scope by action name
|
||||
|
||||
// module:
|
||||
// xblox.model.code.CallMethod
|
||||
return dcl(Block,{
|
||||
declaredClass:"xblox.model.code.CallMethod",
|
||||
//method: (String)
|
||||
// block action name
|
||||
name:'Call Method',
|
||||
//method: (String)
|
||||
// block action name
|
||||
method:'',
|
||||
args:'',
|
||||
|
||||
sharable:true,
|
||||
/***
|
||||
* Returns the block run result
|
||||
* @param scope
|
||||
*/
|
||||
solve:function(scope,settings) {
|
||||
var context = this.getContext();
|
||||
if (context && context[this.method]!=null)
|
||||
{
|
||||
|
||||
|
||||
var res = [];
|
||||
var _fn = context[this.method];
|
||||
try{
|
||||
var _args = this.getArgs(settings);
|
||||
console.log('args',_args);
|
||||
var _res = _fn.apply(context,_args||[]);
|
||||
res = _res;
|
||||
this.onSuccess(this,settings);
|
||||
return res;
|
||||
}catch(e){
|
||||
console.error('call method ' + this.method + ' failed: '+e);
|
||||
logError(e);
|
||||
this.onFailed(this,settings);
|
||||
}
|
||||
}else{
|
||||
this.onFailed(this,settings);
|
||||
return [];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
toText:function(){
|
||||
|
||||
var result = this.getBlockIcon() + ' ' + this.name + ' ';
|
||||
if(this.method){
|
||||
result+= this.makeEditable('method','bottom','text','Enter a driver method','inline');
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
// standard call for editing
|
||||
getFields:function(){
|
||||
|
||||
var fields = this.getDefaultFields();
|
||||
|
||||
var context = this.getContext();
|
||||
/*
|
||||
console.log('call method ', this.getScope().getContext());
|
||||
console.log('call method ', context);*/
|
||||
|
||||
|
||||
fields.push(utils.createCI('value',13,this.method,{
|
||||
group:'General',
|
||||
title:'Method',
|
||||
dst:'method'
|
||||
}));
|
||||
|
||||
fields.push(utils.createCI('value',27,this.args,{
|
||||
group:'Arguments',
|
||||
dst:'args',
|
||||
widget:{
|
||||
title:''
|
||||
}
|
||||
}));
|
||||
|
||||
return fields;
|
||||
},
|
||||
getBlockIcon:function(){
|
||||
return '<span class="fa-caret-square-o-right"></span>';
|
||||
}
|
||||
});
|
||||
});
|
||||
151
packages/xblox/ref-control-freak/xblox/model/code/RunBlock.js
Normal file
151
packages/xblox/ref-control-freak/xblox/model/code/RunBlock.js
Normal file
@ -0,0 +1,151 @@
|
||||
define([
|
||||
'dcl/dcl',
|
||||
"xblox/model/Block",
|
||||
'xide/types',
|
||||
'xide/utils'
|
||||
], function(dcl,Block,types,utils){
|
||||
|
||||
// summary:
|
||||
// The Call Block model.
|
||||
// This block makes calls to another blocks in the same scope by action name
|
||||
|
||||
// module:
|
||||
// xblox.model.code.CallMethod
|
||||
|
||||
|
||||
return dcl(Block,{
|
||||
declaredClass:"xblox.model.code.RunBlock",
|
||||
//method: (String)
|
||||
// block action name
|
||||
name:'Run Block',
|
||||
|
||||
file:'',
|
||||
//method: (String)
|
||||
// block action name
|
||||
method:'',
|
||||
|
||||
args:'',
|
||||
|
||||
sharable:true,
|
||||
|
||||
block:'',
|
||||
|
||||
description:"Runs another Block",
|
||||
/***
|
||||
* Returns the block run result
|
||||
* @param scope
|
||||
*/
|
||||
solve:function(scope,settings) {
|
||||
|
||||
var context = this.getContext();
|
||||
if (context && context[this.method]!=null)
|
||||
{
|
||||
var res = [];
|
||||
var _fn = context[this.method];
|
||||
try{
|
||||
var _args = this._getArgs();
|
||||
var _res = _fn.apply(context,_args||[]);
|
||||
res = _res;
|
||||
this.onSuccess(this,settings);
|
||||
return res;
|
||||
}catch(e){
|
||||
console.error('call method failed');
|
||||
this.onFailed(this,settings);
|
||||
}
|
||||
}else{
|
||||
this.onFailed(this,settings);
|
||||
return [];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
toText:function(){
|
||||
|
||||
var result = this.getBlockIcon() + ' ' + this.name + ' ';
|
||||
if(this.method){
|
||||
result+= this.method.substr(0,20);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
// standard call for editing
|
||||
getFields:function(){
|
||||
|
||||
|
||||
var fields = this.getDefaultFields();
|
||||
|
||||
|
||||
fields.push(utils.createCI('Block', types.ECIType.BLOCK_REFERENCE, this.block, {
|
||||
toolTip:'Enter block, you can use also the block\'s share title',
|
||||
group: 'General',
|
||||
dst: 'block',
|
||||
value: this.block,
|
||||
title:'Block',
|
||||
scope:this.scope
|
||||
}));
|
||||
|
||||
fields.push(utils.createCI('File', types.ECIType.FILE, this.file, {
|
||||
toolTip:'Leave empty to auto-select this file',
|
||||
group: 'General',
|
||||
dst: 'file',
|
||||
value: this.file,
|
||||
intermediateChanges: false,
|
||||
acceptFolders: false,
|
||||
acceptFiles: true,
|
||||
encodeFilePath: false,
|
||||
buildFullPath: true,
|
||||
filePickerOptions: {
|
||||
dialogTitle: 'Select Block File',
|
||||
filePickerMixin: {
|
||||
beanContextName: this.id,
|
||||
persistent: false,
|
||||
globalPanelMixin: {
|
||||
allowLayoutCookies: false
|
||||
}
|
||||
},
|
||||
configMixin: {
|
||||
beanContextName: this.id,
|
||||
LAYOUT_PRESET: types.LAYOUT_PRESET.SINGLE,
|
||||
PANEL_OPTIONS:{
|
||||
ALLOW_MAIN_MENU:false,
|
||||
ALLOW_NEW_TABS:true,
|
||||
ALLOW_MULTI_TAB:false,
|
||||
ALLOW_INFO_VIEW:true,
|
||||
ALLOW_LOG_VIEW:false,
|
||||
ALLOW_CONTEXT_MENU:true,
|
||||
ALLOW_LAYOUT_SELECTOR:true,
|
||||
ALLOW_SOURCE_SELECTOR:true,
|
||||
ALLOW_COLUMN_RESIZE:true,
|
||||
ALLOW_COLUMN_REORDER:true,
|
||||
ALLOW_COLUMN_HIDE:true,
|
||||
ALLOW_ACTION_TOOLBAR:true,
|
||||
ALLOW_BREADCRUMBS:false
|
||||
}
|
||||
},
|
||||
defaultStoreOptions: {
|
||||
"fields": 1663,
|
||||
"includeList": "xblox",
|
||||
"excludeList": "*"
|
||||
},
|
||||
startPath: this.file
|
||||
}
|
||||
}));
|
||||
|
||||
return fields;
|
||||
|
||||
/*
|
||||
fields.push(utils.createCI('value',27,this.args,{
|
||||
group:'General',
|
||||
title:'Arguments',
|
||||
dst:'args'
|
||||
}));
|
||||
|
||||
return fields;
|
||||
*/
|
||||
},
|
||||
getBlockIcon:function(){
|
||||
return '<span class="el-icon-share-alt"></span>';
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,10 @@
|
||||
Runs an expression.<br/>
|
||||
|
||||
<b>Behaviour</b>
|
||||
|
||||
<pre>
|
||||
|
||||
//to abort execution (child blocks), return something negative as -1 or false.
|
||||
return false;
|
||||
|
||||
</pre>
|
||||
300
packages/xblox/ref-control-freak/xblox/model/code/RunScript.js
Normal file
300
packages/xblox/ref-control-freak/xblox/model/code/RunScript.js
Normal file
@ -0,0 +1,300 @@
|
||||
/** @module xblox/model/code/RunScript **/
|
||||
define([
|
||||
'dcl/dcl',
|
||||
'xdojo/has',
|
||||
"dojo/Deferred",
|
||||
"xblox/model/Block",
|
||||
'xide/utils',
|
||||
'xblox/model/Contains',
|
||||
'dojo/promise/all',
|
||||
'xide/types',
|
||||
'module'
|
||||
//'xdojo/has!host-node?dojo/node!tracer',
|
||||
//'xdojo/has!host-node?nxapp/utils/_console'
|
||||
//"xdojo/has!xblox-ui?dojo/text!./RunScript.html"
|
||||
//"xdojo/has!xblox-ui?dojo/text!xblox/docs/code/RunScript.md"
|
||||
], function(dcl,has,Deferred,Block,utils,Contains,all,types,module,tracer,_console,Description,Help){
|
||||
|
||||
|
||||
var isServer = has('host-node');
|
||||
var console = typeof window !== 'undefined' ? window.console : global.console;
|
||||
if(isServer && tracer && console && console.error){
|
||||
console = _console;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @class module:xblox/model/code/RunScript
|
||||
* @extends module:xblox/model/Block
|
||||
*/
|
||||
return dcl([Block,Contains],{
|
||||
declaredClass:"xblox.model.code.RunScript",
|
||||
name:'Run Script',
|
||||
method:'',
|
||||
args:'',
|
||||
deferred:false,
|
||||
sharable:true,
|
||||
context:null,
|
||||
icon:'fa-code',
|
||||
observed:[
|
||||
'method'
|
||||
],
|
||||
getContext:function(){
|
||||
return this.context || (this.scope.getContext ? this.scope.getContext() : this);
|
||||
return this.context || this;
|
||||
},
|
||||
/***
|
||||
* Returns the block run result
|
||||
* @param scope
|
||||
* @param settings
|
||||
* @param run
|
||||
* @param error
|
||||
* @returns {Array}
|
||||
*/
|
||||
solve2:function(scope,settings,run,error) {
|
||||
this._currentIndex = 0;
|
||||
this._return=[];
|
||||
var _script = '' + this._get('method');
|
||||
var thiz=this,
|
||||
ctx = this.getContext();
|
||||
if(_script && _script.length) {
|
||||
|
||||
var runScript = function() {
|
||||
var _function = new Function("{" + _script + "}");
|
||||
var _args = thiz.getArgs() || [];
|
||||
try {
|
||||
var _parsed = _function.apply(ctx, _args || {});
|
||||
thiz._lastResult = _parsed;
|
||||
if (run) {
|
||||
run('Expression ' + _script + ' evaluates to ' + _parsed);
|
||||
}
|
||||
if (_parsed !== 'false' && _parsed !== false) {
|
||||
thiz.onSuccess(thiz, settings,{
|
||||
result:_parsed
|
||||
});
|
||||
} else {
|
||||
thiz.onFailed(thiz, settings);
|
||||
return [];
|
||||
}
|
||||
} catch (e) {
|
||||
if (error) {
|
||||
error('invalid expression : \n' + _script + ': ' + e);
|
||||
}
|
||||
thiz.onFailed(thiz, settings);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
if(scope.global){
|
||||
(function() {
|
||||
window = scope.global;
|
||||
var _args = thiz.getArgs() || [];
|
||||
try {
|
||||
var _parsed = null;
|
||||
if(!ctx.runExpression) {
|
||||
var _function = new Function("{" + _script + "}").bind(this);
|
||||
_parsed = _function.apply(ctx, _args || {});
|
||||
}else{
|
||||
_parsed = ctx.runExpression(_script,null,_args);
|
||||
}
|
||||
|
||||
thiz._lastResult = _parsed;
|
||||
|
||||
if (run) {
|
||||
run('Expression ' + _script + ' evaluates to ' + _parsed);
|
||||
}
|
||||
if (_parsed !== 'false' && _parsed !== false) {
|
||||
thiz.onSuccess(thiz, settings);
|
||||
} else {
|
||||
thiz.onFailed(thiz, settings);
|
||||
return [];
|
||||
}
|
||||
} catch (e) {
|
||||
thiz._lastResult = null;
|
||||
if (error) {
|
||||
error('invalid expression : \n' + _script + ': ' + e);
|
||||
}
|
||||
thiz.onFailed(thiz, settings);
|
||||
return [];
|
||||
}
|
||||
|
||||
}).call(scope.global);
|
||||
|
||||
}else{
|
||||
return runScript();
|
||||
}
|
||||
}else{
|
||||
console.error('have no script');
|
||||
}
|
||||
var ret=[], items = this[this._getContainer()];
|
||||
if(items.length) {
|
||||
this.runFrom(items,0,settings);
|
||||
}else{
|
||||
this.onSuccess(this, settings);
|
||||
}
|
||||
this.onDidRun();
|
||||
return ret;
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param scope
|
||||
* @param settings
|
||||
* @param run
|
||||
* @param error
|
||||
*/
|
||||
solve:function(scope,settings,isInterface,send,run,error){
|
||||
|
||||
this._currentIndex = 0;
|
||||
this._return=[];
|
||||
|
||||
|
||||
settings = settings || {};
|
||||
var _script = send || (this._get('method') ? this._get('method') : this.method);
|
||||
|
||||
if(!scope.expressionModel){
|
||||
//console.error('mar',scope);
|
||||
throw new Error('na');
|
||||
return;
|
||||
}
|
||||
|
||||
var thiz=this,
|
||||
ctx = this.getContext(),
|
||||
items = this[this._getContainer()],
|
||||
|
||||
//outer
|
||||
dfd = new Deferred,
|
||||
listener = settings.listener,
|
||||
isDfd = thiz.deferred,
|
||||
expressionModel = scope.getExpressionModel();
|
||||
|
||||
|
||||
|
||||
this.onRunThis(settings);
|
||||
|
||||
function globalEval(text) {
|
||||
var ret;
|
||||
// Properly escape \, " and ' in the input, normalize \r\n to an escaped \n
|
||||
text = text.replace(/["'\\]/g, "\\$&").replace(/\r\n/g, "\\n");
|
||||
|
||||
// You have to use eval() because not every expression can be used with an assignment operator
|
||||
var where = typeof window!=='undefined' ? window : global;
|
||||
|
||||
where.execScript("globalEval.____lastInputResult____ = eval('" + text + "');} }");
|
||||
|
||||
// Store the result and delete the property
|
||||
ret = globalEval.____lastInputResult____;
|
||||
delete globalEval.____lastInputResult____;
|
||||
|
||||
return ret;
|
||||
}
|
||||
if(!expressionModel){
|
||||
console.error('scope has no expression model');
|
||||
return false;
|
||||
}
|
||||
var expression = expressionModel.replaceVariables(scope,_script,null,null);
|
||||
var _function = expressionModel.expressionCache[expression];
|
||||
if(!_function){
|
||||
_function = expressionModel.expressionCache[expression] = new Function("{" + expression + "}");
|
||||
}
|
||||
var _args = thiz.getArgs(settings) || [];
|
||||
try {
|
||||
if(isDfd){
|
||||
ctx.resolve=function(result){
|
||||
if(thiz._deferredObject) {
|
||||
thiz._deferredObject.resolve();
|
||||
}
|
||||
thiz.onDidRunThis(dfd,result,items,settings);
|
||||
}
|
||||
}
|
||||
var _parsed = _function.apply(ctx, _args || {});
|
||||
thiz._lastResult = _parsed;
|
||||
if (run) {
|
||||
run('Expression ' + _script + ' evaluates to ' + _parsed);
|
||||
}
|
||||
if(!isDfd) {
|
||||
thiz.onDidRunThis(dfd,_parsed,items,settings);
|
||||
}
|
||||
if (_parsed !== 'false' && _parsed !== false) {
|
||||
thiz.onSuccess(thiz, settings);
|
||||
} else {
|
||||
thiz.onFailed(thiz, settings);
|
||||
}
|
||||
} catch (e) {
|
||||
e=e ||{};
|
||||
thiz.onDidRunItemError(dfd,e,settings);
|
||||
thiz.onFailed(thiz,settings);
|
||||
if (error) {
|
||||
error('invalid expression : \n' + _script + ': ' + e);
|
||||
}
|
||||
}
|
||||
return dfd;
|
||||
},
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UI
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
toText:function(){
|
||||
|
||||
var result = '<span style="">' + this.getBlockIcon() + ' ' + this.name + ' :: '+'</span>';
|
||||
if(this.method){
|
||||
result+= this.method.substr(0,50);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
canAdd:function(){
|
||||
return true;
|
||||
},
|
||||
getFields:function(){
|
||||
if(this.description === 'No Description'){
|
||||
this.description = Description;
|
||||
}
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
var thiz=this;
|
||||
fields.push(
|
||||
utils.createCI('name',13,this.name,{
|
||||
group:'General',
|
||||
title:'Name',
|
||||
dst:'name'
|
||||
})
|
||||
);
|
||||
fields.push(
|
||||
utils.createCI('deferred',0,this.deferred,{
|
||||
group:'General',
|
||||
title:'Deferred',
|
||||
dst:'deferred'
|
||||
})
|
||||
);
|
||||
fields.push(utils.createCI('arguments',27,this.args,{
|
||||
group:'Arguments',
|
||||
title:'Arguments',
|
||||
dst:'args'
|
||||
}));
|
||||
|
||||
fields.push(
|
||||
utils.createCI('value',types.ECIType.EXPRESSION_EDITOR,this.method,{
|
||||
group:'Script',
|
||||
title:'Script',
|
||||
dst:'method',
|
||||
select:true,
|
||||
widget:{
|
||||
allowACECache:true,
|
||||
showBrowser:false,
|
||||
showSaveButton:true,
|
||||
editorOptions:{
|
||||
showGutter:true,
|
||||
autoFocus:false
|
||||
},
|
||||
item:this
|
||||
},
|
||||
delegate:{
|
||||
runExpression:function(val,run,error){
|
||||
var old = thiz.method;
|
||||
thiz.method=val;
|
||||
var _res = thiz.solve(thiz.scope,null,run,error);
|
||||
}
|
||||
}
|
||||
}));
|
||||
return fields;
|
||||
}
|
||||
});
|
||||
});
|
||||
393
packages/xblox/ref-control-freak/xblox/model/events/OnEvent.js
Normal file
393
packages/xblox/ref-control-freak/xblox/model/events/OnEvent.js
Normal file
@ -0,0 +1,393 @@
|
||||
define([
|
||||
'dcl/dcl',
|
||||
"dojo/_base/lang",
|
||||
"dojo/Deferred",
|
||||
"xblox/model/Block",
|
||||
'xide/utils',
|
||||
'xide/types',
|
||||
'xide/mixins/EventedMixin',
|
||||
'xblox/model/Referenced',
|
||||
'xide/registry',
|
||||
'dojo/on',
|
||||
'xwire/_Base'
|
||||
], function(dcl,lang,Deferred,Block,utils,types,EventedMixin,Referenced,registry,on,_Base){
|
||||
|
||||
|
||||
|
||||
|
||||
// summary:
|
||||
// The Call Block model.
|
||||
// This block makes calls to another blocks in the same scope by action name
|
||||
|
||||
// module:
|
||||
// xblox.model.code.CallMethod
|
||||
return dcl([Block,EventedMixin.dcl,Referenced.dcl,_Base],{
|
||||
declaredClass:"xblox.model.events.OnEvent",
|
||||
//method: (String)
|
||||
// block action name
|
||||
name:'On Event',
|
||||
event:'',
|
||||
reference:'',
|
||||
references:null,
|
||||
sharable:true,
|
||||
_didSubscribe:false,
|
||||
filterPath:"item.name",
|
||||
filterValue:"",
|
||||
valuePath:"item.value",
|
||||
_nativeEvents:[
|
||||
"onclick",
|
||||
"ondblclick",
|
||||
"onmousedown",
|
||||
"onmouseup",
|
||||
"onmouseover",
|
||||
"onmousemove",
|
||||
"onmouseout",
|
||||
"onkeypress",
|
||||
"onkeydown",
|
||||
"onkeyup",
|
||||
"onfocus",
|
||||
"onblur",
|
||||
"onchange"
|
||||
],
|
||||
|
||||
stop:function(){
|
||||
|
||||
this._destroy();
|
||||
|
||||
},
|
||||
/***
|
||||
* Returns the block run result
|
||||
* @param scope
|
||||
* @param settings
|
||||
* @param run
|
||||
* @param error
|
||||
* @returns {Array}
|
||||
*/
|
||||
solve:function(scope,settings,isInterface,error) {
|
||||
|
||||
if(isInterface){
|
||||
this._destroy();
|
||||
}
|
||||
|
||||
settings = this._lastSettings = settings || this._lastSettings;
|
||||
|
||||
if(!this._didSubscribe){
|
||||
this._registerEvent(this.event);
|
||||
this.onSuccess(this, settings);
|
||||
return false;
|
||||
}
|
||||
|
||||
this.onSuccess(this, settings);
|
||||
|
||||
this._currentIndex=0;
|
||||
this._return=[];
|
||||
|
||||
var ret=[], items = this[this._getContainer()];
|
||||
if(items.length) {
|
||||
//console.log('solve ',settings);
|
||||
var res = this.runFrom(items,0,settings);
|
||||
this.onSuccess(this, settings);
|
||||
return res;
|
||||
}else{
|
||||
this.onSuccess(this, settings);
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UI
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
toText:function(){
|
||||
var result = this.getBlockIcon() + ' ' + this.name + ' :: ';
|
||||
if(this.event){
|
||||
result+= this.event;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
// standard call from interface
|
||||
canAdd:function(){
|
||||
return [];
|
||||
},
|
||||
|
||||
// standard call for editing
|
||||
getFields:function(){
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
var thiz=this;
|
||||
|
||||
var _ref = this.deserialize(this.reference);
|
||||
var isNative = utils.contains(this._nativeEvents,this.event)>-1;
|
||||
var options = null;
|
||||
if(!isNative){
|
||||
options = this.scope.getEventsAsOptions(this.event);
|
||||
}else{
|
||||
|
||||
options = [
|
||||
{label:"onclick", value:"onclick"},
|
||||
{label:"ondblclick",value:"ondblclick"},
|
||||
{label:"onmousedown",value:"onmousedown"},
|
||||
{label:"onmouseup",value:"onmouseup"},
|
||||
{label:"onmouseover",value:"onmouseover"},
|
||||
{label:"onmousemove",value:"onmousemove"},
|
||||
{label:"onmouseout",value:"onmouseout"},
|
||||
{label:"onkeypress",value:"onkeypress"},
|
||||
{label:"onkeydown",value:"onkeydown"},
|
||||
{label:"onkeyup", value:"onkeyup"},
|
||||
{label:"onfocus", value:"onfocus"},
|
||||
{label:"onblur", value:"onblur"},
|
||||
{label:"onchange", value:"onchange"}
|
||||
];
|
||||
|
||||
//select the event we are listening to
|
||||
for (var i = 0; i < options.length; i++) {
|
||||
var obj = options[i];
|
||||
if(obj.value===this.event){
|
||||
obj.selected=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fields.push(utils.createCI('Event',types.ECIType.ENUMERATION,this.event,{
|
||||
group:'General',
|
||||
options:options,
|
||||
dst:'event',
|
||||
widget:{
|
||||
search:true
|
||||
}
|
||||
}));
|
||||
|
||||
fields.push(utils.createCI('Filter Path',13,this.filterPath,{
|
||||
group:'General',
|
||||
dst:'filterPath'
|
||||
}));
|
||||
|
||||
fields.push(utils.createCI('Filter Value',13,this.filterValue,{
|
||||
group:'General',
|
||||
dst:'filterValue'
|
||||
}));
|
||||
|
||||
fields.push(utils.createCI('Value Path',13,this.valuePath,{
|
||||
group:'General',
|
||||
dst:'valuePath'
|
||||
}));
|
||||
|
||||
|
||||
fields.push(utils.createCI('Object/Widget',types.ECIType.WIDGET_REFERENCE,this.reference,{
|
||||
group:'Widget',
|
||||
dst:'reference',
|
||||
value:this.reference
|
||||
}));
|
||||
return fields;
|
||||
},
|
||||
|
||||
getBlockIcon:function(){
|
||||
return '<span class="fa-bell"></span>';
|
||||
},
|
||||
onEvent:function(evt){
|
||||
|
||||
this._lastResult=evt;
|
||||
|
||||
/*
|
||||
if(this.scope && evt.scope && evt.scope!==this.scope){
|
||||
return;
|
||||
}*/
|
||||
|
||||
if(this.filterPath && this.filterValue){
|
||||
var value = this.getValue(evt,this.filterPath);
|
||||
if(value && this.filterValue !==value){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var eventValue = null;
|
||||
if(this.valuePath){
|
||||
|
||||
if(!this._lastSettings){
|
||||
this._lastSettings = {};
|
||||
}
|
||||
eventValue = this.getValue(evt,this.valuePath);
|
||||
if(eventValue!==null){
|
||||
!this._lastSettings.override && (this._lastSettings.override = {});
|
||||
this._lastSettings.override.args = [eventValue];
|
||||
}
|
||||
}
|
||||
|
||||
//console.log('on event ',this._lastSettings);
|
||||
this.solve(this.scope,this._lastSettings);
|
||||
},
|
||||
_subscribe:function(evt,handler,obj){
|
||||
|
||||
if(!evt){
|
||||
return;
|
||||
}
|
||||
var isNative = utils.contains(this._nativeEvents,evt);
|
||||
if(isNative==-1){
|
||||
|
||||
if(this.__events && this.__events[evt]) {
|
||||
var _handles = this.__events[evt];
|
||||
|
||||
_.each(_handles, function (e) {
|
||||
this.unsubscribe(e.type, e.handler);
|
||||
e.remove();
|
||||
}, this);
|
||||
|
||||
_.each(_handles, function (e) {
|
||||
this.__events[evt].remove(e);
|
||||
}, this);
|
||||
}
|
||||
|
||||
this.subscribe(evt, this.onEvent);
|
||||
}else{
|
||||
|
||||
if(obj) {
|
||||
var _event = evt.replace('on', ''),
|
||||
thiz = this;
|
||||
|
||||
var handle = on(obj, _event, function (e) {
|
||||
thiz.onEvent(e)
|
||||
});
|
||||
console.log('wire native event : ' + _event);
|
||||
this._events.push(handle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
_registerEvent:function(evt){
|
||||
|
||||
try {
|
||||
if (!evt || !evt.length) {
|
||||
return;
|
||||
}
|
||||
console.log('register event : ' + evt + ' for ' + this.reference);
|
||||
var objects = this.resolveReference(this.deserialize(this.reference));
|
||||
var thiz = this;
|
||||
if (objects && objects.length) {
|
||||
for (var i = 0; i < objects.length; i++) {
|
||||
var obj = objects[i];
|
||||
|
||||
//try widget
|
||||
if (obj && obj.id) {
|
||||
var _widget = registry.byId(obj.id);
|
||||
if (_widget && _widget.on) {
|
||||
var _event = this.event.replace('on', '');
|
||||
console.log('found widget : ' + obj.id + ' will register event ' + _event);
|
||||
var _handle = _widget.on(_event, lang.hitch(this, function (e) {
|
||||
console.log('event triggered : ' + thiz.event);
|
||||
thiz.onEvent(e);
|
||||
}));
|
||||
this._events.push(_handle);
|
||||
} else {
|
||||
|
||||
this._subscribe(evt, this.onEvent, obj);
|
||||
}
|
||||
} else {
|
||||
|
||||
this._subscribe(evt, this.onEvent, obj);
|
||||
}
|
||||
}
|
||||
console.log('objects found : ', objects);
|
||||
} else {
|
||||
this._subscribe(evt, this.onEvent);
|
||||
}
|
||||
}catch(e){
|
||||
logError(e,'registering event failed');
|
||||
}
|
||||
this._didSubscribe=evt;
|
||||
},
|
||||
onLoad:function(){
|
||||
this._onLoaded=true;
|
||||
if(this.event && this.event.length && this.enabled){
|
||||
this._registerEvent(this.event);
|
||||
}
|
||||
},
|
||||
updateEventSelector:function(objects,cis){
|
||||
|
||||
var options = [];
|
||||
|
||||
if(!objects || !objects.length){
|
||||
options= this.scope.getEventsAsOptions(this.event);
|
||||
}else{
|
||||
|
||||
options = [{label:"onclick", value:"onclick"},
|
||||
{label:"ondblclick",value:"ondblclick"},
|
||||
{label:"onmousedown",value:"onmousedown"},
|
||||
{label:"onmouseup",value:"onmouseup"},
|
||||
{label:"onmouseover",value:"onmouseover"},
|
||||
{label:"onmousemove",value:"onmousemove"},
|
||||
{label:"onmouseout",value:"onmouseout"},
|
||||
{label:"onkeypress",value:"onkeypress"},
|
||||
{label:"onkeydown",value:"onkeydown"},
|
||||
{label:"onkeyup", value:"onkeyup"},
|
||||
{label:"onfocus", value:"onfocus"},
|
||||
{label:"onblur", value:"onblur"},
|
||||
{label:"onchange", value:"onchange"}];
|
||||
|
||||
//select the event we are listening to
|
||||
for (var i = 0; i < options.length; i++) {
|
||||
var obj = options[i];
|
||||
if(obj.value===this.event){
|
||||
obj.selected=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < cis.length; i++) {
|
||||
var ci = cis[i];
|
||||
if(ci['widget'] && ci['widget'].title==='Event'){
|
||||
//console.log('event!');
|
||||
var widget = ci['_widget'];
|
||||
widget.nativeWidget.set('options',options);
|
||||
widget.nativeWidget.reset();
|
||||
widget.nativeWidget.set('value',this.event);
|
||||
this.publish(types.EVENTS.RESIZE,{});
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
onReferenceChanged:function(newValue,cis){
|
||||
|
||||
this._destroy();//unregister previous event(s)
|
||||
|
||||
this.reference = newValue;
|
||||
var objects = this.resolveReference(this.deserialize(newValue));
|
||||
this.updateEventSelector(objects,cis);
|
||||
this._registerEvent(this.event);
|
||||
|
||||
},
|
||||
onChangeField:function(field,newValue,cis){
|
||||
|
||||
if(field=='event'){
|
||||
this._destroy(); //unregister previous event
|
||||
if(this._onLoaded){ // we've have been activated at load time, so re-register our event
|
||||
this.event = newValue;
|
||||
this._registerEvent(newValue);
|
||||
}
|
||||
}
|
||||
if(field=='reference'){
|
||||
this.onReferenceChanged(newValue,cis);
|
||||
}
|
||||
|
||||
this.inherited(arguments);
|
||||
},
|
||||
activate:function(){
|
||||
this._destroy();//you never know
|
||||
this._registerEvent(this.event);
|
||||
},
|
||||
deactivate:function(){
|
||||
this._destroy();
|
||||
},
|
||||
_destroy:function(){
|
||||
|
||||
if(!this._events){this._events=[];}
|
||||
_.each(this._events, dojo.unsubscribe);
|
||||
this.unsubscribe(this.event,this.onEvent);
|
||||
this._lastResult=null;
|
||||
this._didSubscribe = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
276
packages/xblox/ref-control-freak/xblox/model/events/OnKey.js
Normal file
276
packages/xblox/ref-control-freak/xblox/model/events/OnKey.js
Normal file
@ -0,0 +1,276 @@
|
||||
define([
|
||||
'dcl/dcl',
|
||||
"dojo/_base/lang",
|
||||
"dojo/_base/array",
|
||||
"dojo/Deferred",
|
||||
"xblox/model/Block",
|
||||
'xide/utils',
|
||||
'xide/types',
|
||||
'xide/mixins/EventedMixin',
|
||||
'xblox/model/Referenced',
|
||||
'xblox/model/Contains',
|
||||
'xblox/model/events/OnEvent',
|
||||
'xide/registry',
|
||||
'dojo/on'
|
||||
], function(dcl,lang,array,Deferred,Block,utils,types,EventedMixin,Referenced,Contains,OnEvent,registry,on){
|
||||
|
||||
// summary:
|
||||
// The Call Block model.
|
||||
// This block makes calls to another blocks in the same scope by action name
|
||||
|
||||
// module:
|
||||
// xblox.model.code.CallMethod
|
||||
return dcl([Block,EventedMixin.dcl,Referenced.dcl,Contains],{
|
||||
declaredClass:"xblox.model.events.OnKey",
|
||||
//method: (String)
|
||||
// block action name
|
||||
name:'On Key',
|
||||
|
||||
event:'',
|
||||
|
||||
reference:'',
|
||||
|
||||
references:null,
|
||||
|
||||
description:'Triggers when a keyboard sequence ' + this.event +' has been entered',
|
||||
|
||||
listeners:null,
|
||||
|
||||
sharable:true,
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UI
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
toText:function(){
|
||||
|
||||
var result = this.getBlockIcon() + ' ' + this.name + ' :: ';
|
||||
if(this.event){
|
||||
result+= this.event;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
// standard call from interface
|
||||
canAdd:function(){
|
||||
return [];
|
||||
},
|
||||
|
||||
// standard call for editing
|
||||
getFields:function(){
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
|
||||
fields.push(utils.createCI('Keyboard Sequence',types.ECIType.STRING,this.event,{
|
||||
group:'General',
|
||||
dst:'event',
|
||||
value:this.event,
|
||||
intermediateChanges:false
|
||||
}));
|
||||
|
||||
fields.push(utils.createCI('Object/Widget',types.ECIType.WIDGET_REFERENCE,this.reference,{
|
||||
group:'General',
|
||||
dst:'reference',
|
||||
value:this.reference
|
||||
}));
|
||||
return fields;
|
||||
},
|
||||
getBlockIcon:function(){
|
||||
return '<span class="fa-keyboard-o"></span>';
|
||||
},
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Store
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
onEvent:function(evt){
|
||||
this._lastResult=evt;
|
||||
this.solve(this.scope,this._lastRunSettings);
|
||||
|
||||
},
|
||||
_addListerner:function(keys,handler,obj){
|
||||
if(this.listeners==null){
|
||||
this.listeners=[];
|
||||
}
|
||||
|
||||
var my_defaults = {
|
||||
is_unordered : true,
|
||||
prevent_repeat : false,
|
||||
prevent_default : false,
|
||||
on_keyup:function(e){
|
||||
console.log('up');
|
||||
},
|
||||
on_keydown:function(e){
|
||||
console.log('down');
|
||||
},
|
||||
on_release:function(e){
|
||||
console.log('release');
|
||||
}
|
||||
};
|
||||
var listener =null;
|
||||
listener = new window.keypress.Listener(obj, my_defaults);
|
||||
listener.simple_combo(keys, function(e) {
|
||||
if(handler){
|
||||
handler(arguments);
|
||||
}
|
||||
});
|
||||
|
||||
this.listeners.push(listener);
|
||||
},
|
||||
_subscribe:function(keys,handler,obj){
|
||||
|
||||
if(!keys){
|
||||
return;
|
||||
}
|
||||
|
||||
if(obj && obj.domNode){
|
||||
obj = obj.domNode;
|
||||
}
|
||||
|
||||
this._addListerner(keys,handler,obj);
|
||||
|
||||
},
|
||||
_registerEvent:function(evt){
|
||||
|
||||
if(!evt || !evt.length){
|
||||
return;
|
||||
}
|
||||
var objects = this.resolveReference(this.deserialize(this.reference));
|
||||
var thiz=this;
|
||||
if (objects && objects.length) {
|
||||
for (var i = 0; i < objects.length; i++) {
|
||||
var obj = objects[i];
|
||||
//try widget
|
||||
if (obj && obj.id) {
|
||||
var _widget = registry.byId(obj.id);
|
||||
_widget=null;
|
||||
if (_widget && _widget.on) {
|
||||
var _event = this.event.replace('on','');
|
||||
var _handle = _widget.on(_event,lang.hitch(this,function(e){
|
||||
thiz.onEvent(e);
|
||||
}));
|
||||
this._events.push( _handle);
|
||||
}else{
|
||||
|
||||
this._subscribe(evt, function(){thiz.onEvent(arguments)},obj);
|
||||
}
|
||||
}else{
|
||||
|
||||
this._subscribe(evt, function(){thiz.onEvent(arguments)},obj);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
this._subscribe(evt, function(){thiz.onEvent(arguments)});
|
||||
}
|
||||
},
|
||||
onLoad:function(){
|
||||
|
||||
this._onLoaded=true;
|
||||
|
||||
if(this.event && this.event.length && this.enabled){
|
||||
|
||||
this._registerEvent(this.event);
|
||||
}
|
||||
},
|
||||
destroy:function(){
|
||||
this.inherited(arguments);
|
||||
},
|
||||
updateEventSelector:function(objects,cis){
|
||||
|
||||
var options = [];
|
||||
|
||||
if(!objects || !objects.length){
|
||||
options= this.scope.getEventsAsOptions(this.event);
|
||||
}else{
|
||||
|
||||
options = [{label:"onclick", value:"onclick"},
|
||||
{label:"ondblclick",value:"ondblclick"},
|
||||
{label:"onmousedown",value:"onmousedown"},
|
||||
{label:"onmouseup",value:"onmouseup"},
|
||||
{label:"onmouseover",value:"onmouseover"},
|
||||
{label:"onmousemove",value:"onmousemove"},
|
||||
{label:"onmouseout",value:"onmouseout"},
|
||||
{label:"onkeypress",value:"onkeypress"},
|
||||
{label:"onkeydown",value:"onkeydown"},
|
||||
{label:"onkeyup", value:"onkeyup"},
|
||||
{label:"onfocus", value:"onfocus"},
|
||||
{label:"onblur", value:"onblur"},
|
||||
{label:"onchange", value:"onchange"}];
|
||||
|
||||
//select the event we are listening to
|
||||
for (var i = 0; i < options.length; i++) {
|
||||
var obj = options[i];
|
||||
if(obj.value===this.event){
|
||||
obj.selected=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < cis.length; i++) {
|
||||
var ci = cis[i];
|
||||
if(ci['widget'] && ci['widget'].title==='Event'){
|
||||
//console.log('event!');
|
||||
var widget = ci['_widget'];
|
||||
widget.nativeWidget.set('options',options);
|
||||
widget.nativeWidget.reset();
|
||||
widget.nativeWidget.set('value',this.event);
|
||||
this.publish(types.EVENTS.RESIZE,{});
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
onReferenceChanged:function(newValue,cis){
|
||||
|
||||
this._destroy();//unregister previous event(s)
|
||||
|
||||
this.reference = newValue;
|
||||
var objects = this.resolveReference(this.deserialize(newValue));
|
||||
this._registerEvent(this.event);
|
||||
|
||||
},
|
||||
onChangeField:function(field,newValue,cis){
|
||||
|
||||
if(field=='event'){
|
||||
this._destroy(); //unregister previous event
|
||||
if(this._onLoaded){ // we've have been activated at load time, so re-register our event
|
||||
this.event = newValue;
|
||||
this._registerEvent(newValue);
|
||||
}
|
||||
}
|
||||
if(field=='reference'){
|
||||
this.onReferenceChanged(newValue,cis);
|
||||
}
|
||||
|
||||
this.inherited(arguments);
|
||||
},
|
||||
activate:function(){
|
||||
this._destroy();//you never know
|
||||
this._registerEvent(this.event);
|
||||
},
|
||||
deactivate:function(){
|
||||
this._destroy();
|
||||
},
|
||||
_destroy:function(){
|
||||
|
||||
if(this.listeners){
|
||||
|
||||
for (var i = 0; i < this.listeners.length; i++) {
|
||||
var obj = this.listeners[i];
|
||||
obj.stop_listening();
|
||||
var combos = obj.get_registered_combos();
|
||||
if(combos){
|
||||
obj.unregister_many(combos);
|
||||
}
|
||||
obj.reset();
|
||||
|
||||
console.log('did destroy listener');
|
||||
|
||||
}
|
||||
}
|
||||
this.listeners=[];
|
||||
},
|
||||
onFieldsRendered:function(block,cis){}
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,219 @@
|
||||
define([
|
||||
'dcl/dcl',
|
||||
'xide/utils',
|
||||
'xide/types',
|
||||
'dojo/Deferred',
|
||||
"xblox/model/Block",
|
||||
"xcf/model/Command"
|
||||
], function(dcl,utils,types,Deferred,Block,Command){
|
||||
|
||||
// summary:
|
||||
// The Call Block model.
|
||||
// This block makes calls to another blocks in the same scope by action name
|
||||
|
||||
// module:
|
||||
// xblox.model.functions.CallBlock
|
||||
/**
|
||||
* @augments module:xide/mixins/EventedMixin
|
||||
* @extends module:xblox/model/Block_UI
|
||||
* @extends module:xblox/model/Block
|
||||
* @extends module:xblox/model/ModelBase
|
||||
*/
|
||||
return dcl(Command,{
|
||||
declaredClass:"xblox.model.functions.CallBlock",
|
||||
//command: (String)
|
||||
// block action name
|
||||
command:'Select command please',
|
||||
icon:'',
|
||||
args:null,
|
||||
_timeout:100,
|
||||
|
||||
isCommand:true,
|
||||
|
||||
|
||||
_commandHandles:null,
|
||||
/**
|
||||
* onCommandFinish will be excecuted which a driver did run a command
|
||||
* @param msg {object}
|
||||
* @param msg.id {string} the command job id
|
||||
* @param msg.src {string} the source id, which is this block id
|
||||
* @param msg.cmd {string} the command string being sent
|
||||
*/
|
||||
onCommandProgress:function(msg){
|
||||
|
||||
var scope = this.getScope();
|
||||
var context = scope.getContext();//driver instance
|
||||
var result = {};
|
||||
var params = msg.params;
|
||||
|
||||
if(params && params.id){
|
||||
this._emit('cmd:'+msg.cmd + '_' + params.id,{
|
||||
msg:msg
|
||||
});
|
||||
msg.lastResponse && this.storeResult(msg.lastResponse);
|
||||
this._emit('progress',{
|
||||
msg:msg,
|
||||
id:params.id
|
||||
});
|
||||
}
|
||||
|
||||
var command = this._lastCommand;
|
||||
|
||||
this._lastResult = null;
|
||||
|
||||
|
||||
this._lastResult = msg ? msg.result : null;
|
||||
|
||||
var items = this.getItems(types.BLOCK_OUTLET.PROGRESS);
|
||||
if(!this._lastSettings){
|
||||
this._lastSettings = {}
|
||||
}
|
||||
this._lastSettings.override = {};
|
||||
if(items.length) {
|
||||
this.runFrom(items,0,this._lastSettings);
|
||||
}
|
||||
},
|
||||
stop:function(){
|
||||
this._lastCommand && this._lastCommand.stop();
|
||||
},
|
||||
pause:function(){
|
||||
this._lastCommand && this._lastCommand.pause();
|
||||
},
|
||||
destroy:function(){
|
||||
_.invoke(this._commandHandles,'remove');
|
||||
delete this._commandHandles;
|
||||
delete this._lastCommand;
|
||||
},
|
||||
/***
|
||||
* Returns the block run result
|
||||
* @param scope
|
||||
*/
|
||||
solve:function(scope,settings) {
|
||||
if(!this._commandHandles){
|
||||
this._commandHandles=[];
|
||||
}else{
|
||||
//_.invoke(this._commandHandles,'remove');
|
||||
this._commandHandles = [];
|
||||
}
|
||||
|
||||
var timeout = this._timeout || 50;
|
||||
if(_.isString(timeout)){
|
||||
timeout = parseInt(timeout);
|
||||
}
|
||||
|
||||
var dfd = new Deferred();
|
||||
|
||||
var handles = this._commandHandles;
|
||||
|
||||
settings = settings || {}
|
||||
|
||||
setTimeout(function(){
|
||||
if (this.command){
|
||||
|
||||
var _args = null;
|
||||
if(this.args){
|
||||
|
||||
settings.override = settings.override || {};
|
||||
var args = scope.expressionModel.replaceVariables(scope,this.args,false,false,null,null,{
|
||||
begin:"%%",
|
||||
end:"%%"
|
||||
});
|
||||
try {
|
||||
_args = utils.fromJson(args);
|
||||
}catch(e){
|
||||
_args = args;
|
||||
}
|
||||
settings.override['args']= _.isArray(_args) ? _args : [args];
|
||||
settings.override['mixin']=_args;
|
||||
}
|
||||
this._lastCommand = scope.resolveBlock(this.command);
|
||||
|
||||
if(this._lastCommand && this._lastCommand._on){
|
||||
handles.push(this._lastCommand._on('paused',this.onCommandPaused,this));
|
||||
handles.push(this._lastCommand._on('finished',this.onCommandFinish,this));
|
||||
handles.push(this._lastCommand._on('stopped',this.onCommandStopped,this));
|
||||
handles.push(this._lastCommand._on('error',this.onCommandError,this));
|
||||
handles.push(this._lastCommand._on('progress',this.onCommandProgress,this));
|
||||
}
|
||||
|
||||
var res = scope.solveBlock(this.command,settings);
|
||||
if(res){
|
||||
this.onSuccess(this,settings);
|
||||
}else{
|
||||
this.onFailed(this,settings);
|
||||
}
|
||||
dfd.resolve(res);
|
||||
return res;
|
||||
}
|
||||
}.bind(this),timeout);
|
||||
return dfd;
|
||||
},
|
||||
hasInlineEdits:true,
|
||||
/**
|
||||
*
|
||||
* @param field
|
||||
* @param pos
|
||||
* @param type
|
||||
* @param title
|
||||
* @param mode: inline | popup
|
||||
* @returns {string}
|
||||
*/
|
||||
makeEditable:function(field,pos,type,title,mode,options,value){
|
||||
var optionsString = "";
|
||||
return "<a " + optionsString + " tabIndex=\"-1\" pos='" + pos +"' display-mode='" + (mode||'popup') + "' display-type='" + (type || 'text') +"' data-prop='" + field + "' data-title='" + title + "' class='editable editable-click' href='#'>" + this[field] +"</a>";
|
||||
},
|
||||
getFieldOptions:function(field){
|
||||
if(field ==="command"){
|
||||
return this.scope.getCommandsAsOptions("text");
|
||||
}
|
||||
},
|
||||
toText:function(){
|
||||
var text = 'Unknown';
|
||||
var block = this.scope.getBlock(this.command);
|
||||
if(block){
|
||||
text = block.name;
|
||||
}
|
||||
if(this.command.indexOf('://')!==-1) {
|
||||
text = '<span class="text-info">' +this.scope.toFriendlyName(this,this.command) + '</span>';
|
||||
}
|
||||
var _out = this.getBlockIcon('D') + 'Call Command : ' + text;
|
||||
return _out;
|
||||
},
|
||||
// standard call for editing
|
||||
getFields:function(){
|
||||
|
||||
var fields = this.getDefaultFields();
|
||||
var thiz=this;
|
||||
|
||||
var title = 'Command';
|
||||
|
||||
if(this.command.indexOf('://')){
|
||||
title = this.scope.toFriendlyName(this,this.command);
|
||||
}
|
||||
|
||||
fields.push(utils.createCI('value','xcf.widgets.CommandPicker',this.command,{
|
||||
group:'General',
|
||||
title:'Command',
|
||||
dst:'command',
|
||||
options:this.scope.getCommandsAsOptions(),
|
||||
block:this,
|
||||
pickerType:'command',
|
||||
value:this.command
|
||||
}));
|
||||
|
||||
fields.push(utils.createCI('arguments',27,this.args,{
|
||||
group:'Arguments',
|
||||
title:'Arguments',
|
||||
dst:'args'
|
||||
}));
|
||||
|
||||
fields.push(utils.createCI('timeout',13,this._timeout,{
|
||||
group:'General',
|
||||
title:'Delay',
|
||||
dst:'_timeout'
|
||||
}));
|
||||
|
||||
return fields;
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,88 @@
|
||||
/** @module xblox/model/functions/PauseBlock **/
|
||||
define([
|
||||
'dcl/dcl',
|
||||
'xide/utils',
|
||||
'xide/types',
|
||||
'dojo/Deferred',
|
||||
"xblox/model/Block"
|
||||
], function(dcl,utils,types,Deferred,Block){
|
||||
/**
|
||||
* @augments module:xide/mixins/EventedMixin
|
||||
* @lends module:xblox/model/Block_UI
|
||||
* @extends module:xblox/model/Block
|
||||
* @extends module:xblox/model/ModelBase
|
||||
*/
|
||||
return dcl(Block,{
|
||||
declaredClass:"xblox.model.functions.PauseBlock",
|
||||
command:'Select command please',
|
||||
icon:'',
|
||||
args:null,
|
||||
_timeout:100,
|
||||
hasInlineEdits:true,
|
||||
/***
|
||||
* Returns the block run result
|
||||
* @param scope
|
||||
*/
|
||||
solve:function(scope,settings) {
|
||||
if (this.command){
|
||||
var _args = null;
|
||||
var block = scope.resolveBlock(this.command);
|
||||
if(block && block.pause){
|
||||
var res = block.pause();
|
||||
this.onSuccess(this,settings);
|
||||
}else{
|
||||
this.onFailed(this,settings);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param field
|
||||
* @param pos
|
||||
* @param type
|
||||
* @param title
|
||||
* @param mode: inline | popup
|
||||
* @returns {string}
|
||||
*/
|
||||
makeEditable:function(field,pos,type,title,mode,options,value){
|
||||
var optionsString = "";
|
||||
return "<a " + optionsString + " tabIndex=\"-1\" pos='" + pos +"' display-mode='" + (mode||'popup') + "' display-type='" + (type || 'text') +"' data-prop='" + field + "' data-title='" + title + "' class='editable editable-click' href='#'>" + this[field] +"</a>";
|
||||
},
|
||||
getFieldOptions:function(field){
|
||||
if(field ==="command"){
|
||||
return this.scope.getCommandsAsOptions("text");
|
||||
}
|
||||
},
|
||||
toText:function(){
|
||||
var text = 'Unknown';
|
||||
var block = this.scope.getBlock(this.command);
|
||||
if(block){
|
||||
text = block.name;
|
||||
}
|
||||
if(this.command.indexOf('://')!==-1) {
|
||||
text = '<span class="text-info">' +this.scope.toFriendlyName(this,this.command) + '</span>';
|
||||
}
|
||||
var _out = this.getBlockIcon('D') + 'Pause Command : ' + text;
|
||||
return _out;
|
||||
},
|
||||
getFields:function(){
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
var thiz=this;
|
||||
var title = 'Command';
|
||||
if(this.command.indexOf('://')){
|
||||
title = this.scope.toFriendlyName(this,this.command);
|
||||
}
|
||||
fields.push(utils.createCI('value','xcf.widgets.CommandPicker',this.command,{
|
||||
group:'General',
|
||||
title:'Command',
|
||||
dst:'command',
|
||||
options:this.scope.getCommandsAsOptions(),
|
||||
block:this,
|
||||
pickerType:'command',
|
||||
value:this.command
|
||||
}));
|
||||
return fields;
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,117 @@
|
||||
define([
|
||||
'dcl/dcl',
|
||||
'xide/utils',
|
||||
'xide/types',
|
||||
'dojo/Deferred',
|
||||
"xblox/model/Block",
|
||||
"xide/lodash"
|
||||
], function(dcl,utils,types,Deferred,Block,_){
|
||||
/**
|
||||
* @augments module:xide/mixins/EventedMixin
|
||||
* @lends module:xblox/model/Block_UI
|
||||
* @extends module:xblox/model/Block
|
||||
* @extends module:xblox/model/ModelBase
|
||||
*/
|
||||
return dcl(Block,{
|
||||
declaredClass:"xblox.model.functions.SetProperties",
|
||||
command:'Select block',
|
||||
icon:'',
|
||||
args:null,
|
||||
_timeout:100,
|
||||
hasInlineEdits:false,
|
||||
solve:function(scope,settings) {
|
||||
var dfd = new Deferred();
|
||||
if (this.command){
|
||||
var block = scope.resolveBlock(this.command);
|
||||
if(block && this.props){
|
||||
for(var prop in this.props){
|
||||
block.set(prop,this.props[prop]);
|
||||
block[prop] = this.props[prop];
|
||||
block.onChangeField && block.onChangeField(prop,this.props[prop]);
|
||||
}
|
||||
this.onSuccess(this,settings);
|
||||
}else{
|
||||
this.onFailed(this,settings);
|
||||
}
|
||||
dfd.resolve([]);
|
||||
return dfd;
|
||||
}
|
||||
return dfd;
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param field
|
||||
* @param pos
|
||||
* @param type
|
||||
* @param title
|
||||
* @param mode: inline | popup
|
||||
* @returns {string}
|
||||
*/
|
||||
makeEditable:function(field,pos,type,title,mode){
|
||||
var optionsString = "";
|
||||
return "<a " + optionsString + " tabIndex=\"-1\" pos='" + pos +"' display-mode='" + (mode||'popup') + "' display-type='" + (type || 'text') +"' data-prop='" + field + "' data-title='" + title + "' class='editable editable-click' href='#'>" + this[field] +"</a>";
|
||||
},
|
||||
getFieldOptions:function(field){
|
||||
if(field ==="command"){
|
||||
return this.scope.getCommandsAsOptions("text");
|
||||
}
|
||||
},
|
||||
toText:function(){
|
||||
var text = 'Unknown';
|
||||
var block = this.scope.getBlock(this.command);
|
||||
if(block){
|
||||
text = block.name;
|
||||
}
|
||||
if(this.command.indexOf('://')!==-1) {
|
||||
text = '<span class="text-info">' +this.scope.toFriendlyName(this,this.command) + '</span>';
|
||||
}
|
||||
return this.getBlockIcon('D') + 'Set Properties : ' + text;
|
||||
},
|
||||
serializeObject:function(field){
|
||||
return field === 'props';
|
||||
},
|
||||
onChangeField:function(field){
|
||||
if(field==='command'){
|
||||
delete this.props;
|
||||
this.props = {};
|
||||
}
|
||||
},
|
||||
init:function(){
|
||||
if(this.props && _.isString(this.props)){
|
||||
this.props = utils.fromJson(this.props);
|
||||
}
|
||||
|
||||
},
|
||||
getFields:function(){
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
fields.push(utils.createCI('value','xcf.widgets.CommandPicker',this.command,{
|
||||
group:'General',
|
||||
title:'Command',
|
||||
dst:'command',
|
||||
options:this.scope.getCommandsAsOptions(),
|
||||
block:this,
|
||||
pickerType:'command',
|
||||
value:this.command
|
||||
}));
|
||||
var block = this.scope.resolveBlock(this.command);
|
||||
if(block && block.getFields){
|
||||
if(!this.props){
|
||||
this.props = {};
|
||||
}
|
||||
var _fields = block.getFields();
|
||||
var descr = _.find(_fields,{
|
||||
dst:"description"
|
||||
});
|
||||
_fields.remove(descr);
|
||||
_.each(_fields,function(_field){
|
||||
_field.group = "Properties";
|
||||
_field.value = utils.getAt(this.props,_field.dst,_field.value);
|
||||
_field.dst = "props." + _field.dst;
|
||||
|
||||
},this);
|
||||
fields = fields.concat(_fields);
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,76 @@
|
||||
/** @module xblox/model/functions/StopBlock **/
|
||||
define([
|
||||
'dcl/dcl',
|
||||
'xide/utils',
|
||||
"xblox/model/Block"
|
||||
], function(dcl,utils,Block){
|
||||
/**
|
||||
* @augments module:xide/mixins/EventedMixin
|
||||
* @lends module:xblox/model/Block_UI
|
||||
* @extends module:xblox/model/Block
|
||||
* @extends module:xblox/model/ModelBase
|
||||
*/
|
||||
return dcl(Block,{
|
||||
declaredClass:"xblox.model.functions.StopBlock",
|
||||
command:'Select command please',
|
||||
icon:'',
|
||||
args:null,
|
||||
_timeout:100,
|
||||
hasInlineEdits:true,
|
||||
solve:function(scope,settings) {
|
||||
if (this.command){
|
||||
var block = scope.resolveBlock(this.command);
|
||||
if(block && block.stop){
|
||||
var res = block.stop();
|
||||
this.onSuccess(this,settings);
|
||||
}else{
|
||||
this.onFailed(this,settings);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param field
|
||||
* @param pos
|
||||
* @param type
|
||||
* @param title
|
||||
* @param mode: inline | popup
|
||||
* @returns {string}
|
||||
*/
|
||||
makeEditable:function(field,pos,type,title,mode){
|
||||
return "<a tabIndex=\"-1\" pos='" + pos +"' display-mode='" + (mode||'popup') + "' display-type='" + (type || 'text') +"' data-prop='" + field + "' data-title='" + title + "' class='editable editable-click' href='#'>" + this[field] +"</a>";
|
||||
},
|
||||
getFieldOptions:function(field){
|
||||
if(field ==="command"){
|
||||
return this.scope.getCommandsAsOptions("text");
|
||||
}
|
||||
},
|
||||
toText:function(){
|
||||
var text = 'Unknown';
|
||||
var block = this.scope.getBlock(this.command);
|
||||
if(block){
|
||||
text = block.name;
|
||||
}
|
||||
if(this.command.indexOf('://')!==-1) {
|
||||
text = '<span class="text-info">' +this.scope.toFriendlyName(this,this.command) + '</span>';
|
||||
}
|
||||
return this.getBlockIcon('D') + 'Stop Command : ' + text;
|
||||
},
|
||||
onChangeField:function(what,value){
|
||||
},
|
||||
getFields:function(){
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
fields.push(utils.createCI('value','xcf.widgets.CommandPicker',this.command,{
|
||||
group:'General',
|
||||
title:'Command',
|
||||
dst:'command',
|
||||
options:this.scope.getCommandsAsOptions(),
|
||||
block:this,
|
||||
pickerType:'command',
|
||||
value:this.command
|
||||
}));
|
||||
return fields;
|
||||
}
|
||||
});
|
||||
});
|
||||
109
packages/xblox/ref-control-freak/xblox/model/html/SetCSS.js
Normal file
109
packages/xblox/ref-control-freak/xblox/model/html/SetCSS.js
Normal file
@ -0,0 +1,109 @@
|
||||
define([
|
||||
"dojo/_base/declare",
|
||||
"xblox/model/Block",
|
||||
'xide/utils',
|
||||
'xide/types',
|
||||
'xide/mixins/EventedMixin',
|
||||
'xblox/model/Targeted'
|
||||
], function(declare,Block,utils,types,EventedMixin,Targeted){
|
||||
/**
|
||||
* @augments module:xide/mixins/EventedMixin
|
||||
* @lends module:xblox/model/Block_UI
|
||||
* @extends module:xblox/model/Block
|
||||
* @extends module:xblox/model/ModelBase
|
||||
*/
|
||||
return declare("xblox.model.html.SetCSS",[Block,EventedMixin,Targeted],{
|
||||
//method: (String)
|
||||
// block name
|
||||
name:'Set CSS',
|
||||
file:'',
|
||||
reference:'',
|
||||
references:null,
|
||||
description:'Sets HTML Node CSS',
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UI
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
solve:function(scope,settings) {
|
||||
this.onSuccess(this,settings);
|
||||
},
|
||||
toText:function(){
|
||||
var result = this.getBlockIcon() + ' ' + this.name + ' :: ';
|
||||
if(this.event){
|
||||
result+= this.event;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
// standard call for editing
|
||||
getFields:function(){
|
||||
try {
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
fields.push(utils.createCI('File', types.ECIType.FILE, this.file, {
|
||||
group: 'General',
|
||||
dst: 'file',
|
||||
value: this.file,
|
||||
intermediateChanges: false,
|
||||
acceptFolders: false,
|
||||
acceptFiles: true,
|
||||
encodeFilePath: false,
|
||||
buildFullPath: true,
|
||||
filePickerOptions: {
|
||||
dialogTitle: 'Select CSS File',
|
||||
filePickerMixin: {
|
||||
beanContextName: 'CSSFilePicker',
|
||||
persistent: false,
|
||||
globalPanelMixin: {
|
||||
allowLayoutCookies: false
|
||||
}
|
||||
},
|
||||
configMixin: {
|
||||
beanContextName: 'CSSFilePicker',
|
||||
LAYOUT_PRESET: types.LAYOUT_PRESET.SINGLE,
|
||||
PANEL_OPTIONS:{
|
||||
ALLOW_MAIN_MENU:false
|
||||
}
|
||||
},
|
||||
defaultStoreOptions: {
|
||||
"fields": 1663,
|
||||
"includeList": "css",
|
||||
"excludeList": "*"
|
||||
},
|
||||
startPath: this.file
|
||||
}
|
||||
}));
|
||||
fields.push(utils.createCI('Target', types.ECIType.WIDGET_REFERENCE, this.reference, {
|
||||
group: 'General',
|
||||
dst: 'reference',
|
||||
value: this.reference
|
||||
}));
|
||||
|
||||
}catch(e){
|
||||
|
||||
}
|
||||
return fields;
|
||||
},
|
||||
getBlockIcon:function(){
|
||||
return '<span class="fa-paint-brush"></span>';
|
||||
},
|
||||
onReferenceChanged:function(newValue){
|
||||
this._destroy();//unregister previous event(s)
|
||||
this.reference = newValue;
|
||||
},
|
||||
onChangeField:function(field,newValue,cis){
|
||||
if(field=='reference'){
|
||||
this.onReferenceChanged(newValue,cis);
|
||||
}
|
||||
this.inherited(arguments);
|
||||
},
|
||||
activate:function(){
|
||||
this._destroy();
|
||||
},
|
||||
deactivate:function(){
|
||||
this._destroy();
|
||||
},
|
||||
_destroy:function(){
|
||||
}
|
||||
});
|
||||
});
|
||||
258
packages/xblox/ref-control-freak/xblox/model/html/SetState.js
Normal file
258
packages/xblox/ref-control-freak/xblox/model/html/SetState.js
Normal file
@ -0,0 +1,258 @@
|
||||
define([
|
||||
"dcl/dcl",
|
||||
"xblox/model/Block",
|
||||
'xide/utils',
|
||||
'xide/types',
|
||||
'xide/mixins/EventedMixin',
|
||||
'xblox/model/Referenced',
|
||||
"dojo/dom-attr",
|
||||
"dojo/dom-style",
|
||||
"dojo/_base/Color",
|
||||
"xide/registry"
|
||||
], function (dcl, Block, utils, types, EventedMixin, Referenced, domAttr, domStyle, Color, registry) {
|
||||
/**
|
||||
* @augments module:xide/mixins/EventedMixin
|
||||
* @lends module:xblox/model/Block_UI
|
||||
* @extends module:xblox/model/Block
|
||||
* @extends module:xblox/model/ModelBase
|
||||
*/
|
||||
var Impl = {
|
||||
declaredClass: "xblox.model.html.SetState",
|
||||
name: 'Set State',
|
||||
reference: '',
|
||||
references: null,
|
||||
description: 'Switches to a state',
|
||||
value: '',
|
||||
mode: 1,
|
||||
sharable: false,
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UI
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Run this block
|
||||
* @param scope
|
||||
* @param settings
|
||||
*/
|
||||
solve: function (scope, settings) {
|
||||
var value = this.value;
|
||||
settings = settings || {};
|
||||
settings.flags = types.CIFLAG.DONT_PARSE;
|
||||
var objects = this.resolveReference(this.deserialize(this.reference), settings);
|
||||
if (this.override && this.override.variables) {
|
||||
value = utils.replace(value, null, this.override.variables, {
|
||||
begin: '{',
|
||||
end: '}'
|
||||
});
|
||||
}
|
||||
if (objects && objects.length) {
|
||||
_.each(objects, function (object) {
|
||||
var widget = object
|
||||
var _widget = registry.byId(widget.id) || widget;
|
||||
if (widget != _widget) {
|
||||
|
||||
}
|
||||
if (_widget && _widget.setState) {
|
||||
_widget.setState(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
this.onSuccess(this, settings);
|
||||
this.onDidRun(); //clear overrides
|
||||
},
|
||||
/**
|
||||
* Get human readable string for the UI
|
||||
* @returns {string}
|
||||
*/
|
||||
toText: function () {
|
||||
var _ref = this.deserialize(this.reference);
|
||||
var result = this.getBlockIcon() + ' ' + this.name + ' :: on ' + (_ref.reference || 'this' ) + ' to' || ' ' + ' to ';
|
||||
if (this.value) {
|
||||
result += ' ' + this.value;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
/**
|
||||
* Standard call when editing this block
|
||||
* @returns {*}
|
||||
*/
|
||||
getFields: function () {
|
||||
var fields = this.getDefaultFields(false);
|
||||
var referenceArgs = {
|
||||
group: 'General',
|
||||
dst: 'reference',
|
||||
value: this.reference
|
||||
};
|
||||
fields.push(utils.createCI('State', types.ECIType.STRING, this.value, {
|
||||
group: 'General',
|
||||
dst: 'value',
|
||||
value: this.value,
|
||||
intermediateChanges: false
|
||||
}));
|
||||
fields.push(utils.createCI('Target', types.ECIType.WIDGET_REFERENCE, this.reference, referenceArgs));
|
||||
return fields;
|
||||
},
|
||||
getBlockIcon: function () {
|
||||
return '<span class="fa-paint-brush"></span>';
|
||||
},
|
||||
getPropValue: function (stylesObject, prop) {
|
||||
for (var _prop in stylesObject) {
|
||||
if (_prop === prop) {
|
||||
return stylesObject[_prop];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
updateObject: function (obj, style, mode) {
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
mode = mode || 1;
|
||||
if (obj.domNode != null) {
|
||||
obj = obj.domNode;
|
||||
}
|
||||
var currentStyle = domAttr.get(obj, 'style');
|
||||
if (currentStyle === ";") {
|
||||
currentStyle = "";
|
||||
}
|
||||
if (currentStyle === "") {
|
||||
if (obj['lastStyle'] != null) {
|
||||
currentStyle = obj['lastStyle'];
|
||||
} else {
|
||||
currentStyle = style;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentStyle === ";") {
|
||||
currentStyle = style;
|
||||
}
|
||||
switch (mode) {
|
||||
//set
|
||||
case 1:
|
||||
{
|
||||
var currentStyleMap = this._toObject(currentStyle);
|
||||
var props = style.split(';');
|
||||
for (var i = 0; i < props.length; i++) {
|
||||
var _style = props[i].split(':');
|
||||
if (_style.length == 2) {
|
||||
currentStyleMap[_style[0]] = _style[1];
|
||||
}
|
||||
}
|
||||
var styles = [];
|
||||
for (var p in currentStyleMap) {
|
||||
styles.push(p + ':' + currentStyleMap[p]);
|
||||
}
|
||||
$(obj).attr('style', styles.join(';'));
|
||||
break;
|
||||
}
|
||||
//add
|
||||
case 2:
|
||||
{
|
||||
var _newStyle = currentStyle + ';' + style,
|
||||
_newStyleT = _.uniq(_newStyle.split(';')).join(';');
|
||||
domAttr.set(obj, 'style', _newStyleT);
|
||||
break;
|
||||
}
|
||||
//remove
|
||||
case 3:
|
||||
{
|
||||
domAttr.set(obj, 'style', utils.replaceAll(style, '', currentStyle));
|
||||
break;
|
||||
}
|
||||
//increase
|
||||
case 4:
|
||||
//decrease
|
||||
case 5:
|
||||
{
|
||||
var numbersOnlyRegExp = new RegExp(/(\D*)(-?)(\d+)(\D*)/);
|
||||
/**
|
||||
* compute current style values of the object
|
||||
* @type {{}}
|
||||
*/
|
||||
var stylesRequested = this._toObject(style);
|
||||
var stylesComputed = {};
|
||||
var jInstance = $(obj);
|
||||
///determine from node it self
|
||||
if (stylesRequested) {
|
||||
for (var prop in stylesRequested) {
|
||||
stylesComputed[prop] = this._getStyle(prop, obj, jInstance);
|
||||
}
|
||||
}
|
||||
|
||||
var _newStyleObject = {};
|
||||
/**
|
||||
* compute the new style
|
||||
* @type {number}
|
||||
*/
|
||||
for (var prop in stylesRequested) {
|
||||
var _prop = '' + prop.trim();
|
||||
var multiplicator = 1;
|
||||
if (stylesComputed[_prop] != null) {
|
||||
|
||||
var _valueRequested = stylesRequested[prop];
|
||||
var _valueComputed = stylesComputed[prop];
|
||||
|
||||
var _isHex = _valueRequested.indexOf('#') != -1;
|
||||
var _isRGB = _valueRequested.indexOf('rgb') != -1;
|
||||
var _isRGBA = _valueRequested.indexOf('rgba') != -1;
|
||||
|
||||
if (_isHex || _isRGB || _isRGBA) {
|
||||
|
||||
var dColorMultiplicator = dojo.colorFromString(_valueRequested);
|
||||
var dColorNow = dojo.colorFromString(_valueRequested);
|
||||
var dColorComputed = dojo.colorFromString(_valueComputed);
|
||||
var dColorNew = new Color();
|
||||
|
||||
_.each(["r", "g", "b", "a"], function (x) {
|
||||
dColorNew[x] = Math.min(dColorComputed[x] + dColorMultiplicator[x], x == "a" ? 1 : 255);
|
||||
});
|
||||
|
||||
var _valueOut = '';
|
||||
if (_isHex) {
|
||||
_valueOut = dColorNew.toHex();
|
||||
} else if (_isRGB) {
|
||||
_valueOut = dColorNew.toCss(false);
|
||||
} else if (_isRGBA) {
|
||||
_valueOut = dColorNew.toCss(true);
|
||||
}
|
||||
_newStyleObject[prop] = _valueOut;
|
||||
domStyle.set(obj, prop, _valueOut);
|
||||
|
||||
|
||||
} else {
|
||||
//extract actual number :
|
||||
var numberOnly = numbersOnlyRegExp.exec(stylesComputed[_prop]);
|
||||
if (numberOnly && numberOnly.length >= 3) {
|
||||
var _int = parseInt(numberOnly[3]);
|
||||
if (_int && _int > 0) {
|
||||
multiplicator = _int;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//now get an object array of the styles we'd like to alter
|
||||
var styles = this._toObject(currentStyle);
|
||||
if (!styles) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
activate: function () {
|
||||
this._destroy(); //you never know
|
||||
},
|
||||
deactivate: function () {
|
||||
this._destroy();
|
||||
}
|
||||
};
|
||||
|
||||
//package via declare
|
||||
var _class = dcl([Block, EventedMixin.dcl, Referenced.dcl], Impl);
|
||||
//static access to Impl.
|
||||
_class.Impl = Impl;
|
||||
return _class;
|
||||
|
||||
});
|
||||
489
packages/xblox/ref-control-freak/xblox/model/html/SetStyle.js
Normal file
489
packages/xblox/ref-control-freak/xblox/model/html/SetStyle.js
Normal file
@ -0,0 +1,489 @@
|
||||
/** @module xblox/model/html/SetStyle **/
|
||||
define([
|
||||
"dcl/dcl",
|
||||
"xblox/model/Block",
|
||||
'xide/utils',
|
||||
'xide/types',
|
||||
'xide/mixins/EventedMixin',
|
||||
'xblox/model/Referenced',
|
||||
"dojo/dom-attr",
|
||||
"dojo/dom-style",
|
||||
"dojo/_base/Color",
|
||||
"xide/registry"
|
||||
// not loaded yet
|
||||
], function (dcl, Block, utils, types, EventedMixin, Referenced, domAttr, domStyle, Color, registry) {
|
||||
|
||||
var debug = false;
|
||||
/**
|
||||
* @augments module:xide/mixins/EventedMixin
|
||||
* @lends module:xblox/model/Block_UI
|
||||
* @extends module:xblox/model/Block
|
||||
* @extends module:xblox/model/ModelBase
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* @class module:xblox/model/html/SetStyle
|
||||
* @extends module:xblox/model/Block
|
||||
*/
|
||||
var Impl = {
|
||||
declaredClass: "xblox.model.html.SetStyle",
|
||||
name: 'Set Style',
|
||||
reference: '',
|
||||
references: null,
|
||||
description: 'Sets HTML Node Style Attribute',
|
||||
value: '',
|
||||
mode: 1,
|
||||
sharable: true,
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UI
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
*
|
||||
* @param params (object in that format : reference(string) | mode (string))
|
||||
*/
|
||||
/**
|
||||
* Run this block
|
||||
* @param scope
|
||||
* @param settings
|
||||
*/
|
||||
solve: function (scope, settings) {
|
||||
debug && console.log('-set style solve');
|
||||
var value = this.value;
|
||||
settings = settings || {};
|
||||
var override = settings.override || this.override || {};
|
||||
|
||||
if (override.variables) {
|
||||
value = utils.replace(value, null, override.variables, {
|
||||
begin: '{',
|
||||
end: '}'
|
||||
});
|
||||
}
|
||||
|
||||
if (override.args && override.args[0] !== null) {
|
||||
value = utils.replace(value, null, {value: override.args[0]}, {
|
||||
begin: '{',
|
||||
end: '}'
|
||||
});
|
||||
}
|
||||
this.updateObjects(null, value, this.mode, settings);
|
||||
this.onSuccess(this, settings);
|
||||
this.onDidRun();
|
||||
},
|
||||
/**
|
||||
* Get human readable string for the UI
|
||||
* @returns {string}
|
||||
*/
|
||||
toText: function () {
|
||||
var _ref = this.deserialize(this.reference);
|
||||
var result = this.getBlockIcon() + ' ' + this.name + ' :: on ' + _ref.reference + ' to' || ' ' + ' to ';
|
||||
if (this.value) {
|
||||
result += ' ' + this.value;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
/**
|
||||
* Standard call when editing this block
|
||||
* @returns {*}
|
||||
*/
|
||||
getFields: function () {
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
fields.push(utils.createCI('Value', types.ECIType.DOM_PROPERTIES, this.value, {
|
||||
group: 'General',
|
||||
dst: 'value',
|
||||
value: this.value,
|
||||
intermediateChanges: false
|
||||
}));
|
||||
fields.push(utils.createCI('Mode', types.ECIType.ENUMERATION, this.mode, {
|
||||
group: 'General',
|
||||
options: [
|
||||
utils.createOption('Set', 1),
|
||||
utils.createOption('Add', 2),
|
||||
utils.createOption('Remove', 3),
|
||||
utils.createOption('Increase', 4),
|
||||
utils.createOption('Decrease', 5)
|
||||
],
|
||||
dst: 'mode'
|
||||
}));
|
||||
var referenceArgs = {
|
||||
group: 'General',
|
||||
dst: 'reference',
|
||||
value: this.reference
|
||||
};
|
||||
|
||||
if (this.scope) {
|
||||
if (this.scope.global) {
|
||||
referenceArgs.window = this.scope.global;
|
||||
referenceArgs.allowHTMLNodes = true;
|
||||
referenceArgs.allowWidgets = false;
|
||||
|
||||
}
|
||||
if (this.scope.document) {
|
||||
referenceArgs.document = this.scope.document;
|
||||
}
|
||||
}
|
||||
fields.push(utils.createCI('Target', types.ECIType.WIDGET_REFERENCE, this.reference, referenceArgs));
|
||||
|
||||
return fields;
|
||||
},
|
||||
getBlockIcon: function () {
|
||||
return '<span class="fa-paint-brush"></span>';
|
||||
},
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Lifecycle
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
updateEventSelector: function (objects, cis) {
|
||||
var options = [];
|
||||
if (!objects || !objects.length) {
|
||||
options = this.scope.getEventsAsOptions(this.event);
|
||||
} else {
|
||||
options = [{label: "onclick", value: "onclick"},
|
||||
{label: "ondblclick", value: "ondblclick"},
|
||||
{label: "onmousedown", value: "onmousedown"},
|
||||
{label: "onmouseup", value: "onmouseup"},
|
||||
{label: "onmouseover", value: "onmouseover"},
|
||||
{label: "onmousemove", value: "onmousemove"},
|
||||
{label: "onmouseout", value: "onmouseout"},
|
||||
{label: "onkeypress", value: "onkeypress"},
|
||||
{label: "onkeydown", value: "onkeydown"},
|
||||
{label: "onkeyup", value: "onkeyup"},
|
||||
{label: "onfocus", value: "onfocus"},
|
||||
{label: "onblur", value: "onblur"},
|
||||
{label: "onchange", value: "onchange"}];
|
||||
|
||||
//select the event we are listening to
|
||||
for (var i = 0; i < options.length; i++) {
|
||||
var obj = options[i];
|
||||
if (obj.value === this.event) {
|
||||
obj.selected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < cis.length; i++) {
|
||||
var ci = cis[i];
|
||||
if (ci['widget'] && ci['widget'].title === 'Event') {
|
||||
var widget = ci['_widget'];
|
||||
widget.nativeWidget.set('options', options);
|
||||
widget.nativeWidget.reset();
|
||||
widget.nativeWidget.set('value', this.event);
|
||||
this.publish(types.EVENTS.RESIZE, {});
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
onReferenceChanged: function (newValue, cis, settings) {
|
||||
this.reference = newValue;
|
||||
this.references = this.resolveReference(this.deserialize(newValue), settings);
|
||||
this.updateObjects(this.references, this.value, null, settings);
|
||||
},
|
||||
getPropValue: function (stylesObject, prop) {
|
||||
for (var _prop in stylesObject) {
|
||||
if (_prop === prop) {
|
||||
return stylesObject[_prop];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
_getStyle: function (name, obj, jObj) {
|
||||
switch (name) {
|
||||
case "height": {
|
||||
return jObj.outerHeight();
|
||||
}
|
||||
case "width": {
|
||||
return jObj.outerWidth();
|
||||
}
|
||||
case "color": {
|
||||
return jObj.css("color");
|
||||
}
|
||||
case "border-color": {
|
||||
return jObj.css("border-color") || "rgba(0,0,0,0)";
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
updateObject: function (obj, style, mode, settings) {
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
mode = mode || 1;
|
||||
|
||||
var _obj = obj.id ? registry.byId(obj.id) : null;
|
||||
if (_obj) {
|
||||
obj = _obj;
|
||||
}
|
||||
|
||||
if (obj.domNode != null) {
|
||||
obj = obj.domNode;
|
||||
}
|
||||
var currentStyle = domAttr.get(obj, 'style');
|
||||
if (currentStyle === ";") {
|
||||
currentStyle = "";
|
||||
}
|
||||
if (currentStyle === "") {
|
||||
if (obj['lastStyle'] != null) {
|
||||
currentStyle = obj['lastStyle'];
|
||||
} else {
|
||||
currentStyle = style;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentStyle === ";") {
|
||||
currentStyle = style;
|
||||
}
|
||||
switch (mode) {
|
||||
//set
|
||||
case 1: {
|
||||
|
||||
var currentStyleMap = this._toObject(currentStyle);
|
||||
var props = style.split(';');
|
||||
var css = {};
|
||||
for (var i = 0; i < props.length; i++) {
|
||||
var _style = props[i].split(':');
|
||||
if (_style.length == 2) {
|
||||
currentStyleMap[_style[0]] = _style[1];
|
||||
}
|
||||
}
|
||||
var styles = [];
|
||||
for (var p in currentStyleMap) {
|
||||
styles.push(p + ':' + currentStyleMap[p]);
|
||||
}
|
||||
$(obj).attr('style', styles.join(';'));
|
||||
break;
|
||||
}
|
||||
//add
|
||||
case 2: {
|
||||
|
||||
var _newStyle = currentStyle + ';' + style,
|
||||
_newStyleT = _.uniq(_newStyle.split(';')).join(';');
|
||||
|
||||
domAttr.set(obj, 'style', _newStyleT);
|
||||
break;
|
||||
}
|
||||
//remove
|
||||
case 3: {
|
||||
domAttr.set(obj, 'style', utils.replaceAll(style, '', currentStyle));
|
||||
break;
|
||||
}
|
||||
//increase
|
||||
case 4:
|
||||
//decrease
|
||||
case 5: {
|
||||
var numbersOnlyRegExp = new RegExp(/(\D*)(-?)(\d+)(\D*)/);
|
||||
/**
|
||||
* compute current style values of the object
|
||||
* @type {{}}
|
||||
*/
|
||||
var stylesRequested = this._toObject(style);
|
||||
var stylesComputed = {};
|
||||
var jInstance = $(obj);
|
||||
///determine from node it self
|
||||
if (stylesRequested) {
|
||||
for (var prop in stylesRequested) {
|
||||
var currentStyle = this._getStyle(prop, obj, jInstance);
|
||||
stylesComputed[prop] = currentStyle;
|
||||
}
|
||||
}
|
||||
|
||||
var _newStyleObject = {};
|
||||
/**
|
||||
* compute the new style
|
||||
* @type {number}
|
||||
*/
|
||||
for (var prop in stylesRequested) {
|
||||
var _prop = '' + prop.trim();
|
||||
var multiplicator = 1;
|
||||
if (stylesComputed[_prop] != null) {
|
||||
|
||||
var _valueRequested = stylesRequested[prop];
|
||||
var _valueComputed = stylesComputed[prop];
|
||||
|
||||
var _isHex = _valueRequested.indexOf('#') != -1;
|
||||
var _isRGB = _valueRequested.indexOf('rgb') != -1;
|
||||
var _isRGBA = _valueRequested.indexOf('rgba') != -1;
|
||||
|
||||
if (_isHex || _isRGB || _isRGBA) {
|
||||
|
||||
var dColorMultiplicator = dojo.colorFromString(_valueRequested);
|
||||
var dColorNow = dojo.colorFromString(_valueRequested);
|
||||
var dColorComputed = dojo.colorFromString(_valueComputed);
|
||||
var dColorNew = new Color();
|
||||
|
||||
_.each(["r", "g", "b", "a"], function (x) {
|
||||
dColorNew[x] = Math.min(dColorComputed[x] + dColorMultiplicator[x], x == "a" ? 1 : 255);
|
||||
});
|
||||
|
||||
console.log('color computed ' + dColorComputed.toRgba() + ' color requested: ' + dColorNow.toRgba() + ' | multiplicator color = ' + dColorMultiplicator.toRgba() + ' is then = ' + dColorNew.toRgba());
|
||||
|
||||
var _valueOut = '';
|
||||
if (_isHex) {
|
||||
_valueOut = dColorNew.toHex();
|
||||
} else if (_isRGB) {
|
||||
_valueOut = dColorNew.toCss(false);
|
||||
} else if (_isRGBA) {
|
||||
_valueOut = dColorNew.toCss(true);
|
||||
}
|
||||
_newStyleObject[prop] = _valueOut;
|
||||
domStyle.set(obj, prop, _valueOut);
|
||||
|
||||
} else {
|
||||
//extract actual number :
|
||||
var numberOnly = numbersOnlyRegExp.exec(stylesComputed[_prop]);
|
||||
if (numberOnly && numberOnly.length >= 3) {
|
||||
var _int = parseInt(numberOnly[3]);
|
||||
if (_int && _int > 0) {
|
||||
multiplicator = _int;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var delta = mode == 4 ? 1 : -1;
|
||||
//now get an object array of the styles we'd like to alter
|
||||
var styles = this._toObject(currentStyle);
|
||||
var inStyles = this._toObject(style);
|
||||
if (!styles) {
|
||||
return false;
|
||||
}
|
||||
var _skipped = [];
|
||||
for (var prop in styles) {
|
||||
var _prop = '' + prop.trim();
|
||||
}
|
||||
|
||||
var newStyleString = this._toStyleString(_newStyleObject);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
onDomStyleChanged: function (objects, newStyle, mode, settings) {
|
||||
objects = objects || this.resolveReference(this.deserialize(this.reference), settings);
|
||||
if (!objects) {
|
||||
debug && console.warn('have no objects');
|
||||
return;
|
||||
}
|
||||
debug && console.log('change dom style to ' + newStyle + ' on ' + objects.length + ' objects');
|
||||
for (var i = 0; i < objects.length; i++) {
|
||||
var obj = objects[i];
|
||||
if (obj && obj.id && obj.id.indexOf('davinci') != -1) {
|
||||
continue;
|
||||
}
|
||||
this.updateObject(obj, newStyle, mode, settings);
|
||||
}
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param objects
|
||||
* @param domStyleString
|
||||
* @param mode
|
||||
* @param settings
|
||||
*/
|
||||
updateObjects: function (objects, domStyleString, mode, settings) {
|
||||
objects = objects || this.resolveReference(this.deserialize(this.reference), settings);
|
||||
this.onDomStyleChanged(objects, domStyleString, mode, settings);
|
||||
},
|
||||
onChangeField: function (field, newValue, cis) {
|
||||
this._destroy();
|
||||
if (field == 'mode' && newValue !== this.mode) {
|
||||
this.mode = newValue;
|
||||
}
|
||||
if (field == 'value' && newValue !== this.value) {
|
||||
this.onDomStyleChanged(null, newValue, this.mode);
|
||||
this.value = newValue;
|
||||
}
|
||||
if (field == 'reference') {
|
||||
this.onReferenceChanged(newValue, cis);
|
||||
}
|
||||
this.inherited(arguments);
|
||||
},
|
||||
activate: function () {
|
||||
this._destroy();//you never know
|
||||
},
|
||||
deactivate: function () {
|
||||
this._destroy();
|
||||
},
|
||||
_destroy: function () {
|
||||
|
||||
},
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Utils
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
_changeValue: function (value, delta) {
|
||||
if (!value) {
|
||||
return "";
|
||||
}
|
||||
var split = value.split(" ");
|
||||
var result = "";
|
||||
for (var i = 0; i < split.length; i++) {
|
||||
if (i > 0)
|
||||
result += " ";
|
||||
var bits = split[i].match(/([-\d\.]+)([a-zA-Z%]*)/);
|
||||
if (!bits) {
|
||||
result += split[i];
|
||||
} else {
|
||||
if (bits.length == 1) {
|
||||
result += bits[0];
|
||||
} else {
|
||||
for (var z = 1; z < bits.length; z++) {
|
||||
if (!isNaN(bits[z]) && bits[z] != "") {
|
||||
result += parseFloat(bits[z]) + delta;
|
||||
} else {
|
||||
result += bits[z];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
/**
|
||||
* Convert Style String to an object array, eg: { color:value,.... }
|
||||
* @param styleString
|
||||
* @returns {{}}
|
||||
* @private
|
||||
*/
|
||||
_toObject: function (styleString) {
|
||||
if (!styleString) {
|
||||
return {};
|
||||
}
|
||||
var _result = {};
|
||||
var _values = styleString.split(';');
|
||||
for (var i = 0; i < _values.length; i++) {
|
||||
var obj = _values[i];
|
||||
if (!obj || obj.length == 0 || !obj.split) {
|
||||
continue;
|
||||
}
|
||||
var keyVal = obj.split(':');
|
||||
if (!keyVal || !keyVal.length) {
|
||||
continue;
|
||||
}
|
||||
var key = obj.substring(0, obj.indexOf(':'));
|
||||
var value = obj.substring(obj.indexOf(':') + 1, obj.length);
|
||||
|
||||
_result[key] = value;
|
||||
}
|
||||
return _result;
|
||||
},
|
||||
_toStyleString: function (values) {
|
||||
var _values = [];
|
||||
for (var prop in values) {
|
||||
_values.push(prop + ':' + values[prop]);
|
||||
}
|
||||
return _values.join(';') + ';';
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//package via declare
|
||||
var _class = dcl([Block, Referenced.dcl], Impl);
|
||||
//static access to Impl.
|
||||
_class.Impl = Impl;
|
||||
return _class;
|
||||
|
||||
});
|
||||
183
packages/xblox/ref-control-freak/xblox/model/logging/Log.js
Normal file
183
packages/xblox/ref-control-freak/xblox/model/logging/Log.js
Normal file
@ -0,0 +1,183 @@
|
||||
define([
|
||||
'dcl/dcl',
|
||||
"dojo/Deferred",
|
||||
"xblox/model/Block",
|
||||
'xide/utils',
|
||||
'xide/types',
|
||||
'xide/mixins/EventedMixin'
|
||||
], function (dcl, Deferred, Block, utils, types, EventedMixin) {
|
||||
/**
|
||||
* @augments module:xide/mixins/EventedMixin
|
||||
* @lends module:xblox/model/Block_UI
|
||||
* @extends module:xblox/model/Block
|
||||
* @extends module:xblox/model/ModelBase
|
||||
*/
|
||||
return dcl([Block, EventedMixin.dcl], {
|
||||
declaredClass: "xblox.model.logging.Log",
|
||||
name: 'Log Message',
|
||||
level: 'info',
|
||||
message: 'return "Message: " + arguments[0];',
|
||||
_type: 'XBlox',
|
||||
host: 'this host',
|
||||
sharable: true,
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UI
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
toText: function () {
|
||||
var _cls = 'text-primary';
|
||||
switch (this.level) {
|
||||
case 'info': {
|
||||
_cls = 'text-info';
|
||||
break;
|
||||
}
|
||||
case 'warn': {
|
||||
_cls = 'text-warning';
|
||||
break;
|
||||
}
|
||||
case 'error': {
|
||||
_cls = 'text-danger';
|
||||
break;
|
||||
}
|
||||
}
|
||||
var result = this.getBlockIcon() + " " + this.name + " : " + "<span class='" + _cls + " small'> " + ' :: ';
|
||||
if (this.message) {
|
||||
result += this.message;
|
||||
}
|
||||
return result + "</span>";
|
||||
},
|
||||
/***
|
||||
* Returns the block run result
|
||||
* @param expression
|
||||
* @param scope
|
||||
* @param settings
|
||||
* @param run
|
||||
* @param error
|
||||
* @returns {string}
|
||||
*/
|
||||
_solveExpression: function (expression, scope, settings, run, error) {
|
||||
var _script = '' + expression;
|
||||
if (_script && _script.length) {
|
||||
_script = utils.convertAllEscapes(_script, "none");
|
||||
var _args = this.getArgs();
|
||||
try {
|
||||
var _parsed = scope.parseExpression(_script, null, null, null, null, this, _args);
|
||||
if (run) {
|
||||
run('Expression ' + _script + ' evaluates to ' + _parsed);
|
||||
}
|
||||
return _parsed;
|
||||
} catch (e) {
|
||||
if (error) {
|
||||
error('invalid expression : \n' + _script + ': ' + e);
|
||||
}
|
||||
this.onFailed(this, settings);
|
||||
return _script;
|
||||
}
|
||||
}
|
||||
return _script;
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param scope
|
||||
* @param settings
|
||||
* @param run
|
||||
* @param error
|
||||
*/
|
||||
solve: function (scope, settings, run, error) {
|
||||
var dfd = new Deferred();
|
||||
var device = scope.device;
|
||||
var _message = this._solveExpression(this.message, scope, settings, run, error);
|
||||
var message = {
|
||||
message: _message,
|
||||
level: this.level,
|
||||
type: this._type,
|
||||
details: this.getArgs(),
|
||||
time: new Date().getTime(),
|
||||
data: {
|
||||
device: device ? device.info : null
|
||||
},
|
||||
write: true
|
||||
};
|
||||
this.onSuccess(this, settings);
|
||||
dfd.resolve(_message);
|
||||
try {
|
||||
this.publish(types.EVENTS.ON_SERVER_LOG_MESSAGE, message);
|
||||
} catch (e) {
|
||||
this.onFailed(this, settings);
|
||||
}
|
||||
|
||||
return dfd;
|
||||
|
||||
},
|
||||
// standard call from interface
|
||||
canAdd: function () {
|
||||
return null;
|
||||
},
|
||||
// standard call for editing
|
||||
getFields: function () {
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
var thiz = this;
|
||||
var options = [
|
||||
{
|
||||
value: 'info',
|
||||
label: 'Info'
|
||||
},
|
||||
{
|
||||
value: 'warn',
|
||||
label: 'Warning'
|
||||
},
|
||||
{
|
||||
value: 'error',
|
||||
label: 'Error'
|
||||
},
|
||||
{
|
||||
value: 'debug',
|
||||
label: 'Debug'
|
||||
},
|
||||
{
|
||||
value: 'help',
|
||||
label: 'Help'
|
||||
},
|
||||
{
|
||||
value: 'verbose',
|
||||
label: 'verbose'
|
||||
},
|
||||
{
|
||||
value: 'silly',
|
||||
label: 'Silly'
|
||||
}
|
||||
];
|
||||
|
||||
fields.push(utils.createCI('Level', 3, this.level, {
|
||||
group: 'General',
|
||||
options: options,
|
||||
dst: 'level'
|
||||
}));
|
||||
|
||||
fields.push(
|
||||
utils.createCI('message', 25, this.message, {
|
||||
group: 'General',
|
||||
title: 'Message',
|
||||
dst: 'message',
|
||||
delegate: {
|
||||
runExpression: function (val, run, error) {
|
||||
thiz._solveExpression(val, thiz.scope, null, run, error);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
fields.push(
|
||||
utils.createCI('message', 13, this._type, {
|
||||
group: 'General',
|
||||
title: 'Type',
|
||||
dst: '_type'
|
||||
}));
|
||||
|
||||
return fields;
|
||||
},
|
||||
getBlockIcon: function () {
|
||||
return '<span class="fa-bug"></span>';
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,38 @@
|
||||
define([
|
||||
'dcl/dcl',
|
||||
'xblox/model/Block'
|
||||
], function (dcl, Block) {
|
||||
/**
|
||||
* @augments module:xide/mixins/EventedMixin
|
||||
* @lends module:xblox/model/Block_UI
|
||||
* @extends module:xblox/model/Block
|
||||
* @extends module:xblox/model/ModelBase
|
||||
*/
|
||||
|
||||
// summary:
|
||||
// The Case Block model. Each case block contains a comparation and a commands block.
|
||||
// If the comparation result is true, the block is executed
|
||||
//
|
||||
// This block should have an "SwitchBlock" parent
|
||||
|
||||
// module:
|
||||
// xblox.model.logic.CaseBlock
|
||||
return dcl(Block, {
|
||||
declaredClass: "xblox.model.logic.BreakBlock",
|
||||
name: 'Break',
|
||||
icon: 'fa-stop',
|
||||
hasInlineEdits: false,
|
||||
canAdd: false,
|
||||
toText: function () {
|
||||
return ' <span class="fa-stop text-warning"></span> <span>' + this.name + '</span>';
|
||||
},
|
||||
/***
|
||||
* Solves the case block
|
||||
* @param scope
|
||||
* @param settings
|
||||
*/
|
||||
solve: function (scope, settings) {
|
||||
this.onSuccess(this, settings);
|
||||
}
|
||||
});
|
||||
});
|
||||
185
packages/xblox/ref-control-freak/xblox/model/logic/CaseBlock.js
Normal file
185
packages/xblox/ref-control-freak/xblox/model/logic/CaseBlock.js
Normal file
@ -0,0 +1,185 @@
|
||||
define([
|
||||
'dcl/dcl',
|
||||
'xide/utils',
|
||||
'xblox/model/Block',
|
||||
'dojo/Deferred',
|
||||
"xblox/model/logic/BreakBlock"
|
||||
], function (dcl, utils, Block, Deferred, BreakBlock) {
|
||||
/**
|
||||
* @augments module:xide/mixins/EventedMixin
|
||||
* @lends module:xblox/model/Block_UI
|
||||
* @extends module:xblox/model/Block
|
||||
* @extends module:xblox/model/ModelBase
|
||||
*/
|
||||
// summary:
|
||||
// The Case Block model. Each case block contains a comparation and a commands block.
|
||||
// If the comparation result is true, the block is executed
|
||||
//
|
||||
// This block should have an "SwitchBlock" parent
|
||||
|
||||
// module:
|
||||
// xblox.model.logic.CaseBlock
|
||||
return dcl(Block, {
|
||||
declaredClass: "xblox.model.logic.CaseBlock",
|
||||
//comparator: xblox.model.Comparator
|
||||
// Comparison to be applied -> compare <switch variable> width <expression>
|
||||
comparator: null,
|
||||
//expression: xblox.model.Expression
|
||||
// expression to be compared
|
||||
expression: null,
|
||||
//items: Array (xblox.model.Block)
|
||||
// block to be executed if the comparison result is true
|
||||
items: null,
|
||||
name: 'Case',
|
||||
icon: '',
|
||||
hasInlineEdits: true,
|
||||
toText: function () {
|
||||
var _comparator = '' + this.comparator;
|
||||
if (_comparator == '==') {
|
||||
//_comparator =''
|
||||
}
|
||||
return '<span style="text-indent: 1em;"> ' + this.getBlockIcon('I') + this.name + ' ' + this.makeEditable('comparator', 'right', 'text', 'Enter a comparison', 'inline') + (this.expression != null ? ' ' + this.makeEditable('expression', 'right', 'text', 'Enter a value to compare') : '') + '</span>';
|
||||
},
|
||||
canAdd: function () {
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param scope
|
||||
* @param settings
|
||||
* @param switchblock
|
||||
* @returns {Array}
|
||||
* @private
|
||||
*/
|
||||
_solve: function (scope, settings, switchblock) {
|
||||
settings = settings || {
|
||||
highlight: false
|
||||
};
|
||||
var ret = [];
|
||||
for (var n = 0; n < this.items.length; n++) {
|
||||
var block = this.items[n];
|
||||
if (block.declaredClass.indexOf('BreakBlock') !== -1) {
|
||||
switchblock.stop();
|
||||
}
|
||||
this.addToEnd(ret, block.solve(scope, settings));
|
||||
}
|
||||
|
||||
return ret;
|
||||
},
|
||||
/***
|
||||
* Solves the case block
|
||||
* @param scope
|
||||
* @param settings
|
||||
* @param switchBlock => parent SwitchCommand block
|
||||
*/
|
||||
solve: function (scope, switchBlock, settings) {
|
||||
try {
|
||||
var _var = scope.getVariableById(switchBlock.variable);
|
||||
if (!_var && settings.args && settings.args[0]) {
|
||||
_var = {value: settings.args[0]};
|
||||
}
|
||||
// Get the variable to evaluate
|
||||
var switchVarValue = '';
|
||||
if (_var) {
|
||||
switchVarValue = this._getArg(_var.value, true);
|
||||
} else {
|
||||
this.onFailed(this, settings);
|
||||
// Comparation is false
|
||||
return false;
|
||||
}
|
||||
//var compResult = scope.parseExpression("'" + switchVarValue+ "'" + this.comparator + this.expression);
|
||||
var compResult = scope.parseExpression("" + switchVarValue + "" + this.comparator + this._getArg(this.expression, true));
|
||||
if (compResult !== true) {
|
||||
this.onFailed(this, settings);
|
||||
// Comparation is false
|
||||
return false;
|
||||
} else {
|
||||
this.onSuccess(this, settings);
|
||||
// Comparation is true. Return block.solve();
|
||||
this._solve(scope, settings, switchBlock);
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
logError(e);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Store function override
|
||||
* @returns {Array}
|
||||
*/
|
||||
getChildren: function () {
|
||||
return this.items;
|
||||
},
|
||||
// standard call for editing
|
||||
getFields: function () {
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
fields.push(utils.createCI('Expression', 13, this.expression, {
|
||||
group: 'General',
|
||||
title: 'Expression',
|
||||
dst: 'expression'
|
||||
}));
|
||||
|
||||
function makeOption(value, label) {
|
||||
return {
|
||||
label: label || value,
|
||||
value: value
|
||||
}
|
||||
}
|
||||
|
||||
fields.push(utils.createCI('Comparator', 3, this.comparator, {
|
||||
group: 'General',
|
||||
title: 'Comparator',
|
||||
dst: 'comparator',
|
||||
widget: {
|
||||
options: [
|
||||
/*makeOption('==',"Equals"),
|
||||
makeOption('<=',"Smaller or equal"),
|
||||
makeOption('=>',"Greater or equal"),
|
||||
makeOption('!=',"Not equal"),
|
||||
makeOption('<',"Smaller than"),
|
||||
makeOption('>',"Greater than")*/
|
||||
makeOption('=='),
|
||||
makeOption('<='),
|
||||
makeOption('=>'),
|
||||
makeOption('!='),
|
||||
makeOption('<'),
|
||||
makeOption('>')
|
||||
],
|
||||
editable: true
|
||||
}
|
||||
}));
|
||||
return fields;
|
||||
},
|
||||
runAction: function (action) {
|
||||
if (action.command === 'New/Break') {
|
||||
var dfd = new Deferred();
|
||||
var newBlock = this.add(BreakBlock, {
|
||||
group: null
|
||||
});
|
||||
var defaultDfdArgs = {
|
||||
select: [newBlock],
|
||||
focus: true,
|
||||
append: false
|
||||
};
|
||||
dfd.resolve(defaultDfdArgs);
|
||||
newBlock.refresh();
|
||||
return dfd;
|
||||
}
|
||||
},
|
||||
getActions: function () {
|
||||
return [this.createAction({
|
||||
label: 'Break',
|
||||
command: 'New/Break',
|
||||
tab: 'Home',
|
||||
icon: 'fa-stop',
|
||||
group: 'File',
|
||||
mixin: {
|
||||
addPermission: true,
|
||||
custom: true,
|
||||
quick: false
|
||||
}
|
||||
})
|
||||
]
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,16 @@
|
||||
define([
|
||||
"dojo/_base/declare",
|
||||
"../ModelBase"], function (declare, ModelBase) {
|
||||
|
||||
// summary:
|
||||
// The comparator model. A comparator compares two values and returns a boolean, indicating if the comparison
|
||||
// is true of false
|
||||
|
||||
// module:
|
||||
// xblox.model.Comparator
|
||||
return declare("xblox.model.Comparator", [ModelBase], {
|
||||
//name: string
|
||||
// Comparator public name/representation (=,>...)
|
||||
name: ''
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,32 @@
|
||||
define([
|
||||
'dcl/dcl',
|
||||
'xblox/model/Block'
|
||||
], function (dcl, Block) {
|
||||
/**
|
||||
* @augments module:xide/mixins/EventedMixin
|
||||
* @lends module:xblox/model/Block_UI
|
||||
* @extends module:xblox/model/Block
|
||||
* @extends module:xblox/model/ModelBase
|
||||
*/
|
||||
// summary:
|
||||
// The Case Block model. Each case block contains a comparation and a commands block.
|
||||
// If the comparation result is true, the block is executed
|
||||
//
|
||||
// This block should have an "SwitchBlock" parent
|
||||
|
||||
// module:
|
||||
// xblox.model.logic.CaseBlock
|
||||
return dcl(Block, {
|
||||
declaredClass: "xblox.model.logic.DefaultBlock",
|
||||
name: 'Default',
|
||||
icon: '',
|
||||
hasInlineEdits: false,
|
||||
toText: function () {
|
||||
return ' <span class="fa-eject text-info"></span> <span>' + this.name + '</span>';
|
||||
},
|
||||
solve: function (scope, settings) {
|
||||
this.onSuccess(this, settings);
|
||||
return this._solve(scope, settings);
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,62 @@
|
||||
define([
|
||||
"dcl/dcl",
|
||||
"xblox/model/Block",
|
||||
"xblox/model/Contains"
|
||||
], function (dcl, Block, Contains) {
|
||||
/**
|
||||
* @augments module:xide/mixins/EventedMixin
|
||||
* @lends module:xblox/model/Block_UI
|
||||
* @extends module:xblox/model/Block
|
||||
* @extends module:xblox/model/ModelBase
|
||||
*/
|
||||
// summary:
|
||||
// The ElseIf Block model. Each ElseIf block contains a condition and a consequent to be run if the condition
|
||||
// is true
|
||||
//
|
||||
// This block should have an "IfBlock" parent
|
||||
|
||||
// module:
|
||||
// xblox.model.logic.ElseIfBlock
|
||||
return dcl([Block, Contains], {
|
||||
declaredClass: "xblox.model.logic.ElseIfBlock",
|
||||
// condition: (String) expression to be evaluated
|
||||
condition: "",
|
||||
// consequent: (Block) block to be run if the condition is true
|
||||
consequent: null,
|
||||
name: 'else if',
|
||||
icon: '',
|
||||
solve: function (scope, settings) {
|
||||
if (this._checkCondition(scope)) {
|
||||
return this._solve(scope, settings)
|
||||
}
|
||||
return false;
|
||||
},
|
||||
toText: function () {
|
||||
return "<span class='text-primary'>" + this.getBlockIcon('E') + this.name + " </span>" + "<span class='text-warning small'>" + (this.condition || "") + "<span>";
|
||||
},
|
||||
// checks the ElseIf condition
|
||||
_checkCondition: function (scope) {
|
||||
if (this.condition !== null) {
|
||||
return scope.parseExpression(this.condition);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
getFields: function () {
|
||||
var thiz = this;
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
fields.push(
|
||||
this.utils.createCI('condition', this.types.ECIType.EXPRESSION_EDITOR, this.condition, {
|
||||
group: 'General',
|
||||
title: 'Expression',
|
||||
dst: 'condition',
|
||||
delegate: {
|
||||
runExpression: function (val, run, error) {
|
||||
return thiz.scope.expressionModel.parse(thiz.scope, val, false, run, error);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
return fields;
|
||||
}
|
||||
});
|
||||
});
|
||||
306
packages/xblox/ref-control-freak/xblox/model/logic/IfBlock.js
Normal file
306
packages/xblox/ref-control-freak/xblox/model/logic/IfBlock.js
Normal file
@ -0,0 +1,306 @@
|
||||
/** @module xblox/model/logic/IfBlock **/
|
||||
define([
|
||||
"dcl/dcl",
|
||||
"xblox/model/Block",
|
||||
"xblox/model/Statement",
|
||||
"xblox/model/logic/ElseIfBlock",
|
||||
"dojo/Deferred",
|
||||
"xide/utils"
|
||||
], function (dcl, Block, Statement, ElseIfBlock, Deferred, utils) {
|
||||
|
||||
/**
|
||||
* Base block class.
|
||||
*
|
||||
* @class module:xblox/model/logic/IfBlock
|
||||
* @augments module:xblox/model/ModelBase
|
||||
* @extends module:xblox/model/Block
|
||||
*/
|
||||
return dcl(Block, {
|
||||
declaredClass: "xblox.model.logic.IfBlock",
|
||||
// condition: (String) expression to be evaluated
|
||||
condition: 'Invalid Expression',
|
||||
|
||||
// consequent: (Block) block to be run if the condition is true
|
||||
consequent: null,
|
||||
|
||||
// elseIfBlocks: (optional) Array[ElseIfBlock] -> blocks to be run if the condition is false. If any of these blocks condition is
|
||||
// true, the elseIf/else sequence stops
|
||||
elseIfBlocks: null,
|
||||
|
||||
// alternate: (optional) (Block) -> block to be run if the condition is false and none of the "elseIf" blocks is true
|
||||
alternate: null,
|
||||
|
||||
// standard call from interface
|
||||
canAdd: function () {
|
||||
return [];
|
||||
},
|
||||
|
||||
// autoCreateElse : does auto creates the else part
|
||||
autoCreateElse: true,
|
||||
|
||||
// name : this name is displayed in the block row editor
|
||||
name: 'if',
|
||||
|
||||
icon: '',
|
||||
// add
|
||||
//
|
||||
// @param proto {mixed : Prototype|Object} : the new block's call prototype or simply a ready to use block
|
||||
// @param ctrArgs {Array} : constructor arguments for the new block
|
||||
// @param where {String} : consequent or alternate or elseif
|
||||
// @returns {Block}
|
||||
//
|
||||
add: function (proto, ctrArgs, where) {
|
||||
if (where == null) {
|
||||
where = 'consequent';
|
||||
}
|
||||
return this._add(proto, ctrArgs, where, false);
|
||||
},
|
||||
// overrides default store integration
|
||||
__addToStore: function (store) {
|
||||
//add our self to the store
|
||||
store.put(this);
|
||||
},
|
||||
/**
|
||||
* Store function override
|
||||
* @returns {boolean}
|
||||
*/
|
||||
mayHaveChildren: function () {
|
||||
return (this.items !== null && this.items.length) ||
|
||||
(this.elseIfBlocks !== null && this.elseIfBlocks.length) ||
|
||||
(this.consequent != null && this.consequent.length) ||
|
||||
(this.alternate != null && this.alternate.length);
|
||||
|
||||
},
|
||||
/**
|
||||
* Store function override
|
||||
* @returns {Array}
|
||||
*/
|
||||
getChildren: function () {
|
||||
var result = [];
|
||||
if (this.consequent) {
|
||||
result = result.concat(this.consequent);
|
||||
}
|
||||
if (this.elseIfBlocks) {
|
||||
result = result.concat(this.elseIfBlocks);
|
||||
}
|
||||
if (this.alternate) {
|
||||
result = result.concat(this.alternate);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
/**
|
||||
* Block row editor, returns the entire text for this block
|
||||
* @returns {string}
|
||||
*/
|
||||
toText: function () {
|
||||
return "<span class='text-primary'>" + this.getBlockIcon('E') + this.name + " </span>" + "<span class='text-warning small'>" + this.condition + "<span>";
|
||||
},
|
||||
_checkCondition: function (scope) {
|
||||
return scope.parseExpression(this.condition, null, null);
|
||||
},
|
||||
solve: function (scope, settings) {
|
||||
// 1. Check the condition
|
||||
var solvedCondition = this._checkCondition(scope);
|
||||
var elseIfBlocks = this.getElseIfBlocks();
|
||||
var others = this.childrenByNotClass(ElseIfBlock);
|
||||
var result = null;
|
||||
|
||||
others = others.filter(function (block) {
|
||||
return !block.isInstanceOf(Statement);
|
||||
});
|
||||
|
||||
// 2. TRUE? => run consequent
|
||||
if (solvedCondition == true || solvedCondition > 0) {
|
||||
this.onSuccess(this, settings);
|
||||
if (others && others.length) {
|
||||
for (var i = 0; i < others.length; i++) {
|
||||
result = others[i].solve(scope, settings);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
// 3. FALSE?
|
||||
var anyElseIf = false;
|
||||
this.onFailed(this, settings);
|
||||
if (elseIfBlocks) {
|
||||
// 4. ---- check all elseIf blocks. If any of the elseIf conditions is true, run the elseIf consequent and
|
||||
// stop the process
|
||||
for (var n = 0; ( n < elseIfBlocks.length ) && (!anyElseIf); n++) {
|
||||
var _elseIfBlock = elseIfBlocks[n];
|
||||
if (_elseIfBlock._checkCondition(scope)) {
|
||||
_elseIfBlock.onSuccess(_elseIfBlock, settings);
|
||||
anyElseIf = true;
|
||||
return _elseIfBlock.solve(scope, settings);
|
||||
} else {
|
||||
_elseIfBlock.onFailed(_elseIfBlock, settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var alternate = this.childrenByClass(Statement);
|
||||
// 5. ---- If none of the ElseIf blocks has been run, run the alternate
|
||||
if (alternate.length > 0 && (!anyElseIf)) {
|
||||
result = null;
|
||||
for (var i = 0; i < alternate.length; i++) {
|
||||
result = alternate[i].solve(scope, settings);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
* Default override empty. We have 3 arrays to clean : items, alternate and consequent
|
||||
*/
|
||||
empty: function () {
|
||||
this._empty(this.alternate);
|
||||
this._empty(this.consequent);
|
||||
this._empty(this.elseIfBlocks);
|
||||
},
|
||||
/**
|
||||
* Deletes us or children block in alternate or consequent
|
||||
* @param what
|
||||
*/
|
||||
removeBlock: function (what) {
|
||||
if (what) {
|
||||
if (what && what.empty) {
|
||||
what.empty();
|
||||
}
|
||||
delete what.items;
|
||||
what.parent = null;
|
||||
this.alternate.remove(what);
|
||||
this.consequent.remove(what);
|
||||
this.elseIfBlocks.remove(what);
|
||||
}
|
||||
},
|
||||
// evaluate the if condition
|
||||
_getContainer: function (item) {
|
||||
if (this.consequent.indexOf(item) != -1) {
|
||||
return 'consequent';
|
||||
} else if (this.alternate.indexOf(item) != -1) {
|
||||
return 'alternate';
|
||||
} else if (this.elseIfBlocks.indexOf(item) != -1) {
|
||||
return 'elseIfBlocks';
|
||||
}
|
||||
return '_';
|
||||
},
|
||||
/**
|
||||
* Default override, prepare all variables
|
||||
*/
|
||||
init: function () {
|
||||
this.alternate = this.alternate || [];
|
||||
this.consequent = this.consequent || [];
|
||||
this.elseIfBlocks = this.elseIfBlocks || [];
|
||||
|
||||
for (var i = 0; i < this.alternate.length; i++) {
|
||||
this.alternate[i].parentId = this.id;
|
||||
this.alternate[i].parent = this;
|
||||
}
|
||||
for (var i = 0; i < this.elseIfBlocks.length; i++) {
|
||||
this.elseIfBlocks[i].parentId = this.id;
|
||||
this.elseIfBlocks[i].parent = this;
|
||||
}
|
||||
for (var i = 0; i < this.consequent.length; i++) {
|
||||
this.consequent[i].parentId = this.id;
|
||||
this.consequent[i].parent = this;
|
||||
}
|
||||
//var store = this.scope.blockStore;
|
||||
},
|
||||
getFields: function () {
|
||||
var thiz = this;
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
fields.push(
|
||||
this.utils.createCI('condition', this.types.ECIType.EXPRESSION_EDITOR, this.condition, {
|
||||
group: 'General',
|
||||
title: 'Expression',
|
||||
dst: 'condition',
|
||||
delegate: {
|
||||
runExpression: function (val, run, error) {
|
||||
return thiz.scope.expressionModel.parse(thiz.scope, val, false, run, error);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
return fields;
|
||||
},
|
||||
postCreate: function () {
|
||||
if (this._postCreated) {
|
||||
return;
|
||||
}
|
||||
this._postCreated = true;
|
||||
},
|
||||
toCode: function (lang, params) {
|
||||
},
|
||||
getElseIfBlocks: function () {
|
||||
return this.childrenByClass(ElseIfBlock);
|
||||
},
|
||||
runAction: function (action) {
|
||||
var store = this.scope.blockStore;
|
||||
var command = action.command;
|
||||
if (command === 'New/Else' || command === 'New/Else If') {
|
||||
var newBlockClass = command === 'New/Else If' ? ElseIfBlock : Statement;
|
||||
var args = utils.mixin({
|
||||
name: 'else',
|
||||
items: [],
|
||||
dstField: 'alternate',
|
||||
parentId: this.id,
|
||||
parent: this,
|
||||
scope: this.scope,
|
||||
canAdd: function () {
|
||||
return [];
|
||||
},
|
||||
canEdit: function () {
|
||||
return false;
|
||||
}
|
||||
}, newBlockClass == ElseIfBlock ? {name: 'else if', dstField: 'elseIfBlocks'} : {
|
||||
name: 'else', dstField: 'alternate'
|
||||
}
|
||||
);
|
||||
|
||||
var newBlock = this.add(newBlockClass, args, newBlockClass == Statement ? 'alternate' : 'elseIfBlocks');
|
||||
var defaultDfdArgs = {
|
||||
select: [newBlock],
|
||||
focus: true,
|
||||
append: false,
|
||||
expand: true,
|
||||
delay: 10
|
||||
};
|
||||
var dfd = new Deferred();
|
||||
store._emit('added', {
|
||||
target: newBlock
|
||||
});
|
||||
dfd.resolve(defaultDfdArgs);
|
||||
newBlock.refresh();
|
||||
return dfd;
|
||||
}
|
||||
},
|
||||
getActions: function () {
|
||||
var result = [];
|
||||
if (this.alternate.length == 0) {
|
||||
result.push(this.createAction({
|
||||
label: 'Else',
|
||||
command: 'New/Else',
|
||||
icon: this.getBlockIcon('I'),
|
||||
tab: 'Home',
|
||||
group: 'File',
|
||||
mixin: {
|
||||
addPermission: true,
|
||||
custom: true
|
||||
}
|
||||
}));
|
||||
}
|
||||
result.push(this.createAction({
|
||||
label: 'Else If',
|
||||
command: 'New/Else If',
|
||||
icon: this.getBlockIcon('I'),
|
||||
tab: 'Home',
|
||||
group: 'File',
|
||||
mixin: {
|
||||
addPermission: true,
|
||||
custom: true
|
||||
}
|
||||
}));
|
||||
return result;
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,152 @@
|
||||
/** @module xblox/model/logic/SwitchBlock **/
|
||||
define([
|
||||
'dcl/dcl',
|
||||
"xblox/model/Block",
|
||||
"xblox/model/logic/CaseBlock",
|
||||
"xblox/model/logic/DefaultBlock",
|
||||
"dojo/Deferred",
|
||||
"xide/lodash"
|
||||
], function (dcl, Block, CaseBlock, DefaultBlock, Deferred, _) {
|
||||
/**
|
||||
*
|
||||
* @class module:xblox/model/logic/SwitchBlock
|
||||
* @extends module:xblox/model/Block
|
||||
*/
|
||||
return dcl(Block, {
|
||||
declaredClass: "xblox.model.logic.SwitchBlock",
|
||||
items: null,
|
||||
name: 'Switch',
|
||||
icon: null,
|
||||
toText: function () {
|
||||
return this.getBlockIcon('H') + this.name + ' ';
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param what {module:xblox/model/Block}
|
||||
* @returns {*}
|
||||
*/
|
||||
canAdd: function (what) {
|
||||
if(what && what.isInstanceOf){
|
||||
return what.isInstanceOf(CaseBlock) || what.isInstanceOf(DefaultBlock);
|
||||
}
|
||||
return [];
|
||||
},
|
||||
getFields: function () {
|
||||
return this.getDefaultFields(false, false);
|
||||
},
|
||||
/***
|
||||
* Solve the switchblock
|
||||
* @param scope
|
||||
* @param settings
|
||||
* @returns {string} execution result
|
||||
*/
|
||||
solve: function (scope, settings) {
|
||||
this._stopped = false;
|
||||
var anyCase = false; // check if any case is reached
|
||||
var ret = [];
|
||||
this.onSuccess(this, settings);
|
||||
// iterate all case blocks
|
||||
for (var n = 0; n < this.items.length; n++) {
|
||||
var block = this.items[n];
|
||||
|
||||
if (block.declaredClass === 'xblox.model.logic.CaseBlock'/* instanceof CaseBlock*/) {
|
||||
var caseret;
|
||||
// solve each case block. If the comparison result is false, the block returns "false"
|
||||
caseret = block.solve(scope, this, settings);
|
||||
if (caseret != false) {
|
||||
// If the case block return is not false, don't run "else" block
|
||||
anyCase = true;
|
||||
this.addToEnd(ret, caseret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (this._stopped) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// iterate all "else" blocks if none of the cases occurs
|
||||
if (!anyCase) {
|
||||
for (var n = 0; n < this.items.length; n++) {
|
||||
var block = this.items[n];
|
||||
if (!(block.declaredClass == 'xblox.model.logic.CaseBlock')) {
|
||||
this.addToEnd(ret, block.solve(scope, settings));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
/**
|
||||
* Store function override
|
||||
* @returns {Array}
|
||||
*/
|
||||
getChildren: function () {
|
||||
return this.items;
|
||||
},
|
||||
stop: function () {
|
||||
this._stopped = true;
|
||||
},
|
||||
runAction: function (action) {
|
||||
var command = action.command;
|
||||
if (command === 'New/Case' || action.command === 'New/Default') {
|
||||
var store = this.scope.blockStore;
|
||||
var dfd = new Deferred();
|
||||
var newBlock = null;
|
||||
|
||||
switch (command) {
|
||||
case 'New/Case': {
|
||||
newBlock = this.add(CaseBlock, {
|
||||
comparator: "==",
|
||||
expression: "on",
|
||||
group: null
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'New/Default': {
|
||||
newBlock = this.add(DefaultBlock, {
|
||||
group: null
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
dfd.resolve({
|
||||
select: [newBlock],
|
||||
focus: true,
|
||||
append: false
|
||||
});
|
||||
newBlock.refresh();
|
||||
store._emit('added', {
|
||||
target: newBlock
|
||||
});
|
||||
}
|
||||
},
|
||||
getActions: function (permissions, owner) {
|
||||
var result = [this.createAction({
|
||||
label: 'New Case',
|
||||
command: 'New/Case',
|
||||
icon: this.getBlockIcon('I'),
|
||||
tab: 'Home',
|
||||
group: 'File',
|
||||
mixin: {
|
||||
addPermission: true,
|
||||
custom: true,
|
||||
quick: false
|
||||
}
|
||||
})];
|
||||
if (!_.find(this.items, {declaredClass: 'xblox.model.logic.DefaultBlock'})) {
|
||||
result.push(this.createAction({
|
||||
label: 'Default',
|
||||
command: 'New/Default',
|
||||
icon: 'fa-eject',
|
||||
tab: 'Home',
|
||||
group: 'File',
|
||||
mixin: {
|
||||
addPermission: true,
|
||||
custom: true,
|
||||
quick: false
|
||||
}
|
||||
}));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
});
|
||||
});
|
||||
329
packages/xblox/ref-control-freak/xblox/model/loops/ForBlock.js
Normal file
329
packages/xblox/ref-control-freak/xblox/model/loops/ForBlock.js
Normal file
@ -0,0 +1,329 @@
|
||||
define([
|
||||
"dcl/dcl",
|
||||
"xblox/model/Block",
|
||||
"xblox/model/variables/Variable",
|
||||
'xblox/model/Contains',
|
||||
"dojo/promise/all",
|
||||
"dojo/Deferred"
|
||||
], function (dcl, Block, Variable, Contains, all, Deferred) {
|
||||
|
||||
/**
|
||||
* @augments module:xide/mixins/EventedMixin
|
||||
* @lends module:xblox/model/Block_UI
|
||||
* @extends module:xblox/model/Block
|
||||
* @extends module:xblox/model/ModelBase
|
||||
*/
|
||||
// summary:
|
||||
// The for block model. It repeats a block a number of times, while the condition is true.
|
||||
//
|
||||
|
||||
// module:
|
||||
// xblox.model.loops.ForBlock
|
||||
return dcl([Block, Contains], {
|
||||
declaredClass: "xblox.model.loops.ForBlock",
|
||||
// initial: xcf.model.Expression
|
||||
// the initial value
|
||||
initial: null,
|
||||
// final: xcf.model.Expression
|
||||
// the final value to be compared with the counter. Once the final value equals to the counter, the loop stops
|
||||
"final": null,
|
||||
//comparator: xblox.model.Comparator
|
||||
// Comparison to be applied -> compare <counter variable> width <final>
|
||||
comparator: null,
|
||||
// modifier: xcf.model.Expression
|
||||
// expression to be applied to the counter on every step. Expression: "<counter><modifier>"
|
||||
modifier: null,
|
||||
|
||||
//items: Array (xblox.model.Block)
|
||||
// block to be executed while the condition compare <counter variable> width <final> is false
|
||||
items: null,
|
||||
|
||||
//counterName: String
|
||||
// the counter variable name
|
||||
counterName: null,
|
||||
// (private) counter: xblox.model.Variable
|
||||
// counter to be compared and updated on every step
|
||||
_counter: null,
|
||||
name: 'For',
|
||||
sharable: true,
|
||||
icon: '',
|
||||
ignoreErrors: false,
|
||||
deferred: true,
|
||||
_forState: false,
|
||||
_currentForIndex: 0,
|
||||
runFrom: function (_blocks, index, settings) {
|
||||
var thiz = this,
|
||||
blocks = _blocks || this.items,
|
||||
allDfds = [];
|
||||
|
||||
var onFinishBlock = function (block, results) {
|
||||
block._lastResult = block._lastResult || results;
|
||||
thiz._currentIndex++;
|
||||
thiz.runFrom(blocks, thiz._currentIndex, settings);
|
||||
};
|
||||
|
||||
var wireBlock = function (block) {
|
||||
block._deferredObject.then(function (results) {
|
||||
onFinishBlock(block, results);
|
||||
});
|
||||
};
|
||||
|
||||
if (blocks.length) {
|
||||
for (var n = index; n < blocks.length; n++) {
|
||||
var block = blocks[n];
|
||||
if (block.enabled === false) {
|
||||
continue;
|
||||
}
|
||||
if (block.deferred === true) {
|
||||
block._deferredObject = new Deferred();
|
||||
this._currentIndex = n;
|
||||
wireBlock(block);
|
||||
allDfds.push(block.solve(this.scope, settings));
|
||||
break;
|
||||
} else {
|
||||
allDfds.push(block.solve(this.scope, settings));
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
this.onSuccess(this, settings);
|
||||
}
|
||||
return allDfds;
|
||||
},
|
||||
runFromDirect: function (_blocks, index, settings) {
|
||||
var thiz = this,
|
||||
blocks = _blocks || this.items,
|
||||
allDfds = [];
|
||||
|
||||
var onFinishBlock = function (block, results) {
|
||||
block._lastResult = block._lastResult || results;
|
||||
thiz._currentIndex++;
|
||||
thiz.runFrom(blocks, thiz._currentIndex, settings);
|
||||
};
|
||||
|
||||
var wireBlock = function (block) {
|
||||
block._deferredObject.then(function (results) {
|
||||
onFinishBlock(block, results);
|
||||
});
|
||||
};
|
||||
if (blocks.length) {
|
||||
for (var n = index; n < blocks.length; n++) {
|
||||
var block = blocks[n];
|
||||
if (block.enabled === false) {
|
||||
continue;
|
||||
}
|
||||
if (block.deferred === true) {
|
||||
block._deferredObject = new Deferred();
|
||||
this._currentIndex = n;
|
||||
wireBlock(block);
|
||||
allDfds.push(block.solve(this.scope, settings));
|
||||
break;
|
||||
} else {
|
||||
allDfds.push(block.solve(this.scope, settings));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.onSuccess(this, settings);
|
||||
}
|
||||
|
||||
return allDfds;
|
||||
},
|
||||
solveSubs: function (dfd, result, items, settings) {
|
||||
var thiz = this;
|
||||
settings.override = settings.override || {};
|
||||
settings.override['args'] = [this._currentForIndex];
|
||||
//more blocks?
|
||||
if (items.length) {
|
||||
var subDfds = thiz.runFrom(items, 0, settings);
|
||||
all(subDfds).then(function (what) {
|
||||
}, function (err) {
|
||||
thiz.onDidRunItem(dfd, err, settings);
|
||||
});
|
||||
return subDfds;
|
||||
|
||||
} else {
|
||||
thiz.onDidRunItem(dfd, result, settings);
|
||||
}
|
||||
},
|
||||
solveSubsDirect: function (dfd, result, items, settings) {
|
||||
var thiz = this;
|
||||
settings.override = settings.override || {};
|
||||
settings.override['args'] = [this._currentForIndex];
|
||||
//more blocks?
|
||||
if (items.length) {
|
||||
return thiz.runFromDirect(items, 0, settings);
|
||||
}
|
||||
},
|
||||
_solve: function (scope, settings) {
|
||||
var dfd = new Deferred(),
|
||||
self = this;
|
||||
var result = this.solveSubs(dfd, null, this.items, settings);
|
||||
if (result) {
|
||||
all(result).then(function (res) {
|
||||
var falsy = res.indexOf(false);
|
||||
if (self.ignoreErrors !== true && falsy !== -1) {
|
||||
dfd.resolve(false);
|
||||
} else {
|
||||
dfd.resolve(true);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
dfd.resolve(true);
|
||||
}
|
||||
|
||||
return dfd;
|
||||
},
|
||||
step: function (scope, settings) {
|
||||
var state = this._checkCondition(scope, settings);
|
||||
var dfd = new Deferred();
|
||||
if (state) {
|
||||
//run blocks
|
||||
var subs = this._solve(scope, settings);
|
||||
subs.then(function (result) {
|
||||
if (result == true) {
|
||||
dfd.resolve(true);
|
||||
} else {
|
||||
dfd.resolve(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
return dfd;
|
||||
},
|
||||
loop: function (scope, settings) {
|
||||
var stepResult = this.step(scope, settings),
|
||||
self = this;
|
||||
stepResult.then(function (proceed) {
|
||||
self._updateCounter(scope);
|
||||
self._currentForIndex = self._counter.value;
|
||||
if (proceed == true) {
|
||||
self.loop(scope, settings);
|
||||
} else {
|
||||
self.onFailed(self, settings);
|
||||
}
|
||||
});
|
||||
},
|
||||
_solveDirect: function (scope, settings) {
|
||||
return this.solveSubsDirect(null, null, this.items, settings);
|
||||
},
|
||||
stepDirect: function (scope, settings) {
|
||||
return this._solveDirect(scope, settings);
|
||||
},
|
||||
loopDirect: function (scope, settings) {
|
||||
this.stepDirect(scope, settings)
|
||||
for (var index = parseInt(this.initial, 10); index < parseInt(this['final'], 10); index++) {
|
||||
this.stepDirect(scope, settings);
|
||||
}
|
||||
},
|
||||
|
||||
// solves the for block (runs the loop)
|
||||
solve: function (scope, settings) {
|
||||
// 1. Create and initialize counter variable
|
||||
this._counter = new Variable({
|
||||
title: this.counterName,
|
||||
value: this.initial,
|
||||
scope: scope,
|
||||
register: false
|
||||
});
|
||||
//prepare
|
||||
this._forState = true;
|
||||
this._currentForIndex = this.initial;
|
||||
this.deferred ? this.loop(scope, settings) : this.loopDirect(scope, settings);
|
||||
return [];
|
||||
},
|
||||
// checks the loop condition
|
||||
_checkCondition: function (scope, settings) {
|
||||
var expression = '' + this._counter.value + this.comparator + this['final'];
|
||||
var result = scope.parseExpression(expression);
|
||||
if (result != false) {
|
||||
this.onSuccess(this, settings);
|
||||
}
|
||||
this._forState = result;
|
||||
return result;
|
||||
},
|
||||
// updates the counter
|
||||
_updateCounter: function (scope) {
|
||||
var value = this._counter.value;
|
||||
var expression = '' + value + this.modifier;
|
||||
value = scope.parseExpression(expression);
|
||||
// Detect infinite loops
|
||||
if (value == this._counter.value) {
|
||||
return false;
|
||||
} else {
|
||||
this._counter.value = value;
|
||||
return true;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Store function override
|
||||
* @returns {boolean}
|
||||
*/
|
||||
mayHaveChildren: function () {
|
||||
return this.items != null && this.items.length > 0;
|
||||
},
|
||||
/**
|
||||
* Store function override
|
||||
* @returns {Array}
|
||||
*/
|
||||
getChildren: function () {
|
||||
var result = [];
|
||||
if (this.items) {
|
||||
result = result.concat(this.items);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
/**
|
||||
* should return a number of valid classes
|
||||
* @returns {Array}
|
||||
*/
|
||||
canAdd: function () {
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
* UI, Block row editor, returns the entire text for this block
|
||||
* @returns {string}
|
||||
*/
|
||||
toText: function () {
|
||||
return this.getBlockIcon('F') + this.name + ' ' + this.initial + ' ' + this.comparator + ' ' + this['final'] + ' with ' + this.modifier;
|
||||
},
|
||||
/**
|
||||
* UI
|
||||
* @returns {*[]}
|
||||
*/
|
||||
getFields: function () {
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
fields = fields.concat([
|
||||
this.utils.createCI('initial', 13, this.initial, {
|
||||
group: 'General',
|
||||
title: 'Initial',
|
||||
dst: 'initial'
|
||||
}),
|
||||
this.utils.createCI('Final', 13, this['final'], {
|
||||
group: 'General',
|
||||
title: 'Final',
|
||||
dst: 'final'
|
||||
}),
|
||||
this.utils.createCI('comparator', 13, this.comparator, {
|
||||
group: 'General',
|
||||
title: 'Comparision',
|
||||
dst: 'comparator'
|
||||
}),
|
||||
this.utils.createCI('modifier', 13, this.modifier, {
|
||||
group: 'General',
|
||||
title: 'Modifier',
|
||||
dst: 'modifier'
|
||||
}),
|
||||
this.utils.createCI('Abort on Error', 0, this.ignoreErrors, {
|
||||
group: 'General',
|
||||
title: 'Ignore Errors',
|
||||
dst: 'ignoreErrors'
|
||||
}),
|
||||
this.utils.createCI('Deferred', 0, this.deferred, {
|
||||
group: 'General',
|
||||
title: 'Use Deferred',
|
||||
dst: 'deferred'
|
||||
})
|
||||
]);
|
||||
return fields;
|
||||
}
|
||||
});
|
||||
});
|
||||
189
packages/xblox/ref-control-freak/xblox/model/loops/WhileBlock.js
Normal file
189
packages/xblox/ref-control-freak/xblox/model/loops/WhileBlock.js
Normal file
@ -0,0 +1,189 @@
|
||||
define([
|
||||
"dcl/dcl",
|
||||
"xblox/model/Block",
|
||||
"xblox/model/variables/Variable"
|
||||
], function(dcl,Block,Variable){
|
||||
|
||||
// summary:
|
||||
// The while block model. It repeats a block a number of times, while the condition is true.
|
||||
//
|
||||
|
||||
// module:
|
||||
// xblox.model.loops.WhileBlock
|
||||
return dcl(Block,{
|
||||
|
||||
declaredClass:"xblox.model.loops.WhileBlock",
|
||||
// condition: (String) expression to be evaluated every step
|
||||
condition: null,
|
||||
/**
|
||||
* Blocks to be executed while the condition is true
|
||||
* @type {xblox.model.Block[]}
|
||||
* @inheritDoc
|
||||
*/
|
||||
items: null,
|
||||
|
||||
loopLimit: 1500,
|
||||
|
||||
name:'While',
|
||||
|
||||
wait:0,
|
||||
|
||||
_currentIndex:0,
|
||||
|
||||
sharable:true,
|
||||
|
||||
icon:"",
|
||||
|
||||
_timer:null,
|
||||
|
||||
// standard call from interface
|
||||
canAdd:function(){
|
||||
return [];
|
||||
},
|
||||
_solve:function(scope,settings){
|
||||
var ret=[];
|
||||
for(var n = 0; n < this.items.length ; n++)
|
||||
{
|
||||
this.items[n].solve(scope,settings);
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
|
||||
doStep:function(settings){
|
||||
|
||||
if(this._currentIndex < this.loopLimit){
|
||||
|
||||
var ret = [];
|
||||
|
||||
var _cond = this._checkCondition(this.scope);
|
||||
if(_cond) {
|
||||
this.onSuccess(this,settings);
|
||||
this.addToEnd( ret , this._solve(this.scope,settings));
|
||||
this._currentIndex++;
|
||||
}else{
|
||||
if(this._timer){
|
||||
clearInterval(this._timer);
|
||||
}
|
||||
|
||||
|
||||
this.onFailed(this,settings);
|
||||
}
|
||||
}else{
|
||||
console.error('--while block : reached loop limit');
|
||||
this.reset();
|
||||
}
|
||||
},
|
||||
reset:function(){
|
||||
if(this._timer){
|
||||
clearTimeout(this._timer);
|
||||
this._timer = null;
|
||||
}
|
||||
this._currentIndex=0;
|
||||
|
||||
|
||||
},
|
||||
// solves the while block (runs the loop)
|
||||
solve:function(scope,settings) {
|
||||
|
||||
//console.log('solve while ');
|
||||
this.loopLimit = 1500;
|
||||
settings = settings || { };
|
||||
|
||||
var iterations = 0;
|
||||
|
||||
var ret = [],
|
||||
thiz = this;
|
||||
|
||||
var delay = this._getArg(this.wait);
|
||||
|
||||
this.reset();
|
||||
|
||||
// has delay
|
||||
if(delay>0){
|
||||
|
||||
this._timer = setInterval(function(){
|
||||
thiz.doStep(settings);
|
||||
},delay);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
// Evaluate condition
|
||||
while ((this._checkCondition(scope)) && (iterations < this.loopLimit)) {
|
||||
this._solve(scope,settings);
|
||||
iterations++;
|
||||
}
|
||||
//cleanup
|
||||
|
||||
this.reset();
|
||||
|
||||
return ret;
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Block row editor, returns the entire text for this block
|
||||
* @returns {string}
|
||||
*/
|
||||
toText:function(){
|
||||
return this.getBlockIcon('G') + this.name + ' ' + this.condition;
|
||||
},
|
||||
|
||||
// checks the loop condition
|
||||
_checkCondition:function(scope) {
|
||||
return scope.parseExpression(this.condition);
|
||||
},
|
||||
/**
|
||||
* Store function override
|
||||
* @param parent
|
||||
* @returns {boolean}
|
||||
*/
|
||||
mayHaveChildren:function(parent){
|
||||
return this.items!=null && this.items.length>0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Store function override
|
||||
* @param parent
|
||||
* @returns {Array}
|
||||
*/
|
||||
getChildren:function(parent){
|
||||
var result=[];
|
||||
|
||||
if(this.items){
|
||||
result=result.concat(this.items);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
getFields:function(){
|
||||
|
||||
|
||||
var thiz=this;
|
||||
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
|
||||
fields.push(
|
||||
|
||||
this.utils.createCI('condition',25,this.condition,{
|
||||
group:'General',
|
||||
title:'Expression',
|
||||
dst:'condition',
|
||||
delegate:{
|
||||
runExpression:function(val,run,error){
|
||||
return thiz.scope.expressionModel.parse(thiz.scope,val,false,run,error);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
fields.push(this.utils.createCI('wait',13,this.wait,{
|
||||
group:'General',
|
||||
title:'Wait',
|
||||
dst:'wait'
|
||||
}));
|
||||
return fields;
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
239
packages/xblox/ref-control-freak/xblox/model/mqtt/Publish.js
Normal file
239
packages/xblox/ref-control-freak/xblox/model/mqtt/Publish.js
Normal file
@ -0,0 +1,239 @@
|
||||
/** @module xblox/model/mqtt/Publish **/
|
||||
define([
|
||||
'dcl/dcl',
|
||||
'xdojo/has',
|
||||
'xide/utils',
|
||||
'xide/types',
|
||||
'xcf/model/Command'
|
||||
//'xdojo/has!host-node?dojo/node!tracer',
|
||||
//'xdojo/has!host-node?nxapp/utils/_console'
|
||||
], function (dcl, has, utils, types, Command, tracer, _console) {
|
||||
|
||||
/**
|
||||
* @augments module:xide/mixins/EventedMixin
|
||||
* @lends module:xblox/model/Block_UI
|
||||
* @extends module:xblox/model/Block
|
||||
* @extends module:xblox/model/ModelBase
|
||||
*/
|
||||
|
||||
var isServer = has('host-node');
|
||||
var console = typeof window !== 'undefined' ? window.console : global.console;
|
||||
if (isServer && tracer && console && console.error) {
|
||||
console = _console;
|
||||
}
|
||||
|
||||
// summary:
|
||||
// The Call Block model.
|
||||
// This block makes calls to another blocks in the same scope by action name
|
||||
|
||||
// module:
|
||||
// xblox.model.code.CallMethod
|
||||
/**
|
||||
* Base block class.
|
||||
*
|
||||
* @class module:xblox/model/mqtt/Publish
|
||||
* @extends module:xblox/model/Block
|
||||
*/
|
||||
return dcl(Command, {
|
||||
declaredClass: "xblox.model.mqtt.Publish",
|
||||
//method: (String)
|
||||
// block action name
|
||||
name: 'Publish',
|
||||
//method: (String)
|
||||
// block action name
|
||||
topic: '',
|
||||
args: '',
|
||||
deferred: false,
|
||||
sharable: true,
|
||||
context: null,
|
||||
icon: 'fa-send',
|
||||
isCommand: true,
|
||||
qos: 0,
|
||||
retain: false,
|
||||
/**
|
||||
* @type {string|null}
|
||||
*/
|
||||
path: null,
|
||||
flags: 0,
|
||||
onData: function (message) {
|
||||
if (message && message.topic && message.topic == this.topic) {
|
||||
var thiz = this,
|
||||
ctx = this.getContext(),
|
||||
items = this[this._getContainer()];
|
||||
|
||||
var settings = this._lastSettings;
|
||||
var ret = [];
|
||||
if (items.length > 0) {
|
||||
var value = message;
|
||||
this.path = 'value';
|
||||
if (this.path && _.isObject(message)) {
|
||||
value = utils.getAt(message, this.path, message);
|
||||
}
|
||||
|
||||
for (var n = 0; n < this.items.length; n++) {
|
||||
var block = this.items[n];
|
||||
if (block.enabled) {
|
||||
block.override = {
|
||||
args: [value]
|
||||
};
|
||||
ret.push(block.solve(this.scope, settings));
|
||||
}
|
||||
}
|
||||
}
|
||||
this.onSuccess(this, this._lastSettings);
|
||||
return ret;
|
||||
}
|
||||
},
|
||||
observed: [
|
||||
'topic'
|
||||
],
|
||||
getContext: function () {
|
||||
return this.context || (this.scope.getContext ? this.scope.getContext() : this);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param scope
|
||||
* @param settings
|
||||
* @param isInterface
|
||||
* @returns {boolean}
|
||||
*/
|
||||
solve: function (scope, settings, isInterface) {
|
||||
this._currentIndex = 0;
|
||||
this._return = [];
|
||||
settings = this._lastSettings = settings || this._lastSettings;
|
||||
|
||||
var instance = this.getInstance();
|
||||
if (isInterface === true && this._loop) {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
var args = this.args;
|
||||
var inArgs = this.getArgs(settings);
|
||||
if (inArgs[0]) {
|
||||
args = inArgs[0];
|
||||
}
|
||||
|
||||
if (instance) {
|
||||
var flags = settings.flags || this.flags;
|
||||
var parse = !(flags & types.CIFLAG.DONT_PARSE);
|
||||
var isExpression = (flags & types.CIFLAG.EXPRESSION);
|
||||
var value = utils.getJson(args, true, false);
|
||||
if (value === null || value === 0 || value === true || value === false || !_.isObject(value)) {
|
||||
value = {
|
||||
payload: this.args
|
||||
};
|
||||
}
|
||||
var topic = scope.expressionModel.replaceVariables(scope, this.topic, false, false);
|
||||
|
||||
if (value.payload && _.isString(value.payload) && parse) {
|
||||
var override = settings.override || this.override || {};
|
||||
var _overrides = (override && override.variables) ? override.variables : null;
|
||||
if (parse !== false) {
|
||||
value.payload = utils.convertAllEscapes(value.payload, "none");
|
||||
}
|
||||
if (isExpression && parse !== false) {
|
||||
value.payload = scope.parseExpression(value.payload, null, _overrides, null, null, null, override.args);
|
||||
}
|
||||
}
|
||||
instance.callMethod('publishTopic', utils.mixin({
|
||||
topic: topic,
|
||||
qos: this.qos,
|
||||
retain: this.retain
|
||||
}, value), this.id, this.id);
|
||||
}
|
||||
|
||||
settings = settings || {};
|
||||
this.onDidRun();
|
||||
this.onSuccess(this, settings);
|
||||
return true;
|
||||
},
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UI
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
toText: function (icon) {
|
||||
var out = '<span style="">' + this.getBlockIcon() + ' ' + this.makeEditable('name', 'top', 'text', 'Enter a name', 'inline') + ' :: ' + '</span>';
|
||||
if (this.topic) {
|
||||
out += this.makeEditable('topic', 'bottom', 'text', 'Enter a topic', 'inline');
|
||||
this.startup && (out += this.getIcon('fa-bell inline-icon text-warning', 'text-align:right;float:right;', ''));
|
||||
this.interval > 0 && (out += this.getIcon('fa-clock-o inline-icon text-warning', 'text-align:right;float:right', ''));
|
||||
}
|
||||
return out;
|
||||
},
|
||||
// standard call from interface
|
||||
canAdd: function () {
|
||||
return [];
|
||||
},
|
||||
// standard call for editing
|
||||
getFields: function () {
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
fields.push(utils.createCI('qos', types.ECIType.ENUMERATION, this.qos, {
|
||||
group: 'General',
|
||||
title: 'QOS',
|
||||
dst: 'qos',
|
||||
widget: {
|
||||
options: [
|
||||
{
|
||||
label: "0 - at most once",
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
label: "1 - at least once",
|
||||
value: 1
|
||||
},
|
||||
{
|
||||
label: "2 - exactly once",
|
||||
value: 2
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
);
|
||||
fields.push(utils.createCI('arguments', 27, this.args, {
|
||||
group: 'Arguments',
|
||||
title: 'Arguments',
|
||||
dst: 'args'
|
||||
}));
|
||||
fields.push(this.utils.createCI('flags', 5, this.flags, {
|
||||
group: 'Arguments',
|
||||
title: 'Flags',
|
||||
dst: 'flags',
|
||||
data: [
|
||||
{
|
||||
value: 0x000001000,
|
||||
label: 'Dont parse',
|
||||
title: "Do not parse the string and use it as is"
|
||||
},
|
||||
{
|
||||
value: 0x00000800,//2048
|
||||
label: 'Expression',
|
||||
title: 'Parse it as Javascript'
|
||||
}
|
||||
],
|
||||
widget: {
|
||||
hex: true
|
||||
}
|
||||
}));
|
||||
fields.push(utils.createCI('topic', types.ECIType.STRING, this.topic, {
|
||||
group: 'General',
|
||||
title: 'Topic',
|
||||
dst: 'topic',
|
||||
select: true
|
||||
}));
|
||||
fields.push(utils.createCI('retain', types.ECIType.BOOL, this.retain, {
|
||||
group: 'General',
|
||||
title: 'Retain',
|
||||
dst: 'retain'
|
||||
}));
|
||||
fields.remove(_.find(fields, {
|
||||
name: "send"
|
||||
}));
|
||||
|
||||
fields.remove(_.find(fields, {
|
||||
name: "waitForResponse"
|
||||
}));
|
||||
return fields;
|
||||
}
|
||||
});
|
||||
});
|
||||
183
packages/xblox/ref-control-freak/xblox/model/mqtt/Subscribe.js
Normal file
183
packages/xblox/ref-control-freak/xblox/model/mqtt/Subscribe.js
Normal file
@ -0,0 +1,183 @@
|
||||
/** @module xblox/model/mqtt/Subscribe **/
|
||||
define([
|
||||
'dcl/dcl',
|
||||
'xdojo/has',
|
||||
"xblox/model/Block",
|
||||
'xide/utils',
|
||||
'xblox/model/Contains',
|
||||
'xide/types'
|
||||
//'dojo/has!host-node?dojo/node!tracer',
|
||||
//'dojo/has!host-node?nxapp/utils/_console'
|
||||
], function(dcl,has,Block,utils,Contains,types,tracer,_console){
|
||||
|
||||
/**
|
||||
* @augments module:xide/mixins/EventedMixin
|
||||
* @lends module:xblox/model/Block_UI
|
||||
* @extends module:xblox/model/Block
|
||||
* @extends module:xblox/model/ModelBase
|
||||
*/
|
||||
var isServer = has('host-node');
|
||||
var console = typeof window !== 'undefined' ? window.console : global.console;
|
||||
if(isServer && tracer && console && console.error){
|
||||
console = _console;
|
||||
}
|
||||
// summary:
|
||||
// The Call Block model.
|
||||
// This block makes calls to another blocks in the same scope by action name
|
||||
|
||||
// module:
|
||||
// xblox.model.code.CallMethod
|
||||
/**
|
||||
* Base block class.
|
||||
*
|
||||
* @class module:xblox/model/mqtt/Subscribe
|
||||
* @extends module:xblox/model/Block
|
||||
*/
|
||||
return dcl([Block,Contains],{
|
||||
declaredClass:"xblox.model.mqtt.Subscribe",
|
||||
//method: (String)
|
||||
// block action name
|
||||
name:'Subscribe',
|
||||
//method: (String)
|
||||
// block action name
|
||||
topic:'Topic',
|
||||
args:'',
|
||||
deferred:false,
|
||||
sharable:true,
|
||||
context:null,
|
||||
icon:'fa-bell',
|
||||
/**
|
||||
* @type {string|null}
|
||||
*/
|
||||
path:'',
|
||||
qos:0,
|
||||
stop:function(){
|
||||
var instance = this.getInstance();
|
||||
if(instance){
|
||||
instance.callMethod('unSubscribeTopic',utils.mixin({
|
||||
topic:this.topic
|
||||
},utils.getJson(this.args || {})),this.id,this.id);
|
||||
}
|
||||
},
|
||||
onData:function(message){
|
||||
if(message && message.topic && message.topic==this.topic){
|
||||
delete message['src'];
|
||||
delete message['id'];
|
||||
var items = this[this._getContainer()];
|
||||
var settings = this._lastSettings;
|
||||
var ret=[];
|
||||
if(items.length>0){
|
||||
var value = message;
|
||||
var path = this.path && this.path.length ? this.path : (message.payload!==null) ? 'payload' : null;
|
||||
if(path && _.isObject(message)){
|
||||
value = utils.getAt(message,path,message);
|
||||
}
|
||||
for(var n = 0; n < this.items.length ; n++)
|
||||
{
|
||||
var block = this.items[n];
|
||||
if(block.enabled) {
|
||||
block.override ={
|
||||
args: [value]
|
||||
};
|
||||
ret.push(block.solve(this.scope,settings));
|
||||
}
|
||||
}
|
||||
}
|
||||
this.onSuccess(this, this._lastSettings);
|
||||
return ret;
|
||||
}
|
||||
},
|
||||
observed:[
|
||||
'topic'
|
||||
],
|
||||
getContext:function(){
|
||||
return this.context || (this.scope.getContext ? this.scope.getContext() : this);
|
||||
},
|
||||
solve:function(scope,settings){
|
||||
this._currentIndex = 0;
|
||||
this._return=[];
|
||||
this._lastSettings = settings;
|
||||
var instance = this.getInstance();
|
||||
|
||||
if(instance){
|
||||
instance.callMethod('subscribeTopic',utils.mixin({
|
||||
topic:this.topic,
|
||||
qos:this.qos
|
||||
},utils.getJson(this.args ||"{}")),this.id,this.id);
|
||||
}
|
||||
settings = settings || {};
|
||||
this.onRunThis(settings);
|
||||
},
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UI
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
toText:function(){
|
||||
var result = '<span style="">' +
|
||||
this.getBlockIcon() + '' + this.makeEditable('topic','bottom','text','Enter a topic','inline') + ' :: '+'</span>';
|
||||
|
||||
if(this.topic){
|
||||
result+= this.topic.substr(0,30);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
// standard call from interface
|
||||
canAdd:function(){
|
||||
return [];
|
||||
},
|
||||
// standard call for editing
|
||||
getFields:function(){
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
fields.push(
|
||||
utils.createCI('name',13,this.name,{
|
||||
group:'General',
|
||||
title:'Name',
|
||||
dst:'name'
|
||||
})
|
||||
);
|
||||
|
||||
fields.push(utils.createCI('arguments',27,this.args,{
|
||||
group:'Arguments',
|
||||
title:'Arguments',
|
||||
dst:'args'
|
||||
}));
|
||||
|
||||
fields.push(utils.createCI('topic',types.ECIType.STRING,this.topic,{
|
||||
group:'General',
|
||||
title:'Topic',
|
||||
dst:'topic',
|
||||
select:true
|
||||
}));
|
||||
|
||||
fields.push(utils.createCI('name',types.ECIType.ENUMERATION,this.qos,{
|
||||
group:'General',
|
||||
title:'QOS',
|
||||
dst:'qos',
|
||||
widget: {
|
||||
options: [
|
||||
{
|
||||
label:"0 - at most once",
|
||||
value:0
|
||||
},
|
||||
{
|
||||
label:"1 - at least once",
|
||||
value:1
|
||||
},
|
||||
{
|
||||
label:"2 - exactly once",
|
||||
value:2
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
);
|
||||
fields.push(utils.createCI('path',types.ECIType.STRING,this.path,{
|
||||
group:'General',
|
||||
title:'Value Path',
|
||||
dst:'path'
|
||||
}));
|
||||
return fields;
|
||||
}
|
||||
});
|
||||
});
|
||||
165
packages/xblox/ref-control-freak/xblox/model/network/SSH.js
Normal file
165
packages/xblox/ref-control-freak/xblox/model/network/SSH.js
Normal file
@ -0,0 +1,165 @@
|
||||
define([
|
||||
'dcl/dcl',
|
||||
"dojo/Deferred",
|
||||
"xblox/model/Block",
|
||||
'xide/utils',
|
||||
'xblox/model/Contains',
|
||||
'xide/types'
|
||||
], function(dcl,Deferred,Block,utils,Contains,types){
|
||||
/**
|
||||
* @augments module:xide/mixins/EventedMixin
|
||||
* @lends module:xblox/model/Block_UI
|
||||
* @extends module:xblox/model/Block
|
||||
* @extends module:xblox/model/ModelBase
|
||||
*/
|
||||
// summary:
|
||||
// The Call Block model.
|
||||
// This block makes calls to another blocks in the same scope by action name
|
||||
|
||||
// module:
|
||||
// xblox.model.code.CallMethod
|
||||
return dcl([Block,Contains],{
|
||||
declaredClass:"xblox.model.code.SSH",
|
||||
//method: (String)
|
||||
// block action name
|
||||
name:'Run Script',
|
||||
//method: (String)
|
||||
// block action name
|
||||
method:'',
|
||||
args:'',
|
||||
deferred:false,
|
||||
sharable:true,
|
||||
context:null,
|
||||
icon:'fa-code',
|
||||
description:"Runs a piece of code on a SSH connection",
|
||||
observed:[
|
||||
'method'
|
||||
],
|
||||
getContext:function(){
|
||||
return this.context || (this.scope.getContext ? this.scope.getContext() : this);
|
||||
},
|
||||
/***
|
||||
* Returns the block run result
|
||||
* @param scope
|
||||
* @param settings
|
||||
* @param run
|
||||
* @param error
|
||||
* @returns {Array}
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* @param scope
|
||||
* @param settings
|
||||
* @param run
|
||||
* @param error
|
||||
*/
|
||||
solve:function(scope,settings,run,error){
|
||||
this._currentIndex = 0;
|
||||
this._return=[];
|
||||
var _script = '' + this._get('method');
|
||||
var thiz=this,
|
||||
ctx = this.getContext(),
|
||||
items = this[this._getContainer()],
|
||||
dfd = new Deferred(),
|
||||
isDfd = thiz.deferred;
|
||||
this.onRunThis(settings);
|
||||
var _function = new Function("{" + _script + "}");
|
||||
var _args = thiz.getArgs(settings) || [];
|
||||
try {
|
||||
|
||||
if(isDfd){
|
||||
ctx.resolve=function(result){
|
||||
if(thiz._deferredObject) {
|
||||
thiz._deferredObject.resolve();
|
||||
}
|
||||
thiz.onDidRunThis(dfd,result,items,settings);
|
||||
}
|
||||
}
|
||||
var _parsed = _function.apply(ctx, _args || {});
|
||||
thiz._lastResult = _parsed;
|
||||
if (run) {
|
||||
run('Expression ' + _script + ' evaluates to ' + _parsed);
|
||||
}
|
||||
if(!isDfd) {
|
||||
thiz.onDidRunThis(dfd,_parsed,items,settings);
|
||||
}
|
||||
if (_parsed !== 'false' && _parsed !== false) {
|
||||
thiz.onSuccess(thiz, settings);
|
||||
} else {
|
||||
thiz.onFailed(thiz, settings);
|
||||
}
|
||||
} catch (e) {
|
||||
thiz.onDidRunItemError(dfd,e || {},settings);
|
||||
thiz.onFailed(thiz,settings);
|
||||
if (error) {
|
||||
error('invalid expression : \n' + _script + ': ' + e);
|
||||
}
|
||||
}
|
||||
return dfd;
|
||||
},
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UI
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
toText:function(){
|
||||
var result = this.getBlockIcon() + ' ' + this.name + ' :: ';
|
||||
if(this.method){
|
||||
result+= this.method.substr(0,50);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
// standard call from interface
|
||||
canAdd:function(){
|
||||
return [];
|
||||
},
|
||||
// standard call for editing
|
||||
getFields:function(){
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
var thiz=this;
|
||||
fields.push(
|
||||
utils.createCI('name',13,this.name,{
|
||||
group:'General',
|
||||
title:'Name',
|
||||
dst:'name'
|
||||
})
|
||||
);
|
||||
fields.push(
|
||||
utils.createCI('deferred',0,this.deferred,{
|
||||
group:'General',
|
||||
title:'Deferred',
|
||||
dst:'deferred'
|
||||
})
|
||||
);
|
||||
fields.push(utils.createCI('arguments',27,this.args,{
|
||||
group:'Arguments',
|
||||
title:'Arguments',
|
||||
dst:'args'
|
||||
}));
|
||||
fields.push(
|
||||
utils.createCI('value',types.ECIType.EXPRESSION_EDITOR,this.method,{
|
||||
group:'Script',
|
||||
title:'Script',
|
||||
dst:'method',
|
||||
select:true,
|
||||
widget:{
|
||||
allowACECache:true,
|
||||
showBrowser:false,
|
||||
showSaveButton:true,
|
||||
editorOptions:{
|
||||
showGutter:true,
|
||||
autoFocus:false
|
||||
},
|
||||
item:this
|
||||
},
|
||||
delegate:{
|
||||
runExpression:function(val,run,error){
|
||||
thiz.method=val;
|
||||
thiz.solve(thiz.scope,null,run,error);
|
||||
}
|
||||
}
|
||||
}));
|
||||
return fields;
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,345 @@
|
||||
define([
|
||||
"dcl/dcl",
|
||||
"xblox/model/server/ServerBlock",
|
||||
'xide/utils'
|
||||
], function (dcl, ServerBlock, utils) {
|
||||
/**
|
||||
* Runs a JSON-RPC-2.0 method on the server. This assumes that this block's scope has
|
||||
* a 'service object'
|
||||
*/
|
||||
return dcl(ServerBlock, {
|
||||
declaredClass:"xblox.model.server.RunServerMethod",
|
||||
description: 'Runs a JSON-RPC-2.0 method on the server',
|
||||
|
||||
/**
|
||||
* The name of the block, used in the UI
|
||||
* @member {string}
|
||||
*/
|
||||
name: 'Run Server Method',
|
||||
|
||||
/**
|
||||
* The full string of the service class method, ie: MyPHPServerClass::method
|
||||
* @member {string}
|
||||
*/
|
||||
method: 'XShell::run',
|
||||
/**
|
||||
* Arguments for the server call
|
||||
* @member {string}
|
||||
*/
|
||||
args: '',
|
||||
/**
|
||||
* Override in super class, this block runs async by default
|
||||
* @member {boolean}
|
||||
*/
|
||||
deferred: true,
|
||||
/**
|
||||
* The default for the server RPC class
|
||||
* @member {string}
|
||||
*/
|
||||
defaultServiceClass: 'XShell',
|
||||
/**
|
||||
* The default for the server RPC class method
|
||||
* @member {string}
|
||||
*/
|
||||
defaultServiceMethod: 'run',
|
||||
|
||||
sharable:true,
|
||||
/**
|
||||
* Callback when user edited the 'method' field. This will pre-populate the arguments field when empty
|
||||
* with the known SMD parameters : if possible.
|
||||
* @param newMethod
|
||||
* @param cis
|
||||
*/
|
||||
onMethodChanged: function (newMethod, cis) {
|
||||
|
||||
this.method = newMethod;
|
||||
|
||||
//we auto populate the arguments field
|
||||
if (!utils.isValidString(this.args)) {
|
||||
|
||||
var newServerParams = this.getServerParams();
|
||||
if (newServerParams) {
|
||||
this._updateArgs(newServerParams, cis);
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
_getArgs: function () {
|
||||
|
||||
|
||||
/*
|
||||
var test = [
|
||||
{
|
||||
"name": "shellType",
|
||||
"default": "sh", "optional": false, "value": "notset"
|
||||
},
|
||||
{
|
||||
"name": "cmd",
|
||||
"optional": false,
|
||||
"value": "[CurrentDirectory]"
|
||||
},
|
||||
{
|
||||
"name": "cwd",
|
||||
"default": null,
|
||||
"optional": true,
|
||||
"value": "[CurrentDirectory]"
|
||||
}
|
||||
];*/
|
||||
|
||||
|
||||
var _args = utils.getJson(this.args || '[]');
|
||||
var result = [];
|
||||
if (_args) {
|
||||
var isSMD = false;
|
||||
//now check this is still in 'SMD' format
|
||||
if (_args && _args[0] && _args[0]['optional'] != null) {
|
||||
isSMD = true;
|
||||
}
|
||||
//if SMD true, evaluate the value field
|
||||
if (isSMD) {
|
||||
for (var i = 0; i < _args.length; i++) {
|
||||
var _arg = _args[i];
|
||||
var _variableValue = _arg.value;
|
||||
var isBase64 = _arg.name.indexOf('Base64') != -1;
|
||||
if(isBase64){
|
||||
_variableValue = this.getService().base64_encode(_variableValue);
|
||||
}
|
||||
|
||||
if (_arg.value !== 'notset') {
|
||||
if (_arg.value.indexOf('[') != -1 && _arg.value.indexOf(']') != -1) {
|
||||
_variableValue = this.scope.expressionModel.replaceVariables(this.scope, _arg.value, false, false);
|
||||
if (_arg.name.indexOf('Base64') != -1) {
|
||||
_variableValue = this.getService().base64_encode(_variableValue);
|
||||
}
|
||||
result.push(_variableValue);
|
||||
} else {
|
||||
result.push(_variableValue || _arg['default']);
|
||||
}
|
||||
|
||||
} else {
|
||||
result.push(_arg['default'] || _variableValue);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
} else {
|
||||
return [this.args];
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
},
|
||||
/**
|
||||
* Update this.args (string) with a SMD parameter set
|
||||
* @param params
|
||||
* @param cis
|
||||
* @private
|
||||
*/
|
||||
_updateArgs: function (params, cis) {
|
||||
|
||||
var argumentWidget = this.utils.getCIWidgetByName(cis, 'args');
|
||||
if (argumentWidget) {
|
||||
var _string = JSON.stringify(params);
|
||||
argumentWidget.editBox.set('value', _string);
|
||||
this.args = _string;
|
||||
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Find SMD for the current method
|
||||
* @returns {*}
|
||||
*/
|
||||
getServerParams: function () {
|
||||
var service = this.getService();
|
||||
var params = service.getParameterMap(this.getServiceClass(), this.getServiceMethod());
|
||||
if (params) {
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var param = params[i];
|
||||
param.value = 'notset';
|
||||
}
|
||||
}
|
||||
return params;
|
||||
},
|
||||
onReloaded: function (evt) {
|
||||
|
||||
console.log('sdfsd');
|
||||
this._solve()
|
||||
},
|
||||
_solve:function(scope,settings,run,error){
|
||||
|
||||
console.log('solve223');
|
||||
|
||||
},
|
||||
/***
|
||||
* Returns the block run result
|
||||
* @param scope
|
||||
* @param settings
|
||||
* @param run
|
||||
* @param error
|
||||
* @returns {Array}
|
||||
*/
|
||||
solve: function (scope, settings, run, error) {
|
||||
|
||||
|
||||
|
||||
this._return = [];
|
||||
this._lastResult=null;
|
||||
var thiz = this;
|
||||
var ret = [];
|
||||
|
||||
//this._solve();
|
||||
|
||||
|
||||
|
||||
//console.dir(this.scope);
|
||||
|
||||
|
||||
if(!this.isInValidState()){
|
||||
this.onFailed(this, settings);
|
||||
return ret;
|
||||
}
|
||||
|
||||
var _args = this._getArgs();//returns SMD ready array of values
|
||||
var _cbSuccess = function (response) {
|
||||
thiz._lastResult = thiz.utils.getJson(response) || [response];
|
||||
thiz.resolved(thiz._lastResult);
|
||||
thiz.onSuccess(thiz, settings);
|
||||
};
|
||||
var _cbError = function (response) {
|
||||
//console.error(' server method ' + thiz.method + ' with params ' + JSON.stringify(_args) + 'failed ' + response);
|
||||
thiz._lastResult = thiz.utils.getJson(response) || [response];
|
||||
thiz.resolved(thiz._lastResult);
|
||||
thiz.onFailed(thiz, settings);
|
||||
};
|
||||
|
||||
this.onRun(this, settings);
|
||||
|
||||
var service = this.getService();
|
||||
var serviceObject = this.scope.serviceObject;
|
||||
//service.callMethodEx(this.getServiceClass(), this.getServiceMethod(), _args, _cbSuccess,_cbError);
|
||||
|
||||
console.error('run deferred');
|
||||
|
||||
var dfd = serviceObject.runDeferred(this.getServiceClass(),this.getServiceMethod(),_args);
|
||||
if(dfd){
|
||||
dfd.then(function(data){
|
||||
console.error('returned ',data);
|
||||
});
|
||||
}
|
||||
|
||||
return dfd;
|
||||
},
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UI
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
toText: function () {
|
||||
|
||||
var result = this.getBlockIcon() + ' ' + this.name + ' :: ';
|
||||
if (this.method) {
|
||||
result += this.method.substr(0, 50);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
// standard call from interface
|
||||
canAdd: function () {
|
||||
return [];
|
||||
},
|
||||
// standard call for editing
|
||||
getFields: function () {
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
var thiz = this;
|
||||
|
||||
fields.push(utils.createCI('value', 25, this.method, {
|
||||
group: 'General',
|
||||
title: 'Method',
|
||||
dst: 'method',
|
||||
description: 'This should be in the format : MyServerClass::myMethod',
|
||||
delegate: {
|
||||
runExpression: function (val, run, error) {
|
||||
var old = thiz.method;
|
||||
thiz.method = val;
|
||||
var _res = thiz.solve(thiz.scope, null, run, error);
|
||||
}
|
||||
}
|
||||
}));
|
||||
fields = fields.concat(this.getServerDefaultFields());
|
||||
return fields;
|
||||
},
|
||||
getBlockIcon: function () {
|
||||
return '<span class="fa-plug"></span>';
|
||||
},
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Store
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Store function override
|
||||
* @param parent
|
||||
* @returns {boolean}
|
||||
*/
|
||||
mayHaveChildren: function (parent) {
|
||||
return this.items != null && this.items.length > 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Store function override
|
||||
* @param parent
|
||||
* @returns {Array}
|
||||
*/
|
||||
getChildren: function (parent) {
|
||||
return this.items;
|
||||
},
|
||||
|
||||
onChangeField: function (field, newValue, cis) {
|
||||
if (field === 'method') {
|
||||
this.onMethodChanged(newValue, cis);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Check our scope has a service object
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isInValidState: function () {
|
||||
|
||||
return this.getService() != null;
|
||||
},
|
||||
getService: function () {
|
||||
|
||||
var service = this.scope.getService();
|
||||
|
||||
if(!service){
|
||||
console.error('have no service object');
|
||||
}
|
||||
return service;
|
||||
},
|
||||
getServiceClass: function () {
|
||||
return this.method.split('::')[0] || this.defaultServiceClass;
|
||||
},
|
||||
getServiceMethod: function () {
|
||||
return this.method.split('::')[1] || this.defaultServiceMethod;
|
||||
},
|
||||
hasMethod: function (method) {
|
||||
return this.isInValidState() &&
|
||||
this.getService()[this.getServiceClass()] != null &&
|
||||
this.getService()[this.getServiceClass()][this.getServiceMethod()] != null
|
||||
},
|
||||
hasServerClass: function (_class) {
|
||||
return this.isInValidState() &&
|
||||
this.getService()[this.getServiceClass()] != null;
|
||||
},
|
||||
getServerFunction: function () {
|
||||
if (this.isInValidState() && this.getServiceClass() && this.getServiceMethod()) {
|
||||
return this.getService()[this.getServiceClass()][this.getServiceMethod()];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,190 @@
|
||||
define([
|
||||
'dcl/dcl',
|
||||
"xblox/model/Block",
|
||||
"xide/utils"
|
||||
], function (dcl,Block,utils) {
|
||||
/**
|
||||
* Runs a JSON-RPC-2.0 method on the server. This assumes that this block's scope has
|
||||
* a 'service object'
|
||||
*/
|
||||
return dcl(Block, {
|
||||
declaredClass:"xblox.model.server.ServerBlock",
|
||||
/**
|
||||
* The name of the block, used in the UI
|
||||
* @member {string}
|
||||
*/
|
||||
name: 'Run Server Block',
|
||||
/**
|
||||
* The full string of the service class method, ie: MyPHPServerClass::method
|
||||
* @member {string}
|
||||
*/
|
||||
method: 'XShell::run',
|
||||
/**
|
||||
* Arguments for the server call
|
||||
* @member {string}
|
||||
*/
|
||||
args: '',
|
||||
/**
|
||||
* Override in super class, this block runs async by default
|
||||
* @member {boolean}
|
||||
*/
|
||||
deferred: true,
|
||||
/**
|
||||
* The default for the server RPC class
|
||||
* @member {string}
|
||||
*/
|
||||
defaultServiceClass: 'XShell',
|
||||
/**
|
||||
* The default for the server RPC class method
|
||||
* @member {string}
|
||||
*/
|
||||
defaultServiceMethod: 'run',
|
||||
/**
|
||||
* Debugging
|
||||
* @member {function}
|
||||
*/
|
||||
sharable:true,
|
||||
|
||||
onReloaded: function () {
|
||||
},
|
||||
/***
|
||||
* Returns the block run result
|
||||
* @param scope
|
||||
* @param settings
|
||||
* @param run
|
||||
* @param error
|
||||
* @returns {Array}
|
||||
*/
|
||||
solve: function (scope, settings, run, error) {
|
||||
|
||||
this._currentIndex = 0;
|
||||
this._return = [];
|
||||
|
||||
var _script = '' + this.method;
|
||||
var thiz = this;
|
||||
|
||||
if (_script && _script.length) {
|
||||
|
||||
var _function = new Function("{" + _script + "}");
|
||||
var _args = this.getArgs();
|
||||
try {
|
||||
var _parsed = _function.apply(this, _args || {});
|
||||
this._lastResult = _parsed;
|
||||
|
||||
if (run) {
|
||||
run('Expression ' + _script + ' evaluates to ' + _parsed);
|
||||
}
|
||||
if (_parsed !== 'false' && _parsed !== false) {
|
||||
this.onSuccess(this, settings);
|
||||
} else {
|
||||
this.onFailed(this, settings);
|
||||
return [];
|
||||
}
|
||||
} catch (e) {
|
||||
if (error) {
|
||||
error('invalid expression : \n' + _script + ': ' + e);
|
||||
}
|
||||
this.onFailed(this, settings);
|
||||
return [];
|
||||
}
|
||||
} else {
|
||||
console.error('have no script');
|
||||
}
|
||||
var ret = [], items = this[this._getContainer()];
|
||||
if (items.length) {
|
||||
this.runFrom(items, 0, settings);
|
||||
} else {
|
||||
this.onSuccess(this, settings);
|
||||
}
|
||||
|
||||
return ret;
|
||||
},
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UI
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
toText: function () {
|
||||
|
||||
var result = this.getBlockIcon() + ' ' + this.name + ' :: ';
|
||||
if (this.method) {
|
||||
result += this.method.substr(0, 50);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
// standard call from interface
|
||||
canAdd: function () {
|
||||
return [];
|
||||
},
|
||||
getServerDefaultFields:function(target){
|
||||
|
||||
var fields = target || [];
|
||||
|
||||
fields.push(utils.createCI('args', 27, this.args, {
|
||||
group: 'General',
|
||||
title: 'Arguments',
|
||||
dst: 'args'
|
||||
}));
|
||||
|
||||
return fields;
|
||||
},
|
||||
getBlockIcon: function () {
|
||||
return '<span class="fa-plug"></span>';
|
||||
},
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Store
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Store function override
|
||||
* @param parent
|
||||
* @returns {boolean}
|
||||
*/
|
||||
mayHaveChildren: function (parent) {
|
||||
return this.items != null && this.items.length > 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Store function override
|
||||
* @param parent
|
||||
* @returns {Array}
|
||||
*/
|
||||
getChildren: function (parent) {
|
||||
return this.items;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check our scope has a service object
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isInValidState: function () {
|
||||
return this.getService() != null;
|
||||
},
|
||||
getService: function () {
|
||||
return this.scope.getService();
|
||||
},
|
||||
getServiceClass: function () {
|
||||
return this.method.split('::')[0] || this.defaultServiceClass;
|
||||
},
|
||||
getServiceMethod: function () {
|
||||
return this.method.split('::')[1] || this.defaultServiceMethod;
|
||||
},
|
||||
hasMethod: function (method) {
|
||||
return this.isInValidState() &&
|
||||
this.getService()[this.getServiceClass()] != null &&
|
||||
this.getService()[this.getServiceClass()][this.getServiceMethod()] != null
|
||||
},
|
||||
hasServerClass: function (_class) {
|
||||
return this.isInValidState() &&
|
||||
this.getService()[this.getServiceClass()] != null;
|
||||
},
|
||||
getServerFunction: function () {
|
||||
if (this.isInValidState() && this.getServiceClass() && this.getServiceMethod()) {
|
||||
return this.getService()[this.getServiceClass()][this.getServiceMethod()];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
});
|
||||
301
packages/xblox/ref-control-freak/xblox/model/server/Shell.js
Normal file
301
packages/xblox/ref-control-freak/xblox/model/server/Shell.js
Normal file
@ -0,0 +1,301 @@
|
||||
define([
|
||||
"dcl/dcl",
|
||||
"xblox/model/server/ServerBlock",
|
||||
'xide/utils',
|
||||
'xide/types',
|
||||
'xcf/model/Command'
|
||||
], function (dcl, ServerBlock, utils, types, Command) {
|
||||
/**
|
||||
* Runs a JSON-RPC-2.0 method on the server. This assumes that this block's scope has
|
||||
* a 'service object'
|
||||
*/
|
||||
return dcl([Command, ServerBlock], {
|
||||
declaredClass: "xblox.model.server.Shell",
|
||||
description: 'Runs a JSON-RPC-2.0 method on the server',
|
||||
/**
|
||||
* The name of the block, used in the UI
|
||||
* @member {string}
|
||||
*/
|
||||
name: 'Run Shell',
|
||||
|
||||
/**
|
||||
* The full string of the service class method, ie: MyPHPServerClass::method
|
||||
* @member {string}
|
||||
*/
|
||||
method: '',
|
||||
/**
|
||||
* Arguments for the server call
|
||||
* @member {string}
|
||||
*/
|
||||
args: '',
|
||||
/**
|
||||
* Override in super class, this block runs async by default
|
||||
* @member {boolean}
|
||||
*/
|
||||
deferred: true,
|
||||
/**
|
||||
* The default for the server RPC class
|
||||
* @member {string}
|
||||
*/
|
||||
defaultServiceClass: 'XShell',
|
||||
/**
|
||||
* The default for the server RPC class method
|
||||
* @member {string}
|
||||
*/
|
||||
defaultServiceMethod: 'run',
|
||||
|
||||
sharable: true,
|
||||
/**
|
||||
* Callback when user edited the 'method' field. This will pre-populate the arguments field when empty
|
||||
* with the known SMD parameters : if possible.
|
||||
* @param newMethod
|
||||
* @param cis
|
||||
*/
|
||||
onMethodChanged: function (newMethod, cis) {
|
||||
this.method = newMethod;
|
||||
//we auto populate the arguments field
|
||||
if (!utils.isValidString(this.args)) {
|
||||
|
||||
var newServerParams = this.getServerParams();
|
||||
if (newServerParams) {
|
||||
this._updateArgs(newServerParams, cis);
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
_getArgs: function () {
|
||||
|
||||
|
||||
/*
|
||||
var test = [
|
||||
{
|
||||
"name": "shellType",
|
||||
"default": "sh", "optional": false, "value": "notset"
|
||||
},
|
||||
{
|
||||
"name": "cmd",
|
||||
"optional": false,
|
||||
"value": "[CurrentDirectory]"
|
||||
},
|
||||
{
|
||||
"name": "cwd",
|
||||
"default": null,
|
||||
"optional": true,
|
||||
"value": "[CurrentDirectory]"
|
||||
}
|
||||
];*/
|
||||
|
||||
|
||||
var _args = utils.getJson(this.args || '[]');
|
||||
var result = [];
|
||||
if (_args) {
|
||||
var isSMD = false;
|
||||
//now check this is still in 'SMD' format
|
||||
if (_args && _args[0] && _args[0]['optional'] != null) {
|
||||
isSMD = true;
|
||||
}
|
||||
//if SMD true, evaluate the value field
|
||||
if (isSMD) {
|
||||
for (var i = 0; i < _args.length; i++) {
|
||||
var _arg = _args[i];
|
||||
var _variableValue = _arg.value;
|
||||
var isBase64 = _arg.name.indexOf('Base64') != -1;
|
||||
if (isBase64) {
|
||||
_variableValue = this.getService().base64_encode(_variableValue);
|
||||
}
|
||||
|
||||
if (_arg.value !== 'notset') {
|
||||
if (_arg.value.indexOf('[') != -1 && _arg.value.indexOf(']') != -1) {
|
||||
_variableValue = this.scope.expressionModel.replaceVariables(this.scope, _arg.value, false, false);
|
||||
if (_arg.name.indexOf('Base64') != -1) {
|
||||
_variableValue = this.getService().base64_encode(_variableValue);
|
||||
}
|
||||
result.push(_variableValue);
|
||||
} else {
|
||||
result.push(_variableValue || _arg['default']);
|
||||
}
|
||||
|
||||
} else {
|
||||
result.push(_arg['default'] || _variableValue);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
} else {
|
||||
return [this.args];
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
},
|
||||
/**
|
||||
* Update this.args (string) with a SMD parameter set
|
||||
* @param params
|
||||
* @param cis
|
||||
* @private
|
||||
*/
|
||||
_updateArgs: function (params, cis) {
|
||||
|
||||
var argumentWidget = this.utils.getCIWidgetByName(cis, 'args');
|
||||
if (argumentWidget) {
|
||||
var _string = JSON.stringify(params);
|
||||
argumentWidget.editBox.set('value', _string);
|
||||
this.args = _string;
|
||||
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Find SMD for the current method
|
||||
* @returns {*}
|
||||
*/
|
||||
getServerParams: function () {
|
||||
var service = this.getService();
|
||||
var params = service.getParameterMap(this.getServiceClass(), this.getServiceMethod());
|
||||
if (params) {
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var param = params[i];
|
||||
param.value = 'notset';
|
||||
}
|
||||
}
|
||||
return params;
|
||||
},
|
||||
/***
|
||||
* Returns the block run result
|
||||
* @param scope
|
||||
* @param settings
|
||||
* @param run
|
||||
* @param error
|
||||
* @returns {Array}
|
||||
*/
|
||||
solve: function (scope, settings, isInterface, send, run, error) {
|
||||
this._return = [];
|
||||
this._lastResult = null;
|
||||
var thiz = this;
|
||||
var ret = [];
|
||||
settings = this._lastSettings = settings || this._lastSettings;
|
||||
var instance = this.getInstance();
|
||||
var code = scope.expressionModel.replaceVariables(scope, this.method, false, false);
|
||||
if (instance) {
|
||||
instance.runShell(code, utils.mixin({}, {}), this.id, this.id, this);
|
||||
}else{
|
||||
scope.ctx.getDeviceManager().sendManagerCommand(types.SOCKET_SERVER_COMMANDS.RUN_SHELL, {
|
||||
cmd: code,
|
||||
args: [],
|
||||
options: utils.mixin({}, {
|
||||
params: {
|
||||
id: this.id,
|
||||
src: this.id
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
return;
|
||||
|
||||
},
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UI
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
toText: function () {
|
||||
|
||||
var result = this.getBlockIcon() + ' ' + this.name + ' :: ';
|
||||
if (this.method) {
|
||||
result += this.method.substr(0, 50);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
// standard call from interface
|
||||
canAdd: function () {
|
||||
return [];
|
||||
},
|
||||
// standard call for editing
|
||||
getFields: function () {
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
var thiz = this;
|
||||
fields.push(utils.createCI('value', 25, this.method, {
|
||||
group: 'General',
|
||||
title: 'Cmd',
|
||||
dst: 'method',
|
||||
delegate: {
|
||||
runExpression: function (val, run, error) {
|
||||
var old = thiz.method;
|
||||
thiz.method = val;
|
||||
var _res = thiz.solve(thiz.scope, null, run, error);
|
||||
}
|
||||
}
|
||||
}));
|
||||
return fields;
|
||||
},
|
||||
getBlockIcon: function () {
|
||||
return '<span class="fa-plug"></span>';
|
||||
},
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Store
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Store function override
|
||||
* @param parent
|
||||
* @returns {boolean}
|
||||
*/
|
||||
mayHaveChildren: function (parent) {
|
||||
return this.items != null && this.items.length > 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Store function override
|
||||
* @param parent
|
||||
* @returns {Array}
|
||||
*/
|
||||
getChildren: function (parent) {
|
||||
return this.items;
|
||||
},
|
||||
|
||||
onChangeField: function (field, newValue, cis) {
|
||||
if (field === 'method') {
|
||||
this.onMethodChanged(newValue, cis);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Check our scope has a service object
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isInValidState: function () {
|
||||
|
||||
return this.getService() != null;
|
||||
},
|
||||
getService: function () {
|
||||
var service = this.scope.getService();
|
||||
if (!service) {
|
||||
console.error('have no service object');
|
||||
}
|
||||
return service;
|
||||
},
|
||||
getServiceClass: function () {
|
||||
return this.method.split('::')[0] || this.defaultServiceClass;
|
||||
},
|
||||
getServiceMethod: function () {
|
||||
return this.method.split('::')[1] || this.defaultServiceMethod;
|
||||
},
|
||||
hasMethod: function (method) {
|
||||
return this.isInValidState() &&
|
||||
this.getService()[this.getServiceClass()] != null &&
|
||||
this.getService()[this.getServiceClass()][this.getServiceMethod()] != null
|
||||
},
|
||||
hasServerClass: function (_class) {
|
||||
return this.isInValidState() &&
|
||||
this.getService()[this.getServiceClass()] != null;
|
||||
},
|
||||
getServerFunction: function () {
|
||||
if (this.isInValidState() && this.getServiceClass() && this.getServiceMethod()) {
|
||||
return this.getService()[this.getServiceClass()][this.getServiceMethod()];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
});
|
||||
15
packages/xblox/ref-control-freak/xblox/model/simple.json
Normal file
15
packages/xblox/ref-control-freak/xblox/model/simple.json
Normal file
@ -0,0 +1,15 @@
|
||||
[
|
||||
{
|
||||
"_containsChildrenIds": [],
|
||||
"group": "conditionalProcess",
|
||||
"id": "02f10325-cc03-6fd5-c1ce-c47f2d1a0f5a",
|
||||
"method": "test",
|
||||
"declaredClass": "xblox.model.code.CallMethod",
|
||||
"name": "Call Method",
|
||||
"args": "",
|
||||
"serializeMe": true,
|
||||
"enabled": true,
|
||||
"renderBlockIcon": true,
|
||||
"order": 0
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,213 @@
|
||||
define([
|
||||
"dojo/_base/declare",
|
||||
"dojo/_base/lang",
|
||||
"dojo/Deferred",
|
||||
"xblox/model/Block",
|
||||
'xide/utils'
|
||||
], function (declare, lang, Deferred, Block, utils) {
|
||||
|
||||
/**
|
||||
* poor man clone
|
||||
* @param point
|
||||
* @returns {*[]}
|
||||
*/
|
||||
function clone(point) { //TODO: use gl-vec2 for this
|
||||
return [point[0], point[1]]
|
||||
}
|
||||
|
||||
/**
|
||||
* help struct
|
||||
* @param x
|
||||
* @param y
|
||||
* @returns {*[]}
|
||||
*/
|
||||
function vec2(x, y) {
|
||||
return [x, y]
|
||||
}
|
||||
|
||||
/**
|
||||
* the bezier func
|
||||
* @param opt
|
||||
* @example
|
||||
|
||||
|
||||
var bezier = require('adaptive-bezier-curve')
|
||||
|
||||
var start = [20, 20],
|
||||
c1 = [100, 159],
|
||||
c2 = [50, 200],
|
||||
end = [200, 20],
|
||||
scale = 2
|
||||
|
||||
var points = bezier(start, c1, c2, end, scale)
|
||||
|
||||
//returns a list of 2d points: [ [x,y], [x,y], [x,y] ... ]
|
||||
|
||||
* @returns {Function}
|
||||
*/
|
||||
function createQuadraticBuilder(opt) {
|
||||
|
||||
opt = opt || {}
|
||||
|
||||
var RECURSION_LIMIT = typeof opt.recursion === 'number' ? opt.recursion : 8;
|
||||
var FLT_EPSILON = typeof opt.epsilon === 'number' ? opt.epsilon : 1.19209290e-7;
|
||||
var PATH_DISTANCE_EPSILON = typeof opt.pathEpsilon === 'number' ? opt.pathEpsilon : 1.0;
|
||||
|
||||
var curve_angle_tolerance_epsilon = typeof opt.angleEpsilon === 'number' ? opt.angleEpsilon : 0.01;
|
||||
var m_angle_tolerance = opt.angleTolerance || 0;
|
||||
|
||||
return function quadraticCurve(start, c1, end, scale, points) {
|
||||
if (!points)
|
||||
points = []
|
||||
|
||||
scale = typeof scale === 'number' ? scale : 1.0
|
||||
var distanceTolerance = PATH_DISTANCE_EPSILON / scale;
|
||||
distanceTolerance *= distanceTolerance;
|
||||
begin(start, c1, end, points, distanceTolerance);
|
||||
return points
|
||||
};
|
||||
|
||||
////// Based on:
|
||||
////// https://github.com/pelson/antigrain/blob/master/agg-2.4/src/agg_curves.cpp
|
||||
|
||||
function begin(start, c1, end, points, distanceTolerance) {
|
||||
points.push(clone(start));
|
||||
var x1 = start[0],
|
||||
y1 = start[1],
|
||||
x2 = c1[0],
|
||||
y2 = c1[1],
|
||||
x3 = end[0],
|
||||
y3 = end[1];
|
||||
recursive(x1, y1, x2, y2, x3, y3, points, distanceTolerance, 0);
|
||||
points.push(clone(end))
|
||||
}
|
||||
|
||||
|
||||
function recursive(x1, y1, x2, y2, x3, y3, points, distanceTolerance, level) {
|
||||
if (level > RECURSION_LIMIT)
|
||||
return;
|
||||
|
||||
var pi = Math.PI;
|
||||
|
||||
// Calculate all the mid-points of the line segments
|
||||
//----------------------
|
||||
var x12 = (x1 + x2) / 2;
|
||||
var y12 = (y1 + y2) / 2;
|
||||
var x23 = (x2 + x3) / 2;
|
||||
var y23 = (y2 + y3) / 2;
|
||||
var x123 = (x12 + x23) / 2;
|
||||
var y123 = (y12 + y23) / 2;
|
||||
|
||||
var dx = x3 - x1;
|
||||
var dy = y3 - y1;
|
||||
var d = Math.abs(((x2 - x3) * dy - (y2 - y3) * dx));
|
||||
|
||||
if (d > FLT_EPSILON) {
|
||||
// Regular care
|
||||
//-----------------
|
||||
if (d * d <= distanceTolerance * (dx * dx + dy * dy)) {
|
||||
// If the curvature doesn't exceed the distance_tolerance value
|
||||
// we tend to finish subdivisions.
|
||||
//----------------------
|
||||
if (m_angle_tolerance < curve_angle_tolerance_epsilon) {
|
||||
points.push(vec2(x123, y123));
|
||||
return
|
||||
}
|
||||
|
||||
// Angle & Cusp Condition
|
||||
//----------------------
|
||||
var da = Math.abs(Math.atan2(y3 - y2, x3 - x2) - Math.atan2(y2 - y1, x2 - x1))
|
||||
if (da >= pi) da = 2 * pi - da
|
||||
|
||||
if (da < m_angle_tolerance) {
|
||||
// Finally we can stop the recursion
|
||||
//----------------------
|
||||
points.push(vec2(x123, y123));
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Collinear case
|
||||
//-----------------
|
||||
dx = x123 - (x1 + x3) / 2;
|
||||
dy = y123 - (y1 + y3) / 2;
|
||||
if (dx * dx + dy * dy <= distanceTolerance) {
|
||||
points.push(vec2(x123, y123));
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Continue subdivision
|
||||
//----------------------
|
||||
recursive(x1, y1, x12, y12, x123, y123, points, distanceTolerance, level + 1);
|
||||
recursive(x123, y123, x23, y23, x3, y3, points, distanceTolerance, level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Block to interpolate any value given a curve and a boundary.
|
||||
*
|
||||
* This is will be THE performance test for xblox it self!
|
||||
*
|
||||
* Prove that this block can be fast enough to interpolate any value,
|
||||
* fast enough for being used in animations. This block is meant
|
||||
* to be used with SetStyle on certain properties like position/color
|
||||
*
|
||||
* Block signature
|
||||
|
||||
//frames
|
||||
InParameter("Number of steps", INT, "100");
|
||||
//curve, static for now
|
||||
InParameter("Progression Curve", 2DCURVE );
|
||||
|
||||
//window
|
||||
InParameter("Min", FLOAT, "0.0");
|
||||
InParameter("Max", FLOAT, "1.0");
|
||||
|
||||
//outs
|
||||
OutParameter("Value", FLOAT, "0.0" );
|
||||
OutParameter("Delta", FLOAT, "0.0" );
|
||||
|
||||
* @link http://www.jasondavies.com/animated-bezier/
|
||||
* @link https://github.com/mattdesl/adaptive-bezier-curve
|
||||
**/
|
||||
|
||||
var bezInterpolate = declare("xblox.model.transform.BezierInterpolate", [Block], {
|
||||
|
||||
name: 'Bezier-Interpolate',
|
||||
method: '',
|
||||
args: '',
|
||||
deferred: false,
|
||||
sharable: true,
|
||||
context: null,
|
||||
description: "Transform a float value into another float value according to a 2d bezier curve shape, and given boundaries.",
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UI
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
canAdd: function () {
|
||||
return [];
|
||||
},
|
||||
// standard call for editing
|
||||
getFields: function () {
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
var thiz = this;
|
||||
fields.push(this.utils.createCI('value', 13, this.args, {
|
||||
group: 'General',
|
||||
title: 'Value',
|
||||
dst: 'args'
|
||||
}));
|
||||
return fields;
|
||||
},
|
||||
getBlockIcon: function () {
|
||||
return '<span class="fa-code"></span>';
|
||||
}
|
||||
});
|
||||
|
||||
bezInterpolate.createQuadraticBuilder = createQuadraticBuilder();//statics
|
||||
|
||||
return bezInterpolate;
|
||||
|
||||
});
|
||||
@ -0,0 +1,60 @@
|
||||
define([
|
||||
"dojo/_base/declare",
|
||||
"dojo/_base/lang",
|
||||
"dojo/Deferred",
|
||||
"xblox/model/Block",
|
||||
'xide/utils'
|
||||
], function(declare,lang,Deferred,Block,utils){
|
||||
return declare("xblox.model.transorm.Bezier",[Block],{
|
||||
name:'Run Script',
|
||||
method:'',
|
||||
args:'',
|
||||
deferred:false,
|
||||
sharable:true,
|
||||
context:null,
|
||||
description:"Transform a float value into another float value according to a 2d bezier curve shape, and given boundaries. ",
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UI
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
toText:function(){
|
||||
var result = this.getBlockIcon() + ' ' + this.name + ' :: ';
|
||||
if(this.method){
|
||||
result+= this.method.substr(0,50);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
// standard call from interface
|
||||
canAdd:function(){
|
||||
return [];
|
||||
},
|
||||
// standard call for editing
|
||||
getFields:function(){
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields();
|
||||
var thiz=this;
|
||||
fields.push(
|
||||
this.utils.createCI('value',25,this.method,{
|
||||
group:'General',
|
||||
title:'Script',
|
||||
dst:'method',
|
||||
delegate:{
|
||||
runExpression:function(val,run,error){
|
||||
var old = thiz.method;
|
||||
thiz.method=val;
|
||||
var _res = thiz.solve(thiz.scope,null,run,error);
|
||||
}
|
||||
}
|
||||
}));
|
||||
fields.push(this.utils.createCI('value',27,this.args,{
|
||||
group:'General',
|
||||
title:'Arguments',
|
||||
dst:'args'
|
||||
}));
|
||||
return fields;
|
||||
},
|
||||
getBlockIcon:function(){
|
||||
return '<span class="fa-code"></span>';
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,127 @@
|
||||
/** @module xblox/model/variables/Variable */
|
||||
define([
|
||||
'dcl/dcl',
|
||||
'xide/types',
|
||||
"xblox/model/Block"
|
||||
], function(dcl,types,Block){
|
||||
/**
|
||||
* The command model. A 'command' consists out of a few parameters and a series of
|
||||
* expressions. Those expressions need to be evaluated before send them to the device
|
||||
*
|
||||
* @class module:xblox.model.variables.Variable
|
||||
* @augments module:xide/mixins/EventedMixin
|
||||
* @extends module:xblox/model/Block_UI
|
||||
* @extends module:xblox/model/Block
|
||||
*/
|
||||
return dcl(Block,{
|
||||
declaredClass:"xblox.model.variables.Variable",
|
||||
//name: String
|
||||
// the variable's name, it should be unique within a scope
|
||||
name:null,
|
||||
|
||||
//value: Current variable value
|
||||
value:null,
|
||||
|
||||
register:true,
|
||||
|
||||
readOnly:false,
|
||||
|
||||
initial:null,
|
||||
|
||||
isVariable:true,
|
||||
flags: 0x000001000,
|
||||
getValue:function(){
|
||||
return this.value;
|
||||
},
|
||||
canDisable:function(){
|
||||
return false;
|
||||
},
|
||||
canMove:function(){
|
||||
return false;
|
||||
},
|
||||
getIconClass:function(){
|
||||
return 'el-icon-quotes-alt';
|
||||
},
|
||||
getBlockIcon:function(){
|
||||
return '<span class="'+this.icon+'"></span> ';
|
||||
},
|
||||
toText:function(){
|
||||
return "<span class='text-primary'>" + this.getBlockIcon() + this.makeEditable('name','right','text','Enter a unique name','inline') +"</span>";
|
||||
},
|
||||
solve:function(){
|
||||
|
||||
var _result = this.scope.parseExpression(this.getValue(),true);
|
||||
//console.log('resolved variable ' + this.title + ' to ' + _result);
|
||||
return [];
|
||||
|
||||
},
|
||||
getFields:function(){
|
||||
var fields = this.getDefaultFields();
|
||||
var thiz=this,
|
||||
defaultArgs = {
|
||||
allowACECache:true,
|
||||
showBrowser:false,
|
||||
showSaveButton:true,
|
||||
editorOptions:{
|
||||
showGutter:false,
|
||||
autoFocus:false,
|
||||
hasConsole:false
|
||||
},
|
||||
aceOptions:{
|
||||
hasEmmet:false,
|
||||
hasLinking:false,
|
||||
hasMultiDocs:false
|
||||
},
|
||||
item:this
|
||||
};
|
||||
|
||||
fields.push(this.utils.createCI('title',types.ECIType.STRING,this.name,{
|
||||
group:'General',
|
||||
title:'Name',
|
||||
dst:'name'
|
||||
}));
|
||||
|
||||
fields.push(this.utils.createCI('value',types.ECIType.EXPRESSION,this.value,{
|
||||
group:'General',
|
||||
title:'Value',
|
||||
dst:'value',
|
||||
delegate:{
|
||||
runExpression:function(val,run,error){
|
||||
return thiz.scope.expressionModel.parse(thiz.scope,val,false,run,error);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
|
||||
|
||||
//this.types.ECIType.EXPRESSION_EDITOR
|
||||
/*
|
||||
fields.push(this.utils.createCI('initial',this.types.ECIType.EXPRESSION,this.initial,{
|
||||
group:'General',
|
||||
title:'Initial',
|
||||
dst:'initial',
|
||||
widget:defaultArgs,
|
||||
delegate:{
|
||||
runExpression:function(val,run,error){
|
||||
if(thiz.group=='processVariables'){
|
||||
var _val = thiz.scope.getVariable("value");
|
||||
var extra = "";
|
||||
if(_val) {
|
||||
_val = _val.value;
|
||||
if(!thiz.isNumber(_val)){
|
||||
_val = ''+_val;
|
||||
_val = "'" + _val + "'";
|
||||
}
|
||||
extra = "var value = " + _val +";\n";
|
||||
}
|
||||
}
|
||||
return thiz.scope.expressionModel.parse(thiz.scope,extra + val,false,run,error);
|
||||
}
|
||||
}
|
||||
}));
|
||||
*/
|
||||
return fields;
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,260 @@
|
||||
/** @module xblox/model/variables/VariableAssignmentBlock **/
|
||||
define([
|
||||
'dcl/dcl',
|
||||
"xblox/model/Block",
|
||||
"xide/utils",
|
||||
"xide/types",
|
||||
'dstore/legacy/DstoreAdapter',
|
||||
"xide/factory",
|
||||
'xdojo/has'
|
||||
], function(dcl,Block,utils,types,DstoreAdapter,factory,has){
|
||||
|
||||
var isServer = has('host-node');
|
||||
var BLOCK_INSERT_ROOT_COMMAND = 'Step/Insert';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @class module:xblox/model/variables/VariableAssignmentBlock
|
||||
* @extends xblox/model/Block
|
||||
*/
|
||||
var Module = dcl(Block,{
|
||||
declaredClass: "xblox.model.variables.VariableAssignmentBlock",
|
||||
|
||||
//variable: (String)
|
||||
// variable title
|
||||
variable:null,
|
||||
|
||||
//value: (String)
|
||||
// Expression to be asigned
|
||||
value:null,
|
||||
name:'Set Variable',
|
||||
icon:'',
|
||||
hasInlineEdits:true,
|
||||
flags:0x00000004,
|
||||
toText:function(){
|
||||
var _variable = this.scope.getVariableById(this.variable);
|
||||
var _text = _variable ? _variable.name : '';
|
||||
if(this.variable && this.variable.indexOf('://')!==-1) {
|
||||
_text = '<span class="text-info">' +this.scope.toFriendlyName(this, this.variable)+'</span>';
|
||||
}
|
||||
return this.getBlockIcon('C') + this.name + ' ' + _text + "<span class='text-muted small'> to <kbd class='text-warning'>" + this.makeEditable("value",'bottom','text','Enter the string to send','inline') + "</kbd></span>";
|
||||
},
|
||||
_getPreviousResult: function () {
|
||||
var parent = null;
|
||||
var prev = this.getPreviousBlock();
|
||||
if(!prev || !prev._lastResult || !prev.enabled){
|
||||
parent = this.getParent();
|
||||
}else{
|
||||
parent = prev;
|
||||
}
|
||||
|
||||
if (parent && parent._lastResult != null) {
|
||||
if (this.isArray(parent._lastResult)) {
|
||||
return parent._lastResult;
|
||||
} else {
|
||||
return parent._lastResult;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
/***
|
||||
* Makes the assignation
|
||||
* @param scope
|
||||
*/
|
||||
|
||||
solve:function(scope,settings) {
|
||||
var value = this.value;
|
||||
var changed = false;
|
||||
if(!value){
|
||||
var _value = this.getArgs();
|
||||
if(_value.length>0){
|
||||
value = _value[0];
|
||||
}
|
||||
}
|
||||
if (this.variable && value!==null){
|
||||
|
||||
this.onRun(this,settings);
|
||||
//var _variable = scope.getVariable(this.variable).value = scope.parseExpression(this.value);
|
||||
var _variable = this.variable.indexOf('://')!==-1 ? this.scope.resolveBlock(this.variable) : scope.getVariableById(this.variable);
|
||||
//console.log('assign variable',settings);
|
||||
var _value = this._getArg(value);
|
||||
|
||||
var _args = this.getArgs(settings) || [];
|
||||
//console.log('run with args ' , _args);
|
||||
|
||||
if(!_variable){
|
||||
//console.error(' no such variable : ' + this.variable);
|
||||
return [];
|
||||
}
|
||||
var _parsed = null;
|
||||
if(this.isScript(_value)){
|
||||
var override = this.override || {};
|
||||
_parsed = scope.parseExpression(value,null,null,null,null,null,_args || override.args);
|
||||
//_parsed = scope.parseExpression(_value);
|
||||
_parsed = this.replaceAll("'",'',_parsed);
|
||||
//_variable.value = scope.parseExpression(_value);
|
||||
//_variable.value = this.replaceAll("'",'',_variable.value);
|
||||
|
||||
if(_variable.value!==_parsed){
|
||||
changed = true;
|
||||
}
|
||||
|
||||
}else{
|
||||
|
||||
if(_args && _args.length==1 && value==null){
|
||||
_value = _args[0];
|
||||
}
|
||||
|
||||
if(_variable.value!==_value){
|
||||
changed = true;
|
||||
}
|
||||
|
||||
_variable.value = _value;
|
||||
_parsed = _value;
|
||||
}
|
||||
|
||||
|
||||
_variable.set('value',_parsed);
|
||||
|
||||
var publish = false;
|
||||
|
||||
|
||||
var context = this.getContext();
|
||||
if(context) {
|
||||
var device = context.device;
|
||||
if(device && device.info && isServer && device.info.serverSide) {
|
||||
if (this.flags & types.VARIABLE_FLAGS.PUBLISH_IF_SERVER) {
|
||||
publish = true;
|
||||
}else{
|
||||
publish=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(this.flags & types.VARIABLE_FLAGS.PUBLISH && changed){
|
||||
publish = true;
|
||||
}
|
||||
|
||||
changed && factory.publish(types.EVENTS.ON_DRIVER_VARIABLE_CHANGED,{
|
||||
item:_variable,
|
||||
scope:this.scope,
|
||||
save:false,
|
||||
block:this,
|
||||
name:_variable.name,
|
||||
value:_value,
|
||||
publish:publish,
|
||||
result:_parsed
|
||||
});
|
||||
this.onSuccess(this,settings);
|
||||
return [];
|
||||
}
|
||||
},
|
||||
canAdd:function(){
|
||||
return null;
|
||||
},
|
||||
getFields:function(){
|
||||
|
||||
var fields = this.inherited(arguments) || this.getDefaultFields(false);
|
||||
var thiz=this;
|
||||
|
||||
/*
|
||||
fields.push(this.utils.createCI('Variable',3,this.variable,{
|
||||
group:'General',
|
||||
dst:'variable',
|
||||
widget:{
|
||||
store:new DstoreAdapter(this.scope.blockStore),
|
||||
query:{
|
||||
group:'basicVariables'
|
||||
}
|
||||
}
|
||||
}));
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
fields.push(this.utils.createCI('value',29,this.value,{
|
||||
group:'General',
|
||||
title:'Value',
|
||||
dst:'value',
|
||||
widget:{
|
||||
allowACECache:true,
|
||||
showBrowser:false,
|
||||
showSaveButton:true,
|
||||
editorOptions:{
|
||||
showGutter:false,
|
||||
autoSelect: false,
|
||||
autoFocus: false,
|
||||
hasConsole:false,
|
||||
hasItemActions:function(){
|
||||
return false
|
||||
}
|
||||
},
|
||||
item:this
|
||||
},
|
||||
delegate:{
|
||||
runExpression:function(val,run,error){
|
||||
return thiz.scope.expressionModel.parse(thiz.scope,val,false,run,error);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
|
||||
|
||||
fields.push(utils.createCI('value','xcf.widgets.CommandPicker',this.variable,{
|
||||
group:'Variable',
|
||||
title:'Variable',
|
||||
dst:'variable',
|
||||
//options:this.scope.getVariablesAsOptions(),
|
||||
block:this,
|
||||
pickerType:'variable',
|
||||
value:this.variable,
|
||||
widget:{
|
||||
store:this.scope.blockStore,
|
||||
labelField:'name',
|
||||
valueField:'id',
|
||||
value:this.variable,
|
||||
query:[
|
||||
{
|
||||
group:'basicVariables'
|
||||
},
|
||||
{
|
||||
group:'processVariables'
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
}));
|
||||
|
||||
fields.push(this.utils.createCI('flags',5,this.flags,{
|
||||
group:'Variable',
|
||||
title:'Flags',
|
||||
dst:'flags',
|
||||
data:[
|
||||
{
|
||||
value: 0x00000002,
|
||||
label: 'Publish to network',
|
||||
title:"Publish to network in order to make a network variable"
|
||||
},
|
||||
{
|
||||
value: 0x00000004,//2048
|
||||
label: 'Publish if server',
|
||||
title: 'Publish only on network if this is running server side'
|
||||
}
|
||||
],
|
||||
widget:{
|
||||
hex:true
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
return fields;
|
||||
}
|
||||
});
|
||||
|
||||
return Module;
|
||||
|
||||
});
|
||||
@ -0,0 +1,56 @@
|
||||
/** @module xblox/model/variables/VariableSwitch **/
|
||||
define([
|
||||
'dcl/dcl',
|
||||
"xblox/model/logic/SwitchBlock",
|
||||
'xide/types',
|
||||
"xblox/model/logic/CaseBlock",
|
||||
"xblox/model/logic/DefaultBlock",
|
||||
"dojo/Deferred"
|
||||
], function(dcl,SwitchBlock,types,CaseBlock,DefaultBlock,Deferred){
|
||||
/**
|
||||
*
|
||||
* The switch command model. These kind of commands takes a existing variable and applies some comparison.
|
||||
* Depending on the comparison results, the code into each case block is executed or not.
|
||||
* @class module:xblox/model/variables/VariableSwitch
|
||||
* @extends module:xblox/model/Block
|
||||
*/
|
||||
return dcl(SwitchBlock,{
|
||||
declaredClass:"xblox.model.variables.VariableSwitch",
|
||||
name:'Switch on Variable',
|
||||
icon:'',
|
||||
variable:"PowerState",
|
||||
toText:function(){
|
||||
var _variable = this.scope.getVariableById(this.variable);
|
||||
var _text = _variable ? _variable.name : '';
|
||||
return this.getBlockIcon('H') + this.name + ' ' + _text;
|
||||
},
|
||||
// standard call for editing
|
||||
getFields:function(){
|
||||
//options:this.scope.getVariablesAsOptions(),
|
||||
var fields = this.getDefaultFields(false,false);
|
||||
fields = fields.concat([
|
||||
this.utils.createCI('Variable',3,this.variable,
|
||||
{
|
||||
group:'General',
|
||||
widget:{
|
||||
store:this.scope.blockStore,
|
||||
labelField:'name',
|
||||
valueField:'id',
|
||||
query:[
|
||||
{
|
||||
group:'basicVariables'
|
||||
},
|
||||
{
|
||||
group:'processVariables'
|
||||
}
|
||||
]
|
||||
|
||||
},
|
||||
dst:'variable'
|
||||
}
|
||||
)
|
||||
]);
|
||||
return fields;
|
||||
}
|
||||
});
|
||||
});
|
||||
29
packages/xblox/ref-control-freak/xblox/package.json
Normal file
29
packages/xblox/ref-control-freak/xblox/package.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "xblox",
|
||||
"version": "1.0.0-dev",
|
||||
"dependencies": {
|
||||
},
|
||||
"devDependencies": {
|
||||
"intern": "2.2",
|
||||
"intern-geezer": "latest",
|
||||
"grunt": "~0.4.5",
|
||||
"grunt-contrib-jshint": "~0.6.3",
|
||||
"grunt-contrib-clean": "~0.6.0",
|
||||
"grunt-contrib-less": "~0.8.3",
|
||||
"grunt-contrib-uglify": "~0.2.2",
|
||||
"jsdoc-amddcl": "git://github.com/mc007/jsdoc-amddcl#master"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"type": "BSD",
|
||||
"url": "https://github.com/mc007/xgrid/blob/master/LICENSE"
|
||||
}
|
||||
],
|
||||
"bugs": "https://github.com/mc007/xgrid/issues",
|
||||
"dojoBuild": "layer.profile.js",
|
||||
"private": true,
|
||||
"directories": {
|
||||
"doc": "./doc",
|
||||
"lib": "."
|
||||
}
|
||||
}
|
||||
168
packages/xblox/ref-control-freak/xblox/resources-debug.json
Normal file
168
packages/xblox/ref-control-freak/xblox/resources-debug.json
Normal file
@ -0,0 +1,168 @@
|
||||
|
||||
{
|
||||
"class":"cmx.types.Resources",
|
||||
"includes":[
|
||||
|
||||
],
|
||||
"items":[
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"JS-HEADER-INCLUDE",
|
||||
"url":"%XASWEB%/lib/external/moment-with-langs.js",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"%XASWEB%/xfileTheme/claro/document.css",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"%XASWEB%/css/elusive-icons/elusive-webfont.css",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"%XASWEB%/css/elusive-icons/elusive-webfont-ie7.css",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"%XASWEB%/xfileTheme/claro/claro.css",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"%XASWEB%/css/Widgets.css",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"%XASWEB%/css/xasCommons.css",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"%XASWEB%/css/xasdijitOverride.css",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"%XASWEB%/css/xfile/main.css",
|
||||
"enabled":true,
|
||||
"preventCache":true
|
||||
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"%XASWEB%/xfile/ext/cm/lib/codemirror.css",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"%XASWEB%/css/xbox/xboxAdmin.css",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"%XASWEB%/lib/dijit/icons/editorIcons.css",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"%XASWEB%/lib/dgrid/css/dgrid.css",
|
||||
"enabled":false
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"%XASWEB%/lib/dgrid/css/columnset.css",
|
||||
"enabled":false
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"%XASWEB%/lib/cbtree/icons/networkIcons.css",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"%XASWEB%/lib/dojox/layout/resources/ToggleSplitter.css",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"JS-HEADER-INCLUDE",
|
||||
"url":"%XASWEB%/xfile/ext/cm/lib/codemirror.js",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"JS-HEADER-INCLUDE",
|
||||
"url":"%XASWEB%/xfile/ext/cm/addon/mode/loadmode.js",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"%XASWEB%/xfile/ext/cm/addon/dialog/dialog.css",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"JS-HEADER-INCLUDE",
|
||||
"url":"%XASWEB%/xfile/ext/cm/addon/dialog/dialog.js",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"JS-HEADER-INCLUDE",
|
||||
"url":"%XASWEB%/xfile/ext/cm/addon/search/searchcursor.js",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"JS-HEADER-INCLUDE",
|
||||
"url":"%XASWEB%/xfile/ext/cm/addon/search/search.js",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"JS-HEADER-INCLUDE",
|
||||
"url":"%XASWEB%/lib/external/ckeditorfull/ckeditor.js",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"HTML",
|
||||
"url":"%XASWEB%/lib/xide/templates/body.html",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"JS-HEADER-SCRIPT-TAG",
|
||||
"url":"%XASWEB%/lib/xide/Header.js",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"http://code.jquery.com/ui/1.10.3/themes/%JQUERY_THEME%/jquery-ui.css",
|
||||
"enabled":false
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
{
|
||||
"class":"cmx.types.Resources",
|
||||
"distDir":"%XASWEB%/%XLIB%/xbox",
|
||||
"includes":[
|
||||
{
|
||||
"class":"cmx.types.ResourceInclude",
|
||||
"path":"%XLIB%/resourceConfigs/commons-release.json"
|
||||
}
|
||||
],
|
||||
"items":[
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"%XASWEB%/xbox/xbox/resources/app.css"
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"%XASWEB%/%XLIB%/dojox/widget/Wizard/Wizard.css"
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"CSS",
|
||||
"url":"%XASWEB%/xfile/ext/cm/addon/dialog/dialog.css",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"JS-HEADER-INCLUDE",
|
||||
"url":"%XASWEB%/xfile/ext/cm/addon/dialog/dialog.js",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"JS-HEADER-INCLUDE",
|
||||
"url":"%XASWEB%/xfile/ext/cm/addon/search/searchcursor.js",
|
||||
"enabled":true
|
||||
},
|
||||
{
|
||||
"class":"cmx.types.Resource",
|
||||
"type":"JS-HEADER-INCLUDE",
|
||||
"url":"%XASWEB%/xfile/ext/cm/addon/search/search.js",
|
||||
"enabled":true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
31
packages/xblox/ref-control-freak/xblox/run.js
Normal file
31
packages/xblox/ref-control-freak/xblox/run.js
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* This file is used to reconfigure parts of the loader at runtime for this application. We’ve put this extra
|
||||
* configuration in a separate file, instead of adding it directly to index.html, because it contains options that
|
||||
* can be shared if the application is run on both the client and the server.
|
||||
*
|
||||
* If you aren’t planning on running your app on both the client and the server, you could easily move this
|
||||
* configuration into index.html (as a dojoConfig object) if it makes your life easier.
|
||||
*/
|
||||
require({
|
||||
// The base path for all packages and modules. If you don't provide this, baseUrl defaults to the directory
|
||||
// that contains dojo.js. Since all packages are in the root, we just leave it blank. (If you change this, you
|
||||
// will also need to update app.profile.js).
|
||||
/*baseUrl: '../',*/
|
||||
// A list of packages to register. Strictly speaking, you do not need to register any packages,
|
||||
// but you can't require "app" and get app/main.js if you do not register the "app" package (the loader will look
|
||||
// for a module at <baseUrl>/app.js instead). Unregistered packages also cannot use the packageMap feature, which
|
||||
// might be important to you if you need to relocate dependencies. TL;DR, register all your packages all the time:
|
||||
// it will make your life easier.
|
||||
packages: [
|
||||
// If you are registering a package that has an identical name and location, you can just pass a string
|
||||
// instead, and it will configure it using that string for both the "name" and "location" properties. Handy!
|
||||
'xblox'
|
||||
],
|
||||
|
||||
// This is a hack. In order to allow app/main and app/run to be built together into a single file, a cache key needs
|
||||
// to exist here in order to force the loader to actually process the other modules in the file. Without this hack,
|
||||
// the loader will think that code for app/main has not been loaded yet and will try to fetch it again, resulting in
|
||||
// a needless extra HTTP request.
|
||||
cache: {}
|
||||
// Require 'app'. This loads the main application file, app/main.js.
|
||||
}, ['xblox']);
|
||||
20
packages/xblox/ref-control-freak/xblox/test/intern/addCss.js
Normal file
20
packages/xblox/ref-control-freak/xblox/test/intern/addCss.js
Normal file
@ -0,0 +1,20 @@
|
||||
define([ 'require' ], function (require) {
|
||||
return {
|
||||
// Expose this module as an AMD plugin which will wait until the
|
||||
// link element has loaded the stylesheet.
|
||||
// (This uses least-common-denominator logic from xstyle/core/load-css.)
|
||||
load: function (id, parentRequire, loaded) {
|
||||
var link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.href = require.toUrl('../../css/dgrid.css');
|
||||
document.getElementsByTagName('head')[0].appendChild(link);
|
||||
|
||||
var interval = setInterval(function () {
|
||||
if (link.style) {
|
||||
clearInterval(interval);
|
||||
loaded();
|
||||
}
|
||||
}, 15);
|
||||
}
|
||||
};
|
||||
});
|
||||
@ -0,0 +1,3 @@
|
||||
define([
|
||||
'intern/node_modules/dojo/has!host-browser?./core/createDestroy'
|
||||
], function () {});
|
||||
@ -0,0 +1,48 @@
|
||||
define([
|
||||
'intern!tdd',
|
||||
'intern/chai!assert',
|
||||
'dojo/query',
|
||||
'dgrid/OnDemandList',
|
||||
'dgrid/test/data/createSyncStore',
|
||||
'dgrid/test/data/genericData'
|
||||
], function (test, assert, query, OnDemandList, createSyncStore, genericData) {
|
||||
test.suite('OnDemandList with zero rowHeight', function () {
|
||||
var list;
|
||||
var store = createSyncStore({ data: genericData });
|
||||
|
||||
test.beforeEach(function () {
|
||||
list = new OnDemandList({
|
||||
collection: store,
|
||||
renderRow: function () {
|
||||
return document.createElement('div');
|
||||
}
|
||||
});
|
||||
document.body.appendChild(list.domNode);
|
||||
list.startup();
|
||||
});
|
||||
|
||||
test.afterEach(function () {
|
||||
list.destroy();
|
||||
});
|
||||
|
||||
test.test('_processScroll should bail out if rowHeight is 0', function () {
|
||||
// Bailing out with rowHeight === 0 is important because otherwise
|
||||
// _processScroll has the potential to loop infinitely.
|
||||
|
||||
// _processScroll will call _trackError if it doesn't bail out and
|
||||
// thinks it should render more items, so replace it to fail the test
|
||||
list._trackError = function () {
|
||||
throw new assert.AssertionError({
|
||||
message: '_processScroll with 0 rowHeight should not result in any query'
|
||||
});
|
||||
};
|
||||
|
||||
list._processScroll();
|
||||
});
|
||||
|
||||
test.test('refresh with zero rowHeight should only render minRowsPerPage rows', function () {
|
||||
// This tests GitHub issue #965.
|
||||
assert.strictEqual(query('.dgrid-row', list.contentNode).length, list.minRowsPerPage);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,302 @@
|
||||
define([
|
||||
'intern!tdd',
|
||||
'intern/chai!assert',
|
||||
'dojo/_base/lang',
|
||||
'dojo/_base/declare',
|
||||
'dojo/aspect',
|
||||
'dojo/Deferred',
|
||||
'dgrid/OnDemandList',
|
||||
// column.set can't be tested independently from a Grid,
|
||||
// so we are testing through OnDemandGrid for now.
|
||||
'dgrid/OnDemandGrid',
|
||||
'dgrid/ColumnSet',
|
||||
'dgrid/test/data/createSyncStore',
|
||||
'dgrid/test/data/genericData',
|
||||
'dojo/domReady!'
|
||||
], function (test, assert, lang, declare, aspect, Deferred,
|
||||
OnDemandList, OnDemandGrid, ColumnSet, createSyncStore, genericData) {
|
||||
|
||||
// Helper method used to set column set() methods for various grid compositions
|
||||
function testSetMethod(grid, dfd) {
|
||||
var store = createSyncStore({ data: genericData });
|
||||
grid.set('collection', store);
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
|
||||
var changes = [
|
||||
{
|
||||
objectId: 0,
|
||||
field: 'col1',
|
||||
newValue: 'sleepy',
|
||||
expectedSavedValue: 'SLEEPY'
|
||||
},
|
||||
{
|
||||
objectId: 1,
|
||||
field: 'col3',
|
||||
newValue: 'dopey',
|
||||
expectedSavedValue: 'DOPEY'
|
||||
},
|
||||
{
|
||||
objectId: 2,
|
||||
field: 'col4',
|
||||
newValue: 'rutherford',
|
||||
expectedSavedValue: 'RUTHERFORD'
|
||||
}
|
||||
],
|
||||
len = changes.length,
|
||||
i,
|
||||
change;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
change = changes[i];
|
||||
grid.updateDirty(change.objectId, change.field, change.newValue);
|
||||
}
|
||||
|
||||
grid.save().then(
|
||||
dfd.callback(function () {
|
||||
for (var i = 0, change; i < changes.length; i++) {
|
||||
change = changes[i];
|
||||
assert.strictEqual(store.getSync(change.objectId)[change.field],
|
||||
change.expectedSavedValue);
|
||||
}
|
||||
}),
|
||||
lang.hitch(dfd, 'reject')
|
||||
);
|
||||
|
||||
return dfd;
|
||||
}
|
||||
|
||||
// the set() method to use for column.set() tests
|
||||
function sampleSetMethod(item) {
|
||||
return item[this.field].toUpperCase();
|
||||
}
|
||||
|
||||
test.suite('_StoreMixin', function () {
|
||||
var grid; // Reused for each test and common afterEach logic
|
||||
|
||||
test.afterEach(function () {
|
||||
grid.destroy();
|
||||
});
|
||||
|
||||
test.suite('_StoreMixin#_setCollection', function () {
|
||||
var store;
|
||||
|
||||
test.beforeEach(function () {
|
||||
store = createSyncStore({ data: genericData });
|
||||
grid = new OnDemandList({
|
||||
collection: store
|
||||
});
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
});
|
||||
|
||||
test.test('null', function () {
|
||||
assert.isDefined(grid._renderedCollection,
|
||||
'grid._renderedCollection should be defined');
|
||||
assert.notStrictEqual(grid.contentNode.children.length, 0,
|
||||
'grid.contentNode should contain children when refreshing with a store');
|
||||
|
||||
grid.set('collection', null);
|
||||
assert.isNull(grid._renderedCollection,
|
||||
'grid._renderedCollection should be null after setting collection to null');
|
||||
assert.strictEqual(grid.contentNode.children.length, 1,
|
||||
'grid.contentNode should contain one child when refreshing with a null collection');
|
||||
assert.strictEqual(grid.contentNode.children[0], grid.noDataNode,
|
||||
'grid.contentNode should contain the noDataNode');
|
||||
|
||||
grid.set('collection', store);
|
||||
assert.isNotNull(grid._renderedCollection,
|
||||
'grid._renderedCollection should not be null after setting collection to store again');
|
||||
assert.notStrictEqual(grid.contentNode.children.length, 0,
|
||||
'grid.contentNode should contain children when refreshing with a store');
|
||||
});
|
||||
|
||||
test.test('dirty data preservation/cleanup', function () {
|
||||
grid.updateDirty(0, 'col1', 'modified');
|
||||
assert.isDefined(grid.dirty[0], 'Dirty hash should contain entry for item 0 after updateDirty');
|
||||
grid.set('sort', 'col3');
|
||||
assert.isDefined(grid.dirty[0], 'Dirty hash should still contain entry for item 0 after sort');
|
||||
grid.set('collection', store.filter({ col2: false }));
|
||||
assert.isDefined(grid.dirty[0], 'Dirty hash should still contain entry for item 0 after filter');
|
||||
grid.set('collection', createSyncStore({ data: genericData }));
|
||||
assert.isUndefined(grid.dirty[0],
|
||||
'Dirty hash should be cleared after setting collection based on different store');
|
||||
});
|
||||
});
|
||||
|
||||
test.test('_StoreMixin#_onNotification', function () {
|
||||
var store = createSyncStore({ data: genericData }),
|
||||
notificationCount = 0,
|
||||
lastNotificationEvent = null;
|
||||
|
||||
grid = new OnDemandList({
|
||||
collection: store,
|
||||
_onNotification: function (rows, event) {
|
||||
notificationCount++;
|
||||
lastNotificationEvent = event;
|
||||
}
|
||||
});
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
|
||||
var item = store.getSync(1);
|
||||
store.removeSync(item.id);
|
||||
assert.equal(notificationCount, 1);
|
||||
assert.isNotNull(lastNotificationEvent);
|
||||
assert.equal(lastNotificationEvent.type, 'delete');
|
||||
assert.equal(lastNotificationEvent.id, item.id);
|
||||
|
||||
lastNotificationEvent = null;
|
||||
store.addSync(item);
|
||||
assert.equal(notificationCount, 2);
|
||||
assert.isNotNull(lastNotificationEvent);
|
||||
assert.equal(lastNotificationEvent.type, 'add');
|
||||
assert.equal(lastNotificationEvent.target, item);
|
||||
|
||||
item.col1 = 'changed';
|
||||
lastNotificationEvent = null;
|
||||
store.putSync(item);
|
||||
assert.equal(notificationCount, 3);
|
||||
assert.isNotNull(lastNotificationEvent);
|
||||
assert.equal(lastNotificationEvent.type, 'update');
|
||||
assert.equal(lastNotificationEvent.target, item);
|
||||
});
|
||||
|
||||
test.suite('_StoreMixin#_trackError', function () {
|
||||
var emittedErrorCount,
|
||||
lastEmittedError,
|
||||
expectedValue;
|
||||
|
||||
function expectedSuccess(actualValue) {
|
||||
assert.strictEqual(actualValue, expectedValue,
|
||||
'Resolved promise should yield expected value');
|
||||
assert.strictEqual(emittedErrorCount, 0,
|
||||
'dgrid-error event should not have fired');
|
||||
}
|
||||
function expectedError(error) {
|
||||
assert.strictEqual(error.message, expectedValue,
|
||||
'An error with the expected message should be thrown');
|
||||
assert.strictEqual(emittedErrorCount, 1,
|
||||
'A dgrid-error event should have fired');
|
||||
assert.strictEqual(lastEmittedError, error,
|
||||
'The error should be accessible from the dgrid-error event');
|
||||
}
|
||||
function unexpectedSuccess() {
|
||||
throw new Error('Unexpected resolution');
|
||||
}
|
||||
|
||||
test.beforeEach(function () {
|
||||
grid = new OnDemandList();
|
||||
|
||||
grid.on('dgrid-error', function (event) {
|
||||
emittedErrorCount++;
|
||||
lastEmittedError = event.error;
|
||||
});
|
||||
|
||||
emittedErrorCount = 0;
|
||||
lastEmittedError = null;
|
||||
});
|
||||
|
||||
test.test('_StoreMixin#_trackError - sync value', function () {
|
||||
expectedValue = 'expected';
|
||||
return grid._trackError(function () {
|
||||
return expectedValue;
|
||||
}).then(expectedSuccess);
|
||||
});
|
||||
|
||||
test.test('_StoreMixin#_trackError - async value', function () {
|
||||
expectedValue = 'expected-async';
|
||||
return grid._trackError(function () {
|
||||
var dfd = new Deferred();
|
||||
setTimeout(function () {
|
||||
dfd.resolve(expectedValue);
|
||||
}, 100);
|
||||
return dfd.promise;
|
||||
}).then(expectedSuccess);
|
||||
});
|
||||
|
||||
test.test('_StoreMixin#_trackError - sync error', function () {
|
||||
expectedValue = 'expected-error';
|
||||
return grid._trackError(function () {
|
||||
throw new Error(expectedValue);
|
||||
}).then(unexpectedSuccess, expectedError);
|
||||
});
|
||||
|
||||
test.test('_StoreMixin#_trackError - async error', function () {
|
||||
// async error
|
||||
expectedValue = 'expected-async-error';
|
||||
return grid._trackError(function () {
|
||||
var dfd = new Deferred();
|
||||
setTimeout(function () {
|
||||
dfd.reject(new Error(expectedValue));
|
||||
}, 100);
|
||||
return dfd.promise;
|
||||
}).then(unexpectedSuccess, expectedError);
|
||||
});
|
||||
});
|
||||
|
||||
test.suite('_StoreMixin#save / column.set tests', function () {
|
||||
test.test('column.set in subRows', function () {
|
||||
grid = new OnDemandGrid({
|
||||
subRows: [
|
||||
[
|
||||
{ label: 'Column 1', field: 'col1', set: sampleSetMethod },
|
||||
{ label: 'Column 2', field: 'col2', sortable: false },
|
||||
{ label: 'Column 1', field: 'col1', rowSpan: 2 },
|
||||
{ label: 'Column 4', field: 'col4', set: sampleSetMethod }
|
||||
],
|
||||
[
|
||||
{ label: 'Column 3', field: 'col3', colSpan: 2, set: sampleSetMethod },
|
||||
{ label: 'Column 5', field: 'col5' }
|
||||
]
|
||||
]
|
||||
});
|
||||
testSetMethod(grid, this.async());
|
||||
});
|
||||
|
||||
test.test('column.set in columnSets', function () {
|
||||
grid = new (declare([OnDemandGrid, ColumnSet]))({
|
||||
columnSets: [
|
||||
[
|
||||
[
|
||||
{ label: 'Column 1', field: 'col1', set: sampleSetMethod },
|
||||
{ label: 'Column 2', field: 'col2', sortable: false }
|
||||
],
|
||||
[
|
||||
{label: 'Column 3', field: 'col3', colSpan: 2, set: sampleSetMethod }
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
{ label: 'Column 1', field: 'col1', rowSpan: 2 },
|
||||
{ label: 'Column 4', field: 'col4', set: sampleSetMethod }
|
||||
],
|
||||
[
|
||||
{ label: 'Column 5', field: 'col5' }
|
||||
]
|
||||
]
|
||||
]
|
||||
});
|
||||
testSetMethod(grid, this.async());
|
||||
});
|
||||
});
|
||||
|
||||
test.suite('Effect of set-before-startup on refresh calls', function(){
|
||||
test.test('set(\'collection\') before startup should not cause superfluous refresh', function () {
|
||||
var numCalls = 0;
|
||||
|
||||
grid = new OnDemandList();
|
||||
|
||||
aspect.before(grid, 'refresh', function () {
|
||||
numCalls++;
|
||||
});
|
||||
|
||||
grid.set('collection', createSyncStore(genericData));
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
|
||||
assert.strictEqual(numCalls, 1, 'refresh should only have been called once');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,335 @@
|
||||
define([
|
||||
'intern!tdd',
|
||||
'intern/chai!assert',
|
||||
'dojo/_base/declare',
|
||||
'dojo/dom-style',
|
||||
'dojo/dom-construct',
|
||||
'dojo/query',
|
||||
'dgrid/Grid',
|
||||
'dgrid/ColumnSet',
|
||||
'dgrid/extensions/ColumnHider',
|
||||
'dgrid/extensions/ColumnResizer',
|
||||
'dgrid/util/misc'
|
||||
], function (test, assert, declare, domStyle, domConstruct, query,
|
||||
Grid, ColumnSet, ColumnHider, ColumnResizer, miscUtil) {
|
||||
|
||||
test.suite('addCssRule', function () {
|
||||
var testDiv;
|
||||
var grid;
|
||||
|
||||
// Setup / teardown
|
||||
test.before(function () {
|
||||
testDiv = domConstruct.create('div', null, document.body);
|
||||
});
|
||||
|
||||
test.after(function () {
|
||||
domConstruct.destroy(testDiv);
|
||||
});
|
||||
|
||||
test.afterEach(function () {
|
||||
if (grid) {
|
||||
grid.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
// Tests
|
||||
test.test('addCssRule + remove', function () {
|
||||
testDiv.className = 'foo';
|
||||
// cache original style and update .foo
|
||||
var origStyle = domStyle.getComputedStyle(testDiv).fontSize,
|
||||
rule = miscUtil.addCssRule('.foo', 'font-size: 8px;');
|
||||
// check updated font size was applied
|
||||
assert.strictEqual('8px', domStyle.getComputedStyle(testDiv).fontSize,
|
||||
'Node with matching class has expected font-size');
|
||||
// remove the rule & make sure the computed style is good again
|
||||
rule.remove();
|
||||
assert.strictEqual(origStyle, domStyle.getComputedStyle(testDiv).fontSize,
|
||||
'Node with matching class no longer has font-size from removed rule');
|
||||
testDiv.className = '';
|
||||
});
|
||||
|
||||
test.test('addCssRule get/set/remove', function () {
|
||||
testDiv.className = 'bar';
|
||||
// cache original style and update .foo
|
||||
var origStyle = domStyle.getComputedStyle(testDiv).fontSize,
|
||||
rule = miscUtil.addCssRule('.bar', 'font-size: 8px;');
|
||||
// check updated font size was applied
|
||||
assert.strictEqual('8px', rule.get('fontSize'),
|
||||
'rule.get(\'fontSize\') reports expected value');
|
||||
// update the font size
|
||||
rule.set('fontSize', '9px');
|
||||
// verify that the size updated
|
||||
assert.strictEqual('9px', domStyle.getComputedStyle(testDiv).fontSize,
|
||||
'Node with matching class has expected font-size after set');
|
||||
// make sure rule.get works the same
|
||||
assert.strictEqual('9px', rule.get('fontSize'),
|
||||
'rule.get(\'fontSize\') reports expected value after set');
|
||||
// remove the rule & make sure it updates
|
||||
rule.remove();
|
||||
assert.strictEqual(origStyle, domStyle.getComputedStyle(testDiv).fontSize,
|
||||
'Node with matching class no longer has font-size from removed rule');
|
||||
testDiv.className = '';
|
||||
});
|
||||
|
||||
test.test('add/remove multiple rules in mixed order', function () {
|
||||
var origStyle = domStyle.getComputedStyle(testDiv).fontSize,
|
||||
rules = [],
|
||||
expected = { // hash containing test classes / values
|
||||
foo: '7px',
|
||||
bar: '8px',
|
||||
baz: '9px'
|
||||
},
|
||||
cls;
|
||||
|
||||
function check() {
|
||||
// Test that all expected styles hold
|
||||
var cls;
|
||||
for (cls in expected) {
|
||||
testDiv.className = cls;
|
||||
assert.strictEqual(expected[cls], domStyle.getComputedStyle(testDiv).fontSize,
|
||||
'Node with class ' + cls + ' has expected font-size');
|
||||
}
|
||||
testDiv.className = '';
|
||||
}
|
||||
|
||||
// Create rules and maintain references to returned objects
|
||||
for (cls in expected) {
|
||||
rules.push(miscUtil.addCssRule('.' + cls, 'font-size: ' + expected[cls] + ';'));
|
||||
}
|
||||
|
||||
// Do initial check, then remove rules one by one, out of order,
|
||||
// updating the hash and checking each time along the way
|
||||
check();
|
||||
|
||||
rules[2].remove();
|
||||
expected.baz = origStyle;
|
||||
check();
|
||||
|
||||
rules[0].remove();
|
||||
expected.foo = origStyle;
|
||||
check();
|
||||
|
||||
rules[1].remove();
|
||||
expected.bar = origStyle;
|
||||
check();
|
||||
});
|
||||
|
||||
test.test('addCssRule via dgrid APIs', function () {
|
||||
var values = ['7px', '8px'],
|
||||
origValues;
|
||||
|
||||
function createGrid(cleanAddedRules) {
|
||||
grid = new Grid({
|
||||
id: 'my.grid', // test escaping of CSS identifiers from methods
|
||||
columns: {
|
||||
name: 'Name',
|
||||
value: 'Value',
|
||||
comment: 'Comment' // unstyled buffer
|
||||
},
|
||||
cleanAddedRules: cleanAddedRules
|
||||
});
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
}
|
||||
|
||||
function addRules() {
|
||||
var rules = [];
|
||||
|
||||
rules.push(grid.addCssRule('.field-value', 'font-size: ' + values[0] + ';'));
|
||||
rules.push(grid.styleColumn('name', 'font-size: ' + values[1] + ';'));
|
||||
|
||||
return rules;
|
||||
}
|
||||
|
||||
function getStyles() {
|
||||
return [
|
||||
domStyle.getComputedStyle(query('.field-value', grid.domNode)[0]).fontSize,
|
||||
domStyle.getComputedStyle(query('.dgrid-column-name', grid.domNode)[0]).fontSize
|
||||
];
|
||||
}
|
||||
|
||||
function checkRules(expected) {
|
||||
var actual = getStyles(grid);
|
||||
assert.strictEqual(expected[0], actual[0],
|
||||
'Style modified via addCssRule has expected value');
|
||||
assert.strictEqual(expected[1], actual[1],
|
||||
'Style modified via styleColumn has expected value');
|
||||
}
|
||||
|
||||
// Create grid for the first time
|
||||
createGrid(true);
|
||||
// Collect original style values for later cleanup check
|
||||
origValues = getStyles();
|
||||
// Add rules and make sure they applied as expected
|
||||
addRules();
|
||||
checkRules(values);
|
||||
// Destroy the grid, which should remove the style rules
|
||||
grid.destroy();
|
||||
|
||||
// Create grid for the second time, with cleanAddedRules: false
|
||||
createGrid(false);
|
||||
// Before adding styles, make sure the ones from last time were removed
|
||||
checkRules(origValues);
|
||||
// Add rules and check again;
|
||||
// store the rules for tearDown since they won't be cleaned up
|
||||
this.rules = addRules();
|
||||
checkRules(values);
|
||||
// Destroy the grid, which should *not* remove the style rules
|
||||
grid.destroy();
|
||||
|
||||
// Create grid for the third time
|
||||
createGrid(true);
|
||||
// Check that styles from last time still exist
|
||||
checkRules(values);
|
||||
// Destroy the grid (which won't remove the styles from last time,
|
||||
// since no handles were added to this exact instance)
|
||||
grid.destroy();
|
||||
// Clean up rule litter from cleanAddedRules: false test
|
||||
var i;
|
||||
for (i in this.rules) {
|
||||
this.rules[i].remove();
|
||||
}
|
||||
});
|
||||
|
||||
test.test('Grid columns as array (numeric IDs)', function () {
|
||||
grid = new Grid({
|
||||
columns: [
|
||||
{ field: 'name' },
|
||||
{ field: 'value' }
|
||||
]
|
||||
});
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
|
||||
assert.doesNotThrow(function () {
|
||||
grid.styleColumn(0, 'font-size: 8px;');
|
||||
}, null, 'styleColumn with numeric column ID should not throw error');
|
||||
assert.strictEqual('8px', domStyle.getComputedStyle(query('.dgrid-cell')[0]).fontSize,
|
||||
'Column cell should have expected style');
|
||||
});
|
||||
});
|
||||
|
||||
test.suite('CSS escaping of column IDs via dgrid APIs', function () {
|
||||
|
||||
var grid;
|
||||
|
||||
test.suite('Grid columns and columnsets', function () {
|
||||
function makeTest(func, id) {
|
||||
return function () {
|
||||
assert.doesNotThrow(function () {
|
||||
grid[func](id, 'font-size: 8px;');
|
||||
}, null, func + ' should escape special characters and not throw error');
|
||||
assert.strictEqual('8px', domStyle.getComputedStyle(query('.dgrid-cell')[0]).fontSize,
|
||||
'Column cell should have expected style');
|
||||
};
|
||||
}
|
||||
|
||||
test.beforeEach(function () {
|
||||
grid = new (declare([Grid, ColumnSet]))({
|
||||
id: 'i:d',
|
||||
columnSets: [[[
|
||||
{ field: 'foo', id: 'col:umn' }
|
||||
]]]
|
||||
});
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
});
|
||||
|
||||
test.afterEach(function () {
|
||||
grid.destroy();
|
||||
});
|
||||
|
||||
test.test('styleColumn', makeTest('styleColumn', 'col:umn'));
|
||||
|
||||
// Currently ColumnSet IDs can't be customized so that isn't really an issue,
|
||||
// but this still tests escaping the grid ID
|
||||
test.test('styleColumnSet', makeTest('styleColumnSet', '0'));
|
||||
});
|
||||
|
||||
test.suite('ColumnHider', function () {
|
||||
var ColumnHiderGrid = declare([Grid, ColumnHider]);
|
||||
|
||||
test.afterEach(function () {
|
||||
grid.destroy();
|
||||
});
|
||||
|
||||
test.test('Hiding column after construction', function () {
|
||||
assert.doesNotThrow(function () {
|
||||
grid = new ColumnHiderGrid({
|
||||
id: 'i:d',
|
||||
columns: [
|
||||
{ field: 'foo', id: 'col:umn' }
|
||||
]
|
||||
});
|
||||
}, null, 'ColumnHider should not throw error during construction');
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
|
||||
assert.doesNotThrow(function () {
|
||||
grid._hideColumn('col:umn');
|
||||
}, null, '_hideColumn should escape special characters and not throw error');
|
||||
assert.strictEqual(query('.dgrid-cell')[0].offsetHeight, 0,
|
||||
'Column should be hidden');
|
||||
});
|
||||
|
||||
test.test('Hiding column during construction', function () {
|
||||
assert.doesNotThrow(function () {
|
||||
grid = new ColumnHiderGrid({
|
||||
id: 'i:d',
|
||||
columns: [
|
||||
{ field: 'foo', id: 'col:umn', hidden: true }
|
||||
]
|
||||
});
|
||||
}, null, 'ColumnHider should not throw error during construction');
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
assert.strictEqual(query('.dgrid-cell')[0].offsetHeight, 0,
|
||||
'Column should be hidden');
|
||||
});
|
||||
});
|
||||
|
||||
test.suite('ColumnResizer', function () {
|
||||
var ColumnResizerGrid = declare([Grid, ColumnResizer]);
|
||||
|
||||
test.afterEach(function () {
|
||||
grid.destroy();
|
||||
});
|
||||
|
||||
test.test('Resizing column after construction', function () {
|
||||
assert.doesNotThrow(function () {
|
||||
grid = new ColumnResizerGrid({
|
||||
id: 'i:d',
|
||||
columns: [
|
||||
{ field: 'foo', id: 'col:umn' },
|
||||
{ field: 'bar' }
|
||||
]
|
||||
});
|
||||
}, null, 'ColumnResizer should not throw error during construction');
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
|
||||
assert.doesNotThrow(function () {
|
||||
grid.resizeColumnWidth('col:umn', 100);
|
||||
}, null, 'resizeColumnWidth should escape special characters and not throw error');
|
||||
assert.strictEqual(query('.dgrid-cell')[0].offsetWidth, 100,
|
||||
'Column should be the expected width');
|
||||
});
|
||||
|
||||
test.test('Resizing column during construction', function () {
|
||||
assert.doesNotThrow(function () {
|
||||
grid = new ColumnResizerGrid({
|
||||
id: 'i:d',
|
||||
columns: [
|
||||
{ field: 'foo', id: 'col:umn', width: 100 },
|
||||
{ field: 'bar' }
|
||||
]
|
||||
});
|
||||
}, null, 'ColumnResizer should not throw error during construction');
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
assert.strictEqual(query('.dgrid-cell')[0].offsetWidth, 100,
|
||||
'Column should be the expected width');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,102 @@
|
||||
define([
|
||||
'intern!tdd',
|
||||
'intern/chai!assert',
|
||||
'dojo/_base/declare',
|
||||
'dojo/query',
|
||||
'dgrid/Grid',
|
||||
'dgrid/ColumnSet',
|
||||
'dgrid/test/data/orderedData'
|
||||
], function (test, assert, declare, query, Grid, ColumnSet, orderedData) {
|
||||
|
||||
var grid;
|
||||
|
||||
function runClassNameTests() {
|
||||
var domNode = grid.domNode,
|
||||
node;
|
||||
|
||||
assert.strictEqual(query('.dgrid-cell.field-order', domNode).length, 10,
|
||||
'Each row (including header) should contain a cell with the field-order class');
|
||||
assert.strictEqual(query('.dgrid-cell.field-name', domNode).length, 10,
|
||||
'Each row (including header) should contain a cell with the field-name class');
|
||||
assert.strictEqual(query('.dgrid-cell.field-description', domNode).length, 10,
|
||||
'Each row (including header) should contain a cell with the field-description class');
|
||||
|
||||
assert.strictEqual(query('.dgrid-cell.field-name.name-column.main-column', domNode).length, 10,
|
||||
'Each row\'s (including header\'s) field-name cell should have the name-column and main-column classes');
|
||||
|
||||
assert.strictEqual(query('.dgrid-cell.field-description.desc-row', domNode).length, 9,
|
||||
'Each body row\'s description cell should also have the desc-row class');
|
||||
node = query('.dgrid-header .dgrid-cell.field-description', domNode)[0];
|
||||
assert.strictEqual(node.className.indexOf('undefined'), -1,
|
||||
'Header row\'s description cell should NOT contain \'undefined\' due to className returning \'\'');
|
||||
assert.isTrue(query('.dgrid-content .dgrid-cell.field-description', domNode).every(function (cell) {
|
||||
return (/desc-\w+ desc-row/).test(cell.className);
|
||||
}),
|
||||
'Each body row\'s description cell has two desc-* classes (one being desc-row)');
|
||||
}
|
||||
|
||||
test.suite('columns', function () {
|
||||
test.afterEach(function () {
|
||||
grid.destroy();
|
||||
});
|
||||
|
||||
test.test('className property', function () {
|
||||
grid = new Grid({
|
||||
columns: {
|
||||
order: 'Order',
|
||||
name: {
|
||||
label: 'Name',
|
||||
className: 'name-column main-column'
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
className: function (object) {
|
||||
return object ?
|
||||
'desc-' + object.name.replace(/ /g, '') + ' desc-row' :
|
||||
'';
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
grid.renderArray(orderedData.items);
|
||||
runClassNameTests();
|
||||
});
|
||||
});
|
||||
|
||||
test.suite('columnSets', function () {
|
||||
test.afterEach(function () {
|
||||
grid.destroy();
|
||||
});
|
||||
|
||||
test.test('className property', function () {
|
||||
grid = new (declare([Grid, ColumnSet]))({
|
||||
columnSets: [
|
||||
[[
|
||||
{ field: 'order', label: 'Order' },
|
||||
{
|
||||
field: 'name',
|
||||
label: 'Name',
|
||||
className: 'name-column main-column'
|
||||
}
|
||||
]], [[
|
||||
{
|
||||
field: 'description',
|
||||
label: 'Description',
|
||||
className: function (object) {
|
||||
return object ?
|
||||
'desc-' + object.name.replace(/ /g, '') + ' desc-row' :
|
||||
'';
|
||||
}
|
||||
}
|
||||
]]
|
||||
]
|
||||
});
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
grid.renderArray(orderedData.items);
|
||||
runClassNameTests();
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,26 @@
|
||||
define([
|
||||
'intern!tdd',
|
||||
'intern/chai!assert',
|
||||
'dojo/_base/declare',
|
||||
'dojo/on',
|
||||
'dgrid/List',
|
||||
'dgrid/OnDemandList',
|
||||
'dstore/Memory'
|
||||
], function (test, assert, declare, on, List, OnDemandList, Memory) {
|
||||
|
||||
test.suite('createDestroy', function () {
|
||||
|
||||
test.test('no params list', function () {
|
||||
|
||||
/*
|
||||
assert.strictEqual(list.contentNode.children.length, 3,
|
||||
'List\'s contentNode has expected number of children after renderArray');
|
||||
|
||||
list.destroy();
|
||||
assert.notStrictEqual(document.body, list.parentNode,
|
||||
'List is removed from body after destroy');
|
||||
*/
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,95 @@
|
||||
define([
|
||||
'intern!tdd',
|
||||
'intern/chai!assert',
|
||||
'dgrid/List',
|
||||
'dgrid/Grid',
|
||||
'dgrid/GridFromHtml',
|
||||
'dojo/_base/array',
|
||||
'dojo/parser',
|
||||
'dojo/dom-class',
|
||||
'dojo/dom-construct',
|
||||
'dojo/text!../resources/setClass.html'
|
||||
], function (test, assert, List, Grid, GridFromHtml, arrayUtil, parser, domClass, domConstruct, gridTemplate) {
|
||||
|
||||
test.suite('setClass', function () {
|
||||
// Tests
|
||||
test.test('Lists + initially-defined classes', function () {
|
||||
function renderRow(item) {
|
||||
var div = document.createElement('div');
|
||||
div.appendChild(document.createTextNode(item.name));
|
||||
return div;
|
||||
}
|
||||
// Build three lists
|
||||
var listC = window.listC = new List({
|
||||
'class': 'c',
|
||||
renderRow: renderRow
|
||||
}),
|
||||
listCN = window.listCN = new List({
|
||||
className: 'cn',
|
||||
renderRow: renderRow
|
||||
}),
|
||||
listDOM = window.listDOM = new List({
|
||||
renderRow: renderRow
|
||||
}, domConstruct.create('div', {'class': 'dom'}));
|
||||
|
||||
// Check the classes on each List.domNode
|
||||
assert.ok(domClass.contains(listC.domNode, 'c'));
|
||||
assert.ok(domClass.contains(listCN.domNode, 'cn'));
|
||||
assert.ok(domClass.contains(listDOM.domNode, 'dom'));
|
||||
|
||||
// Destroy the lists after performing the tests
|
||||
listC.destroy();
|
||||
listCN.destroy();
|
||||
listDOM.destroy();
|
||||
});
|
||||
|
||||
test.test('Grids + initially-defined classes', function () {
|
||||
// Build three grids
|
||||
var columns = {
|
||||
order: 'step', // give column a custom name
|
||||
name: {},
|
||||
description: { label: 'what to do', sortable: false }
|
||||
},
|
||||
gridC = window.gridC = new Grid({
|
||||
'class': 'c',
|
||||
columns: columns
|
||||
}),
|
||||
gridCN = window.gridCN = new Grid({
|
||||
'class': 'cn',
|
||||
columns: columns
|
||||
}),
|
||||
gridDOM = window.gridDOM = new Grid({
|
||||
columns: columns
|
||||
}, domConstruct.create('div', { 'class': 'dom' }));
|
||||
|
||||
// Check the classes on each List.domNode
|
||||
assert.ok(domClass.contains(gridC.domNode, 'c'));
|
||||
assert.ok(domClass.contains(gridCN.domNode, 'cn'));
|
||||
assert.ok(domClass.contains(gridDOM.domNode, 'dom'));
|
||||
|
||||
// Destroy the grids after performing the tests
|
||||
gridC.destroy();
|
||||
gridCN.destroy();
|
||||
gridDOM.destroy();
|
||||
});
|
||||
|
||||
test.test('Declarative Grid + initially-defined class', function () {
|
||||
/* global gridDecl */
|
||||
|
||||
// Create markup for a grid to be declaratively parsed
|
||||
var node = domConstruct.create('div', {
|
||||
innerHTML: gridTemplate
|
||||
});
|
||||
|
||||
// Expose GridFromHtml via a global namespace for parser to use
|
||||
window.dgrid = { GridFromHtml: GridFromHtml };
|
||||
parser.parse(node);
|
||||
|
||||
// Make sure the expected class exists on the parsed instance
|
||||
assert.ok(domClass.contains(gridDecl.domNode, 'dom'));
|
||||
|
||||
// Destroy the grid after performing the test
|
||||
gridDecl.destroy();
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,178 @@
|
||||
define([
|
||||
'intern!tdd',
|
||||
'intern/chai!assert',
|
||||
'dojo/_base/declare',
|
||||
'dojo/aspect',
|
||||
'dojo/on',
|
||||
'dgrid/Grid',
|
||||
'dgrid/OnDemandGrid',
|
||||
'dgrid/extensions/Pagination',
|
||||
'dgrid/test/data/errorStores',
|
||||
'dgrid/test/data/createSyncStore',
|
||||
'dgrid/test/data/createAsyncStore',
|
||||
'dgrid/test/data/genericData',
|
||||
'dgrid/test/data/testPerformanceStore',
|
||||
'../addCss!'
|
||||
], function (test, assert, declare, aspect, on, Grid, OnDemandGrid, Pagination,
|
||||
errorStores, createSyncStore, createAsyncStore, genericData, testPerformanceStore) {
|
||||
|
||||
var PaginationGrid = declare([Grid, Pagination]);
|
||||
var grid;
|
||||
var handles = [];
|
||||
|
||||
// Common reusable function for tests
|
||||
function storeTest(CustomGrid, store, expectSuccess, dfd) {
|
||||
var expectedEvent = expectSuccess ? 'dgrid-refresh-complete' : 'dgrid-error',
|
||||
unexpectedEvent = !expectSuccess ? 'dgrid-refresh-complete' : 'dgrid-error';
|
||||
|
||||
grid = new CustomGrid({
|
||||
collection: store
|
||||
});
|
||||
|
||||
// Hook up event handler before calling startup, to be able to
|
||||
// test both synchronous and asynchronous stores
|
||||
handles.push(on.once(grid, expectedEvent, function () {
|
||||
// After receiving the expected event, perform a refresh,
|
||||
// to also test resolution/rejection of the promise it returns.
|
||||
grid.refresh().then(function () {
|
||||
dfd[expectSuccess ? 'resolve' : 'reject']();
|
||||
}, function () {
|
||||
dfd[!expectSuccess ? 'resolve' : 'reject']();
|
||||
});
|
||||
}));
|
||||
|
||||
// Also hook up the opposite event handler, to signal failure
|
||||
handles.push(on.once(grid, unexpectedEvent, function () {
|
||||
dfd.reject(new Error('Expected ' + expectedEvent + ' to fire, but ' +
|
||||
unexpectedEvent + ' fired instead.'));
|
||||
}));
|
||||
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
return dfd;
|
||||
}
|
||||
|
||||
function createReleaseRangeGrid(CustomGrid) {
|
||||
grid = new CustomGrid({
|
||||
collection: testPerformanceStore,
|
||||
columns: {
|
||||
id: 'ID'
|
||||
},
|
||||
sort: 'id'
|
||||
});
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
}
|
||||
|
||||
function testReleaseRange(visibleId) {
|
||||
var numInserts = 0;
|
||||
|
||||
handles.push(aspect.after(grid, 'insertRow', function () {
|
||||
numInserts++;
|
||||
}, true));
|
||||
|
||||
testPerformanceStore.putSync(testPerformanceStore.getSync(0));
|
||||
assert.strictEqual(numInserts, 0,
|
||||
'Item from unrendered range should not be added to grid when updated');
|
||||
testPerformanceStore.putSync(testPerformanceStore.getSync(visibleId || 19999));
|
||||
assert.strictEqual(numInserts, 1,
|
||||
'Item from rendered range should be re-added to grid when updated');
|
||||
}
|
||||
|
||||
test.suite('stores', function () {
|
||||
// Setup / teardown
|
||||
test.afterEach(function () {
|
||||
for (var i = handles.length; i--;) {
|
||||
handles[i].remove();
|
||||
}
|
||||
handles = [];
|
||||
grid.destroy();
|
||||
});
|
||||
|
||||
var store = createSyncStore({ data: genericData }),
|
||||
asyncStore = createAsyncStore({ data: genericData });
|
||||
|
||||
test.test('OnDemandGrid + sync store', function () {
|
||||
storeTest(OnDemandGrid, store, true, this.async());
|
||||
});
|
||||
|
||||
test.test('OnDemandGrid + async store', function () {
|
||||
storeTest(OnDemandGrid, asyncStore, true, this.async());
|
||||
});
|
||||
|
||||
test.test('OnDemandGrid + async store w/ error', function () {
|
||||
storeTest(OnDemandGrid, errorStores.asyncFetch, false, this.async());
|
||||
});
|
||||
|
||||
test.test('OnDemandGrid + async store w/ total error', function () {
|
||||
storeTest(OnDemandGrid, errorStores.asyncFetchTotal, false, this.async());
|
||||
});
|
||||
|
||||
test.test('OnDemandGrid observes/releases ranges appropriately', function () {
|
||||
var dfd = this.async();
|
||||
createReleaseRangeGrid(OnDemandGrid);
|
||||
|
||||
// Since _processScroll gets called on a debounce, need to wait for it
|
||||
handles.push(aspect.after(grid, '_processScroll', dfd.callback(function () {
|
||||
testReleaseRange();
|
||||
}), true));
|
||||
|
||||
grid.scrollTo({ y: grid.bodyNode.scrollHeight });
|
||||
return dfd;
|
||||
});
|
||||
|
||||
test.test('PaginationGrid + sync store', function () {
|
||||
storeTest(PaginationGrid, store, true, this.async());
|
||||
});
|
||||
|
||||
test.test('PaginationGrid + async store', function () {
|
||||
storeTest(PaginationGrid, asyncStore, true, this.async());
|
||||
});
|
||||
|
||||
test.test('PaginationGrid + async store w/ error', function () {
|
||||
storeTest(PaginationGrid, errorStores.asyncFetch, false, this.async());
|
||||
});
|
||||
|
||||
test.test('Pagination observes/releases ranges appropriately', function () {
|
||||
createReleaseRangeGrid(PaginationGrid);
|
||||
grid.gotoPage(2);
|
||||
testReleaseRange(10);
|
||||
});
|
||||
});
|
||||
|
||||
test.suite('Async empty stores', function () {
|
||||
test.afterEach(function () {
|
||||
grid.destroy();
|
||||
});
|
||||
|
||||
var emptyStore = createAsyncStore({ data: [] });
|
||||
|
||||
function createTest(Grid) {
|
||||
return function () {
|
||||
var dfd = this.async(1000);
|
||||
grid = new Grid({
|
||||
columns: {
|
||||
id: 'ID'
|
||||
},
|
||||
collection: emptyStore
|
||||
});
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
|
||||
grid.on('dgrid-error', function () {
|
||||
dfd.reject('dgrid-error should not be emitted on consecutive synchronous refresh');
|
||||
});
|
||||
|
||||
grid.refresh().then(function () {
|
||||
dfd.resolve();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
test.test('OnDemandGrid consecutive refresh with async empty store (#1065)',
|
||||
createTest(OnDemandGrid));
|
||||
|
||||
test.test('Pagination consecutive refresh with async empty store',
|
||||
createTest(PaginationGrid));
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,388 @@
|
||||
define([
|
||||
'intern!tdd',
|
||||
'intern/chai!assert',
|
||||
'dojo/_base/declare',
|
||||
'dojo/aspect',
|
||||
'dojo/dom-class',
|
||||
'dojo/query',
|
||||
'../../data/createSyncStore',
|
||||
'dgrid/OnDemandList'
|
||||
], function (test, assert, declare, aspect, domClass, query, createSyncStore, OnDemandList) {
|
||||
|
||||
var widget,
|
||||
storeCounter = 0;
|
||||
|
||||
function destroyWidget() {
|
||||
if (widget) {
|
||||
widget.destroy();
|
||||
widget = null;
|
||||
}
|
||||
}
|
||||
|
||||
function indexToId(index) {
|
||||
return (index + 1) * 10;
|
||||
}
|
||||
|
||||
function createItem(index) {
|
||||
var id = indexToId(index);
|
||||
return { id: id, value: 'Value ' + id + ' / Store ' + storeCounter };
|
||||
}
|
||||
|
||||
function createData(numStoreItems) {
|
||||
var data = [];
|
||||
for (var i = 0; i < numStoreItems; i++) {
|
||||
data.push(createItem(i));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function createStore(numStoreItems) {
|
||||
storeCounter++;
|
||||
return createSyncStore({
|
||||
data: createData(numStoreItems)
|
||||
});
|
||||
}
|
||||
|
||||
function renderRow(object) {
|
||||
var div = document.createElement('div');
|
||||
div.appendChild(document.createTextNode(object.value));
|
||||
return div;
|
||||
}
|
||||
|
||||
function createList(numStoreItems, itemsPerQuery, overlap, shouldTrackCollection) {
|
||||
widget = new OnDemandList({
|
||||
collection: createStore(numStoreItems),
|
||||
minRowsPerPage: itemsPerQuery,
|
||||
maxRowsPerPage: itemsPerQuery,
|
||||
queryRowsOverlap: overlap,
|
||||
renderRow: renderRow,
|
||||
shouldTrackCollection: shouldTrackCollection !== false,
|
||||
sort: 'id'
|
||||
});
|
||||
document.body.appendChild(widget.domNode);
|
||||
widget.startup();
|
||||
}
|
||||
|
||||
function itemTest(itemAction, index, numToModify, backwards) {
|
||||
// Creates a single test case for performing an action on numToModify rows/items.
|
||||
var description = itemAction.actionName + ' ' + numToModify + ' item' + (numToModify > 1 ? 's' : '') +
|
||||
' starting at index ' + index + ', in ' + (backwards ? 'decreasing' : 'increasing') + ' order';
|
||||
|
||||
numToModify = numToModify || 1;
|
||||
|
||||
test.test(description, function () {
|
||||
var i,
|
||||
cnt,
|
||||
step = function () {
|
||||
cnt++;
|
||||
backwards ? i-- : i++;
|
||||
},
|
||||
tmp,
|
||||
expectedValues = [],
|
||||
msgPrefix;
|
||||
|
||||
function testRow(element, i) {
|
||||
var expectedValue = expectedValues[i];
|
||||
if (expectedValue == null || expectedValue.deleted) {
|
||||
assert.isTrue(element == null, msgPrefix + 'row at index ' + i + ' should not be found');
|
||||
}
|
||||
else {
|
||||
expectedValue = expectedValue.value;
|
||||
assert.isTrue(element != null,
|
||||
msgPrefix + 'row at index ' + i + ' with an expected value of "' +
|
||||
expectedValue + '" is missing');
|
||||
assert.strictEqual(expectedValue, element.innerHTML,
|
||||
msgPrefix + element.innerHTML + ' should be ' + expectedValue);
|
||||
}
|
||||
}
|
||||
|
||||
// Perform the actions and update the array of expected values.
|
||||
expectedValues = createData(widget.collection.data.length);
|
||||
for (i = index, cnt = 0; cnt < numToModify; step()) {
|
||||
itemAction(indexToId(i), expectedValues);
|
||||
}
|
||||
|
||||
// Use the dgrid widget API to test if the action was performed properly.
|
||||
msgPrefix = 'dgrid API: ';
|
||||
tmp = [];
|
||||
for (i = 0; i < expectedValues.length; i++) {
|
||||
var expectedValue = expectedValues[i],
|
||||
expectedId = expectedValue.id;
|
||||
testRow(widget.row(expectedId).element, i);
|
||||
if (!expectedValue.deleted) {
|
||||
tmp.push(expectedValue);
|
||||
}
|
||||
}
|
||||
expectedValues = tmp;
|
||||
|
||||
// Query the DOM to verify the structure matches the expected results.
|
||||
msgPrefix = 'DOM query: ';
|
||||
query('.dgrid-row', widget.domNode).forEach(testRow);
|
||||
});
|
||||
}
|
||||
|
||||
function itemTestSuite(widgetClassName, storeSize, itemsPerQuery, overlap, config) {
|
||||
// Create a test suite that performs one action type (itemAction) on 1 to config.itemsModifiedMax with
|
||||
// a given amount of overlap.
|
||||
var index, numToModify;
|
||||
|
||||
test.suite(widgetClassName + ' with ' + overlap + ' overlap', function () {
|
||||
|
||||
test.beforeEach(function () {
|
||||
createList(storeSize, itemsPerQuery, overlap);
|
||||
});
|
||||
|
||||
test.afterEach(destroyWidget);
|
||||
|
||||
// Modify items counting up.
|
||||
for (numToModify = 1; numToModify <= config.itemsModifiedMax; numToModify++) {
|
||||
for (index = 0; index <= (storeSize - numToModify); index++) {
|
||||
itemTest(config.itemAction, index, numToModify);
|
||||
}
|
||||
}
|
||||
// Modify items counting down. Starting at a count of 2 because
|
||||
// single item modification were tested above.
|
||||
for (numToModify = 2; numToModify <= config.itemsModifiedMax; numToModify++) {
|
||||
for (index = numToModify - 1; index < storeSize; index++) {
|
||||
itemTest(config.itemAction, index, numToModify, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function itemActionTestSuite(description, itemAction, config) {
|
||||
// Creates multiple item test suites for a given action (itemAction):
|
||||
// - a list that executes a single query
|
||||
// - lists with overlap from 0 to config.itemOverlapMax
|
||||
|
||||
// Note: for debugging, comment out the contents of destroyWidget so the dgrid widgets are not destroyed.
|
||||
// Each widget uses a different store id and those ids are used in the row contents allowing you to
|
||||
// easily match up an error message like
|
||||
// "Error: dgrid API: row at index 2 with an expected value of "Value 30 / Store 10 / Changed!" is missing"
|
||||
// with the correct widget on the page.
|
||||
config.itemAction = itemAction;
|
||||
|
||||
test.suite(description, function () {
|
||||
// Test widgets with only one query: total item count equals item count per query.
|
||||
itemTestSuite('OnDemandList one query', config.itemsPerQuery, config.itemsPerQuery, 0, config);
|
||||
|
||||
// Test widgets that make multiple query requests: twice as many items as items per query so multiple
|
||||
// queries will create multiple observers.
|
||||
var storeSize = config.itemsPerQuery * 2;
|
||||
// Test with OnDemandList with varying overlap values
|
||||
for (var overlap = 0; overlap <= config.itemOverlapMax; overlap++) {
|
||||
itemTestSuite('OnDemandList multiple queries', storeSize, config.itemsPerQuery, overlap, config);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function itemAddEmptyStoreTest(itemsToAddCount, itemsPerQuery, overlap) {
|
||||
var i;
|
||||
|
||||
function rowHasClass(rowNode, cssClass) {
|
||||
assert.isTrue(domClass.contains(rowNode, cssClass), rowNode.outerHTML + ' should have ' + cssClass);
|
||||
}
|
||||
|
||||
test.test('Add ' + itemsToAddCount + ' items with ' + overlap + ' overlap', function () {
|
||||
createList(0, itemsPerQuery, overlap);
|
||||
var store = widget.collection;
|
||||
for (i = 0; i < itemsToAddCount; i++) {
|
||||
store.put(createItem(i));
|
||||
}
|
||||
|
||||
var rows = query('.dgrid-content > div', widget.domNode);
|
||||
rowHasClass(rows[0], 'dgrid-preload');
|
||||
for (i = 1; i <= itemsToAddCount; i++) {
|
||||
rowHasClass(rows[i], (i % 2) ? 'dgrid-row-even' : 'dgrid-row-odd');
|
||||
}
|
||||
rowHasClass(rows[i], 'dgrid-preload');
|
||||
|
||||
for (i = 0; i < itemsToAddCount; i++) {
|
||||
store.put(createItem(i));
|
||||
}
|
||||
|
||||
rows = query('.dgrid-content > div', widget.domNode);
|
||||
rowHasClass(rows[0], 'dgrid-preload');
|
||||
for (i = 1; i <= itemsToAddCount; i++) {
|
||||
rowHasClass(rows[i], (i % 2) ? 'dgrid-row-even' : 'dgrid-row-odd');
|
||||
}
|
||||
rowHasClass(rows[i], 'dgrid-preload');
|
||||
});
|
||||
}
|
||||
|
||||
function itemAddEmptyStoreTestSuite(config) {
|
||||
test.suite('Add items to empty store', function () {
|
||||
|
||||
test.afterEach(destroyWidget);
|
||||
|
||||
itemAddEmptyStoreTest(1, config.itemsPerQuery, 0);
|
||||
|
||||
// Test with OnDemandList with varying overlap values
|
||||
for (var overlap = 0; overlap <= config.itemOverlapMax; overlap++) {
|
||||
itemAddEmptyStoreTest(config.itemsPerQuery + overlap + 1, config.itemsPerQuery, overlap);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
test.suite('Trackable lists', function () {
|
||||
// Creates test suites that execute the following actions on OnDemandLists with varying amount of
|
||||
// overlap and modifying varying number of items:
|
||||
// - modify existing items
|
||||
// - remove existing items
|
||||
// - add new items before existing items
|
||||
// - add new items after existing items
|
||||
|
||||
function findIndex(id, objs) {
|
||||
for (var i = 0; i < objs.length; i++) {
|
||||
var obj = objs[i];
|
||||
if (obj && obj.id === id) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
var modifyAction = function (id, expectedValues) {
|
||||
var index = findIndex(id, expectedValues);
|
||||
var value = expectedValues[index].value + ' / Changed!';
|
||||
var dataObj = {id: id, value: value};
|
||||
widget.collection.put(dataObj);
|
||||
expectedValues[index] = dataObj;
|
||||
};
|
||||
modifyAction.actionName = 'Modify';
|
||||
|
||||
var removeAction = function (id, expectedValues) {
|
||||
widget.collection.remove(id);
|
||||
var index = findIndex(id, expectedValues);
|
||||
expectedValues[index].deleted = true;
|
||||
};
|
||||
removeAction.actionName = 'Remove';
|
||||
|
||||
var addBeforeAction = function (id, expectedValues) {
|
||||
var index = findIndex(id, expectedValues);
|
||||
var obj = { id: id - 5, value: expectedValues[index].value + ' / Added before!' };
|
||||
widget.collection.add(obj);
|
||||
expectedValues.splice(index, 0, obj);
|
||||
};
|
||||
addBeforeAction.actionName = 'Add before';
|
||||
|
||||
var addAfterAction = function (id, expectedValues) {
|
||||
var index = findIndex(id, expectedValues);
|
||||
var obj = {id: id + 5, value: expectedValues[index].value + ' / Added after!'};
|
||||
widget.collection.add(obj);
|
||||
expectedValues.splice(index + 1, 0, obj);
|
||||
};
|
||||
addAfterAction.actionName = 'Add after';
|
||||
|
||||
// Run a test case with each action (modify, remove, add before, add after) and vary the amount of
|
||||
// queryRowsOverlap and vary the number of items modified during each test case. A configuration
|
||||
// object controls the amount of variation. The properties are:
|
||||
// itemsPerQuery - The OnDemandList is configured to request this number of items per query.
|
||||
// This property also determines the size of the store. Test cases run with a store size
|
||||
// equal to this number and test cases run with a store size twice this number.
|
||||
// itemOverlapMax - Each test case is executed with a queryRowsOverap value of 0 up to this number.
|
||||
// itemsModifiedMax - Each test is executed where the number of items modified, deleted or added is
|
||||
// 1 up to this number; all of the test cases are run where 1 item is modified and then again
|
||||
// with 2 items being modified and so on.
|
||||
var config = {
|
||||
itemsPerQuery: 3,
|
||||
itemOverlapMax: 2,
|
||||
itemsModifiedMax: 2
|
||||
};
|
||||
itemActionTestSuite('Modify store items', modifyAction, config);
|
||||
itemActionTestSuite('Remove store items', removeAction, config);
|
||||
itemActionTestSuite('Insert store items before', addBeforeAction, config);
|
||||
itemActionTestSuite('Insert store items after', addAfterAction, config);
|
||||
|
||||
itemAddEmptyStoreTestSuite(config);
|
||||
});
|
||||
|
||||
test.suite('Multiple updates to trackable list', function () {
|
||||
test.afterEach(destroyWidget);
|
||||
|
||||
test.test('Multiple puts', function () {
|
||||
var i;
|
||||
var data = [];
|
||||
for (i = 0; i < 10; i++) {
|
||||
data.push({ id: i, value: 'Value ' + i, enabled: true });
|
||||
}
|
||||
var store = createSyncStore({ data: data });
|
||||
widget = new OnDemandList({
|
||||
collection: store.filter({ enabled: true }),
|
||||
renderRow: renderRow
|
||||
});
|
||||
document.body.appendChild(widget.domNode);
|
||||
widget.startup();
|
||||
|
||||
// Test putting several items with a filter applied;
|
||||
// the put objects should all be seen as removed
|
||||
for (i = 0; i < 5; i++){
|
||||
var item = data[i];
|
||||
item.enabled = false;
|
||||
store.put(item);
|
||||
}
|
||||
|
||||
assert.strictEqual(widget._rows.length, 5,
|
||||
'5 items should remain in the _rows array (5 should be removed)');
|
||||
});
|
||||
});
|
||||
|
||||
test.suite('shouldTrackCollection = false + store modifications', function () {
|
||||
var numItems = 3;
|
||||
var store;
|
||||
var handles = [];
|
||||
|
||||
test.before(function () {
|
||||
createList(numItems, 25, 0, false);
|
||||
});
|
||||
|
||||
test.beforeEach(function () {
|
||||
store = createStore(numItems);
|
||||
widget.set('collection', store);
|
||||
});
|
||||
|
||||
test.afterEach(function () {
|
||||
for (var i = handles.length; i--;) {
|
||||
handles[i].remove();
|
||||
}
|
||||
handles = [];
|
||||
});
|
||||
|
||||
test.after(destroyWidget);
|
||||
|
||||
function countRows() {
|
||||
var count = query('.dgrid-row', widget.contentNode).length;
|
||||
return count;
|
||||
}
|
||||
|
||||
test.test('shouldTrackCollection = false + add', function () {
|
||||
var numRows = countRows();
|
||||
store.addSync(createItem(3));
|
||||
assert.strictEqual(countRows(), numRows);
|
||||
});
|
||||
|
||||
test.test('shouldTrackCollection = false + put', function () {
|
||||
var calls = 0;
|
||||
|
||||
handles.push(aspect.before(widget, 'removeRow', function () {
|
||||
calls++;
|
||||
}));
|
||||
handles.push(aspect.before(widget, 'insertRow', function () {
|
||||
calls++;
|
||||
}));
|
||||
|
||||
for (var i = 0; i < numItems; i++) {
|
||||
store.putSync(store.getSync(indexToId(i)));
|
||||
}
|
||||
assert.strictEqual(calls, 0, 'insertRow and removeRow should never be called');
|
||||
});
|
||||
|
||||
test.test('shouldTrackCollection = false + remove', function () {
|
||||
var numRows = countRows();
|
||||
for (var i = 0; i < numItems; i++) {
|
||||
store.removeSync(indexToId(i));
|
||||
}
|
||||
assert.strictEqual(countRows(), numRows);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,39 @@
|
||||
define([
|
||||
'intern!tdd',
|
||||
'intern/chai!assert',
|
||||
'dojo/_base/declare',
|
||||
'dgrid/Grid',
|
||||
'dgrid/extensions/ColumnHider'
|
||||
], function (test, assert, declare, Grid, ColumnHider) {
|
||||
var ColumnHiderGrid = declare([ Grid, ColumnHider ]);
|
||||
var grid;
|
||||
|
||||
test.suite('ColumnHider', function () {
|
||||
test.beforeEach(function () {
|
||||
grid = new ColumnHiderGrid({
|
||||
columns: {
|
||||
col1: 'Column 1',
|
||||
col2: {
|
||||
label: 'Column 2',
|
||||
unhidable: true
|
||||
}
|
||||
}
|
||||
});
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
grid.renderArray([]);
|
||||
});
|
||||
|
||||
test.afterEach(function () {
|
||||
grid.destroy();
|
||||
});
|
||||
|
||||
test.suite('#toggleColumnHiddenState', function () {
|
||||
test.test('unhidable column', function () {
|
||||
assert.doesNotThrow(function () {
|
||||
grid.toggleColumnHiddenState('col2');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,713 @@
|
||||
define([
|
||||
'intern!tdd',
|
||||
'intern/chai!assert',
|
||||
'dojo/_base/declare',
|
||||
'dgrid/Grid',
|
||||
'dgrid/extensions/CompoundColumns'
|
||||
], function (test, assert, declare, Grid, CompoundColumns) {
|
||||
var CompoundColumnGrid = declare([Grid, CompoundColumns]),
|
||||
data = [],
|
||||
grid;
|
||||
|
||||
// Generate data to be used for all tests
|
||||
for (var itemIndex = 0; itemIndex < 12; itemIndex++) {
|
||||
var item = { id: itemIndex };
|
||||
for (var propIndex = 0; propIndex < 10; propIndex++) {
|
||||
item['data' + propIndex] = 'Value ' + itemIndex + ':' + propIndex;
|
||||
}
|
||||
data.push(item);
|
||||
}
|
||||
|
||||
function createGrid(columns, hideHeader) {
|
||||
grid = new CompoundColumnGrid({
|
||||
columns: columns,
|
||||
showHeader: !hideHeader
|
||||
});
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
grid.renderArray(data);
|
||||
}
|
||||
|
||||
test.suite('CompoundColumns', function () {
|
||||
test.suite('cell method', function () {
|
||||
test.afterEach(function () {
|
||||
grid.destroy();
|
||||
});
|
||||
|
||||
test.test('simple grid', function () {
|
||||
createGrid({
|
||||
data0: 'Data 0',
|
||||
data1: 'Data 1',
|
||||
data2: 'Data 2',
|
||||
data3: 'Data 3',
|
||||
data4: 'Data 4'
|
||||
}, true);
|
||||
|
||||
assert.strictEqual(grid.cell(0, 0).element.innerHTML, 'Value 0:0');
|
||||
assert.strictEqual(grid.cell(0, 4).element.innerHTML, 'Value 0:4');
|
||||
assert.strictEqual(grid.cell(11, 0).element.innerHTML, 'Value 11:0');
|
||||
assert.strictEqual(grid.cell(11, 4).element.innerHTML, 'Value 11:4');
|
||||
assert.isUndefined(grid.cell(0, 5).element);
|
||||
assert.isUndefined(grid.cell(12, 0).element);
|
||||
});
|
||||
|
||||
test.test('simple grid with column ids', function () {
|
||||
createGrid({
|
||||
data0: { label: 'Data 0', id: 'myData0' },
|
||||
data1: { label: 'Data 1', id: 'myData1' },
|
||||
data2: { label: 'Data 2', id: 'myData2' },
|
||||
data3: { label: 'Data 3', id: 'myData3' },
|
||||
data4: { label: 'Data 4', id: 'myData4' }
|
||||
}, true);
|
||||
|
||||
assert.strictEqual(grid.cell(0, 'myData0').element.innerHTML, 'Value 0:0');
|
||||
assert.strictEqual(grid.cell(0, 'myData4').element.innerHTML, 'Value 0:4');
|
||||
assert.strictEqual(grid.cell(11, 'myData0').element.innerHTML, 'Value 11:0');
|
||||
assert.strictEqual(grid.cell(11, 'myData4').element.innerHTML, 'Value 11:4');
|
||||
assert.isUndefined(grid.cell(0, 'myData5').element);
|
||||
assert.isUndefined(grid.cell(12, 'myData0').element);
|
||||
|
||||
assert.isUndefined(grid.cell(0, 0).element);
|
||||
});
|
||||
|
||||
test.test('grid with children', function () {
|
||||
createGrid([
|
||||
{ field: 'data0', label: 'Data 0' },
|
||||
{
|
||||
label: 'Compound 1',
|
||||
children: [
|
||||
{ field: 'data1', label: 'Data 1' },
|
||||
{ field: 'data2', label: 'Data 2' }
|
||||
]
|
||||
},
|
||||
{ field: 'data3', label: 'Data 3' },
|
||||
{
|
||||
label: 'Compound 2',
|
||||
children: [
|
||||
{ field: 'data4', label: 'Data 4' },
|
||||
{ field: 'data5', label: 'Data 5' }
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
assert.strictEqual(grid.cell(0, 0).element.innerHTML, 'Value 0:0');
|
||||
assert.strictEqual(grid.cell(0, 1).element.innerHTML, 'Value 0:1');
|
||||
assert.strictEqual(grid.cell(0, 2).element.innerHTML, 'Value 0:2');
|
||||
assert.strictEqual(grid.cell(0, 5).element.innerHTML, 'Value 0:5');
|
||||
assert.strictEqual(grid.cell(11, 0).element.innerHTML, 'Value 11:0');
|
||||
assert.strictEqual(grid.cell(11, 1).element.innerHTML, 'Value 11:1');
|
||||
assert.strictEqual(grid.cell(11, 2).element.innerHTML, 'Value 11:2');
|
||||
assert.strictEqual(grid.cell(11, 5).element.innerHTML, 'Value 11:5');
|
||||
|
||||
assert.isUndefined(grid.cell(0, 6).element);
|
||||
assert.isUndefined(grid.cell(12, 0).element);
|
||||
});
|
||||
|
||||
test.test('grid with children and children ids', function () {
|
||||
createGrid([
|
||||
{ field: 'data0', label: 'Data 0' },
|
||||
{
|
||||
label: 'Compound 1',
|
||||
children: [
|
||||
{ field: 'data1', label: 'Data 1', id: 'myData1' },
|
||||
{ field: 'data2', label: 'Data 2', id: 'myData2' }
|
||||
]
|
||||
},
|
||||
{ field: 'data3', label: 'Data 3' },
|
||||
{
|
||||
label: 'Compound 2',
|
||||
children: [
|
||||
{ field: 'data4', label: 'Data 4', id: 'myData4' },
|
||||
{ field: 'data5', label: 'Data 5', id: 'myData5' }
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
assert.strictEqual(grid.cell(0, 0).element.innerHTML, 'Value 0:0');
|
||||
assert.strictEqual(grid.cell(0, 3).element.innerHTML, 'Value 0:3');
|
||||
assert.strictEqual(grid.cell(0, 'myData1').element.innerHTML, 'Value 0:1');
|
||||
assert.strictEqual(grid.cell(0, 'myData2').element.innerHTML, 'Value 0:2');
|
||||
assert.strictEqual(grid.cell(0, 'myData5').element.innerHTML, 'Value 0:5');
|
||||
assert.strictEqual(grid.cell(11, 0).element.innerHTML, 'Value 11:0');
|
||||
assert.strictEqual(grid.cell(11, 3).element.innerHTML, 'Value 11:3');
|
||||
assert.strictEqual(grid.cell(11, 'myData1').element.innerHTML, 'Value 11:1');
|
||||
assert.strictEqual(grid.cell(11, 'myData2').element.innerHTML, 'Value 11:2');
|
||||
assert.strictEqual(grid.cell(11, 'myData5').element.innerHTML, 'Value 11:5');
|
||||
|
||||
assert.strictEqual(grid.cell(0, '0-1-myData1').element.innerHTML, 'Value 0:1');
|
||||
assert.strictEqual(grid.cell(0, '0-1-myData2').element.innerHTML, 'Value 0:2');
|
||||
assert.strictEqual(grid.cell(0, '0-4-myData5').element.innerHTML, 'Value 0:5');
|
||||
assert.strictEqual(grid.cell(11, '0-1-myData1').element.innerHTML, 'Value 11:1');
|
||||
assert.strictEqual(grid.cell(11, '0-1-myData2').element.innerHTML, 'Value 11:2');
|
||||
assert.strictEqual(grid.cell(11, '0-4-myData5').element.innerHTML, 'Value 11:5');
|
||||
|
||||
assert.strictEqual(grid.cell(0, '1-myData1').element.innerHTML, 'Value 0:1');
|
||||
assert.strictEqual(grid.cell(0, '1-myData2').element.innerHTML, 'Value 0:2');
|
||||
assert.strictEqual(grid.cell(0, '4-myData5').element.innerHTML, 'Value 0:5');
|
||||
assert.strictEqual(grid.cell(11, '1-myData1').element.innerHTML, 'Value 11:1');
|
||||
assert.strictEqual(grid.cell(11, '1-myData2').element.innerHTML, 'Value 11:2');
|
||||
assert.strictEqual(grid.cell(11, '4-myData5').element.innerHTML, 'Value 11:5');
|
||||
});
|
||||
|
||||
test.test('grid with children and ids', function () {
|
||||
createGrid([
|
||||
{ field: 'data0', label: 'Data 0' },
|
||||
{
|
||||
label: 'Compound 1',
|
||||
id: 'compound1',
|
||||
children: [
|
||||
{ field: 'data1', label: 'Data 1', id: 'myData1' },
|
||||
{ field: 'data2', label: 'Data 2', id: 'myData2' }
|
||||
]
|
||||
},
|
||||
{ field: 'data3', label: 'Data 3' },
|
||||
{
|
||||
label: 'Compound 2',
|
||||
id: 'compound2',
|
||||
children: [
|
||||
{ field: 'data4', label: 'Data 4', id: 'myData4' },
|
||||
{ field: 'data5', label: 'Data 5', id: 'myData5' }
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
assert.strictEqual(grid.cell(0, 0).element.innerHTML, 'Value 0:0');
|
||||
assert.strictEqual(grid.cell(0, 3).element.innerHTML, 'Value 0:3');
|
||||
assert.strictEqual(grid.cell(0, 'myData1').element.innerHTML, 'Value 0:1');
|
||||
assert.strictEqual(grid.cell(0, 'myData2').element.innerHTML, 'Value 0:2');
|
||||
assert.strictEqual(grid.cell(0, 'myData5').element.innerHTML, 'Value 0:5');
|
||||
assert.strictEqual(grid.cell(11, 0).element.innerHTML, 'Value 11:0');
|
||||
assert.strictEqual(grid.cell(11, 3).element.innerHTML, 'Value 11:3');
|
||||
assert.strictEqual(grid.cell(11, 'myData1').element.innerHTML, 'Value 11:1');
|
||||
assert.strictEqual(grid.cell(11, 'myData2').element.innerHTML, 'Value 11:2');
|
||||
assert.strictEqual(grid.cell(11, 'myData5').element.innerHTML, 'Value 11:5');
|
||||
|
||||
assert.strictEqual(grid.cell(0, 'compound1-myData1').element.innerHTML, 'Value 0:1');
|
||||
assert.strictEqual(grid.cell(0, 'compound1-myData2').element.innerHTML, 'Value 0:2');
|
||||
assert.strictEqual(grid.cell(0, 'compound2-myData5').element.innerHTML, 'Value 0:5');
|
||||
assert.strictEqual(grid.cell(11, 'compound1-myData1').element.innerHTML, 'Value 11:1');
|
||||
assert.strictEqual(grid.cell(11, 'compound1-myData2').element.innerHTML, 'Value 11:2');
|
||||
assert.strictEqual(grid.cell(11, 'compound2-myData5').element.innerHTML, 'Value 11:5');
|
||||
});
|
||||
|
||||
test.test('grid with nested children and ids', function () {
|
||||
createGrid([
|
||||
{ field: 'data0', label: 'Data 0' },
|
||||
{
|
||||
label: 'Compound 1',
|
||||
id: 'compound1',
|
||||
children: [
|
||||
{
|
||||
label: 'Nested Compound 1',
|
||||
id: 'nested1',
|
||||
children: [
|
||||
{ field: 'data1', label: 'Data 1', id: 'myData1' },
|
||||
{ field: 'data9', label: 'Data 9', id: 'myData9' }
|
||||
]
|
||||
},
|
||||
{ field: 'data2', label: 'Data 2', id: 'myData2' }
|
||||
]
|
||||
},
|
||||
{ field: 'data3', label: 'Data 3' },
|
||||
{
|
||||
label: 'Compound 2',
|
||||
id: 'compound2',
|
||||
children: [
|
||||
{ field: 'data4', label: 'Data 4', id: 'myData4' },
|
||||
{
|
||||
label: 'Nested Compound 2',
|
||||
id: 'nested2',
|
||||
children: [
|
||||
{ field: 'data5', label: 'Data 5', id: 'myData5' },
|
||||
{ field: 'data8', label: 'Data 8', id: 'myData8' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
assert.strictEqual(grid.cell(0, 'myData1').element.innerHTML, 'Value 0:1');
|
||||
assert.strictEqual(grid.cell(0, 'myData2').element.innerHTML, 'Value 0:2');
|
||||
assert.strictEqual(grid.cell(0, 'myData9').element.innerHTML, 'Value 0:9');
|
||||
assert.strictEqual(grid.cell(0, 'myData4').element.innerHTML, 'Value 0:4');
|
||||
assert.strictEqual(grid.cell(0, 'myData5').element.innerHTML, 'Value 0:5');
|
||||
assert.strictEqual(grid.cell(0, 'myData8').element.innerHTML, 'Value 0:8');
|
||||
assert.strictEqual(grid.cell(11, 'myData1').element.innerHTML, 'Value 11:1');
|
||||
assert.strictEqual(grid.cell(11, 'myData2').element.innerHTML, 'Value 11:2');
|
||||
assert.strictEqual(grid.cell(11, 'myData9').element.innerHTML, 'Value 11:9');
|
||||
assert.strictEqual(grid.cell(11, 'myData4').element.innerHTML, 'Value 11:4');
|
||||
assert.strictEqual(grid.cell(11, 'myData5').element.innerHTML, 'Value 11:5');
|
||||
assert.strictEqual(grid.cell(11, 'myData8').element.innerHTML, 'Value 11:8');
|
||||
|
||||
assert.strictEqual(grid.cell(0, 'nested1-myData1').element.innerHTML, 'Value 0:1');
|
||||
assert.strictEqual(grid.cell(0, 'nested1-myData9').element.innerHTML, 'Value 0:9');
|
||||
assert.strictEqual(grid.cell(0, 'nested2-myData5').element.innerHTML, 'Value 0:5');
|
||||
assert.strictEqual(grid.cell(0, 'nested2-myData8').element.innerHTML, 'Value 0:8');
|
||||
assert.strictEqual(grid.cell(11, 'nested1-myData1').element.innerHTML, 'Value 11:1');
|
||||
assert.strictEqual(grid.cell(11, 'nested1-myData9').element.innerHTML, 'Value 11:9');
|
||||
assert.strictEqual(grid.cell(11, 'nested2-myData5').element.innerHTML, 'Value 11:5');
|
||||
assert.strictEqual(grid.cell(11, 'nested2-myData8').element.innerHTML, 'Value 11:8');
|
||||
|
||||
assert.strictEqual(grid.cell(0, 'compound1-nested1-myData1').element.innerHTML, 'Value 0:1');
|
||||
assert.strictEqual(grid.cell(0, 'compound1-nested1-myData9').element.innerHTML, 'Value 0:9');
|
||||
assert.strictEqual(grid.cell(0, 'compound2-nested2-myData5').element.innerHTML, 'Value 0:5');
|
||||
assert.strictEqual(grid.cell(0, 'compound2-nested2-myData8').element.innerHTML, 'Value 0:8');
|
||||
assert.strictEqual(grid.cell(11, 'compound1-nested1-myData1').element.innerHTML, 'Value 11:1');
|
||||
assert.strictEqual(grid.cell(11, 'compound1-nested1-myData9').element.innerHTML, 'Value 11:9');
|
||||
assert.strictEqual(grid.cell(11, 'compound2-nested2-myData5').element.innerHTML, 'Value 11:5');
|
||||
assert.strictEqual(grid.cell(11, 'compound2-nested2-myData8').element.innerHTML, 'Value 11:8');
|
||||
});
|
||||
|
||||
test.test('grid with nested children and ids hiding all headers', function () {
|
||||
createGrid([
|
||||
{ field: 'data0', label: 'Data 0' },
|
||||
{
|
||||
label: 'Compound 1',
|
||||
id: 'compound1',
|
||||
children: [
|
||||
{
|
||||
label: 'Nested Compound 1',
|
||||
id: 'nested1',
|
||||
children: [
|
||||
{ field: 'data1', label: 'Data 1', id: 'myData1' },
|
||||
{ field: 'data9', label: 'Data 9', id: 'myData9' }
|
||||
]
|
||||
},
|
||||
{ field: 'data2', label: 'Data 2', id: 'myData2' }
|
||||
]
|
||||
},
|
||||
{ field: 'data3', label: 'Data 3' },
|
||||
{
|
||||
label: 'Compound 2',
|
||||
id: 'compound2',
|
||||
children: [
|
||||
{ field: 'data4', label: 'Data 4', id: 'myData4' },
|
||||
{
|
||||
label: 'Nested Compound 2',
|
||||
id: 'nested2',
|
||||
children: [
|
||||
{ field: 'data5', label: 'Data 5', id: 'myData5' },
|
||||
{ field: 'data8', label: 'Data 8', id: 'myData8' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
], true);
|
||||
|
||||
assert.strictEqual(grid.cell(0, 'myData1').element.innerHTML, 'Value 0:1');
|
||||
assert.strictEqual(grid.cell(0, 'myData2').element.innerHTML, 'Value 0:2');
|
||||
assert.strictEqual(grid.cell(0, 'myData9').element.innerHTML, 'Value 0:9');
|
||||
assert.strictEqual(grid.cell(0, 'myData4').element.innerHTML, 'Value 0:4');
|
||||
assert.strictEqual(grid.cell(0, 'myData5').element.innerHTML, 'Value 0:5');
|
||||
assert.strictEqual(grid.cell(0, 'myData8').element.innerHTML, 'Value 0:8');
|
||||
assert.strictEqual(grid.cell(11, 'myData1').element.innerHTML, 'Value 11:1');
|
||||
assert.strictEqual(grid.cell(11, 'myData2').element.innerHTML, 'Value 11:2');
|
||||
assert.strictEqual(grid.cell(11, 'myData9').element.innerHTML, 'Value 11:9');
|
||||
assert.strictEqual(grid.cell(11, 'myData4').element.innerHTML, 'Value 11:4');
|
||||
assert.strictEqual(grid.cell(11, 'myData5').element.innerHTML, 'Value 11:5');
|
||||
assert.strictEqual(grid.cell(11, 'myData8').element.innerHTML, 'Value 11:8');
|
||||
|
||||
assert.strictEqual(grid.cell(0, 'nested1-myData1').element.innerHTML, 'Value 0:1');
|
||||
assert.strictEqual(grid.cell(0, 'nested1-myData9').element.innerHTML, 'Value 0:9');
|
||||
assert.strictEqual(grid.cell(0, 'nested2-myData5').element.innerHTML, 'Value 0:5');
|
||||
assert.strictEqual(grid.cell(0, 'nested2-myData8').element.innerHTML, 'Value 0:8');
|
||||
assert.strictEqual(grid.cell(11, 'nested1-myData1').element.innerHTML, 'Value 11:1');
|
||||
assert.strictEqual(grid.cell(11, 'nested1-myData9').element.innerHTML, 'Value 11:9');
|
||||
assert.strictEqual(grid.cell(11, 'nested2-myData5').element.innerHTML, 'Value 11:5');
|
||||
assert.strictEqual(grid.cell(11, 'nested2-myData8').element.innerHTML, 'Value 11:8');
|
||||
|
||||
assert.strictEqual(grid.cell(0, 'compound1-nested1-myData1').element.innerHTML, 'Value 0:1');
|
||||
assert.strictEqual(grid.cell(0, 'compound1-nested1-myData9').element.innerHTML, 'Value 0:9');
|
||||
assert.strictEqual(grid.cell(0, 'compound2-nested2-myData5').element.innerHTML, 'Value 0:5');
|
||||
assert.strictEqual(grid.cell(0, 'compound2-nested2-myData8').element.innerHTML, 'Value 0:8');
|
||||
assert.strictEqual(grid.cell(11, 'compound1-nested1-myData1').element.innerHTML, 'Value 11:1');
|
||||
assert.strictEqual(grid.cell(11, 'compound1-nested1-myData9').element.innerHTML, 'Value 11:9');
|
||||
assert.strictEqual(grid.cell(11, 'compound2-nested2-myData5').element.innerHTML, 'Value 11:5');
|
||||
assert.strictEqual(grid.cell(11, 'compound2-nested2-myData8').element.innerHTML, 'Value 11:8');
|
||||
});
|
||||
|
||||
test.test('grid with nested children and ids hiding child headers', function () {
|
||||
createGrid([
|
||||
{ field: 'data0', label: 'Data 0' },
|
||||
{
|
||||
label: 'Compound 1',
|
||||
id: 'compound1',
|
||||
children: [
|
||||
{
|
||||
label: 'Nested Compound 1',
|
||||
id: 'nested1',
|
||||
showChildHeaders: false,
|
||||
children: [
|
||||
{ field: 'data1', label: 'Data 1', id: 'myData1' },
|
||||
{ field: 'data9', label: 'Data 9', id: 'myData9' }
|
||||
]
|
||||
},
|
||||
{ field: 'data2', label: 'Data 2', id: 'myData2' }
|
||||
]
|
||||
},
|
||||
{ field: 'data3', label: 'Data 3' },
|
||||
{
|
||||
label: 'Compound 2',
|
||||
id: 'compound2',
|
||||
children: [
|
||||
{ field: 'data4', label: 'Data 4', id: 'myData4' },
|
||||
{
|
||||
label: 'Nested Compound 2',
|
||||
id: 'nested2',
|
||||
showChildHeaders: false,
|
||||
children: [
|
||||
{ field: 'data5', label: 'Data 5', id: 'myData5' },
|
||||
{ field: 'data8', label: 'Data 8', id: 'myData8' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
assert.strictEqual(grid.cell(0, 'myData1').element.innerHTML, 'Value 0:1');
|
||||
assert.strictEqual(grid.cell(0, 'myData2').element.innerHTML, 'Value 0:2');
|
||||
assert.strictEqual(grid.cell(0, 'myData9').element.innerHTML, 'Value 0:9');
|
||||
assert.strictEqual(grid.cell(0, 'myData4').element.innerHTML, 'Value 0:4');
|
||||
assert.strictEqual(grid.cell(0, 'myData5').element.innerHTML, 'Value 0:5');
|
||||
assert.strictEqual(grid.cell(0, 'myData8').element.innerHTML, 'Value 0:8');
|
||||
assert.strictEqual(grid.cell(11, 'myData1').element.innerHTML, 'Value 11:1');
|
||||
assert.strictEqual(grid.cell(11, 'myData2').element.innerHTML, 'Value 11:2');
|
||||
assert.strictEqual(grid.cell(11, 'myData9').element.innerHTML, 'Value 11:9');
|
||||
assert.strictEqual(grid.cell(11, 'myData4').element.innerHTML, 'Value 11:4');
|
||||
assert.strictEqual(grid.cell(11, 'myData5').element.innerHTML, 'Value 11:5');
|
||||
assert.strictEqual(grid.cell(11, 'myData8').element.innerHTML, 'Value 11:8');
|
||||
|
||||
assert.strictEqual(grid.cell(0, 'nested1-myData1').element.innerHTML, 'Value 0:1');
|
||||
assert.strictEqual(grid.cell(0, 'nested1-myData9').element.innerHTML, 'Value 0:9');
|
||||
assert.strictEqual(grid.cell(0, 'nested2-myData5').element.innerHTML, 'Value 0:5');
|
||||
assert.strictEqual(grid.cell(0, 'nested2-myData8').element.innerHTML, 'Value 0:8');
|
||||
assert.strictEqual(grid.cell(11, 'nested1-myData1').element.innerHTML, 'Value 11:1');
|
||||
assert.strictEqual(grid.cell(11, 'nested1-myData9').element.innerHTML, 'Value 11:9');
|
||||
assert.strictEqual(grid.cell(11, 'nested2-myData5').element.innerHTML, 'Value 11:5');
|
||||
assert.strictEqual(grid.cell(11, 'nested2-myData8').element.innerHTML, 'Value 11:8');
|
||||
|
||||
assert.strictEqual(grid.cell(0, 'compound1-nested1-myData1').element.innerHTML, 'Value 0:1');
|
||||
assert.strictEqual(grid.cell(0, 'compound1-nested1-myData9').element.innerHTML, 'Value 0:9');
|
||||
assert.strictEqual(grid.cell(0, 'compound2-nested2-myData5').element.innerHTML, 'Value 0:5');
|
||||
assert.strictEqual(grid.cell(0, 'compound2-nested2-myData8').element.innerHTML, 'Value 0:8');
|
||||
assert.strictEqual(grid.cell(11, 'compound1-nested1-myData1').element.innerHTML, 'Value 11:1');
|
||||
assert.strictEqual(grid.cell(11, 'compound1-nested1-myData9').element.innerHTML, 'Value 11:9');
|
||||
assert.strictEqual(grid.cell(11, 'compound2-nested2-myData5').element.innerHTML, 'Value 11:5');
|
||||
assert.strictEqual(grid.cell(11, 'compound2-nested2-myData8').element.innerHTML, 'Value 11:8');
|
||||
});
|
||||
});
|
||||
|
||||
test.suite('column method', function () {
|
||||
test.afterEach(function () {
|
||||
grid.destroy();
|
||||
});
|
||||
|
||||
test.test('simple grid', function () {
|
||||
createGrid({
|
||||
data0: 'Data 0',
|
||||
data1: 'Data 1',
|
||||
data2: 'Data 2',
|
||||
data3: 'Data 3',
|
||||
data4: 'Data 4'
|
||||
}, true);
|
||||
|
||||
assert.strictEqual(grid.column(0).label, 'Data 0');
|
||||
assert.strictEqual(grid.column(4).label, 'Data 4');
|
||||
assert.isUndefined(grid.column(5));
|
||||
});
|
||||
|
||||
test.test('simple grid with column ids', function () {
|
||||
createGrid({
|
||||
data0: { label: 'Data 0', id: 'myData0' },
|
||||
data1: { label: 'Data 1', id: 'myData1' },
|
||||
data2: { label: 'Data 2', id: 'myData2' },
|
||||
data3: { label: 'Data 3', id: 'myData3' },
|
||||
data4: { label: 'Data 4', id: 'myData4' }
|
||||
}, true);
|
||||
|
||||
assert.strictEqual(grid.column('myData0').label, 'Data 0');
|
||||
assert.strictEqual(grid.column('myData4').label, 'Data 4');
|
||||
assert.isUndefined(grid.column('myData5'));
|
||||
assert.isUndefined(grid.column(0));
|
||||
});
|
||||
|
||||
test.test('grid with children', function () {
|
||||
createGrid([
|
||||
{ field: 'data0', label: 'Data 0' },
|
||||
{
|
||||
label: 'Compound 1',
|
||||
children: [
|
||||
{ field: 'data1', label: 'Data 1' },
|
||||
{ field: 'data2', label: 'Data 2' }
|
||||
]
|
||||
},
|
||||
{ field: 'data3', label: 'Data 3' },
|
||||
{
|
||||
label: 'Compound 2',
|
||||
children: [
|
||||
{ field: 'data4', label: 'Data 4' },
|
||||
{ field: 'data5', label: 'Data 5' }
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
assert.strictEqual(grid.column(0).label, 'Data 0');
|
||||
assert.strictEqual(grid.column(1).label, 'Data 1');
|
||||
assert.strictEqual(grid.column(2).label, 'Data 2');
|
||||
assert.strictEqual(grid.column(5).label, 'Data 5');
|
||||
assert.isUndefined(grid.column(6));
|
||||
});
|
||||
|
||||
test.test('grid with children and children ids', function () {
|
||||
createGrid([
|
||||
{ field: 'data0', label: 'Data 0' },
|
||||
{
|
||||
label: 'Compound 1',
|
||||
children: [
|
||||
{ field: 'data1', label: 'Data 1', id: 'myData1' },
|
||||
{ field: 'data2', label: 'Data 2', id: 'myData2' }
|
||||
]
|
||||
},
|
||||
{ field: 'data3', label: 'Data 3' },
|
||||
{
|
||||
label: 'Compound 2',
|
||||
children: [
|
||||
{ field: 'data4', label: 'Data 4', id: 'myData4' },
|
||||
{ field: 'data5', label: 'Data 5', id: 'myData5' }
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
assert.strictEqual(grid.column(0).label, 'Data 0');
|
||||
assert.strictEqual(grid.column(3).label, 'Data 3');
|
||||
assert.strictEqual(grid.column('myData1').label, 'Data 1');
|
||||
assert.strictEqual(grid.column('myData2').label, 'Data 2');
|
||||
assert.strictEqual(grid.column('myData5').label, 'Data 5');
|
||||
|
||||
assert.strictEqual(grid.column('0-1-myData1').label, 'Data 1');
|
||||
assert.strictEqual(grid.column('0-1-myData2').label, 'Data 2');
|
||||
assert.strictEqual(grid.column('0-4-myData5').label, 'Data 5');
|
||||
|
||||
assert.strictEqual(grid.column('1-myData1').label, 'Data 1');
|
||||
assert.strictEqual(grid.column('1-myData2').label, 'Data 2');
|
||||
assert.strictEqual(grid.column('4-myData5').label, 'Data 5');
|
||||
});
|
||||
|
||||
test.test('grid with children and ids', function () {
|
||||
createGrid([
|
||||
{ field: 'data0', label: 'Data 0' },
|
||||
{
|
||||
label: 'Compound 1',
|
||||
id: 'compound1',
|
||||
children: [
|
||||
{ field: 'data1', label: 'Data 1', id: 'myData1' },
|
||||
{ field: 'data2', label: 'Data 2', id: 'myData2' }
|
||||
]
|
||||
},
|
||||
{ field: 'data3', label: 'Data 3' },
|
||||
{
|
||||
label: 'Compound 2',
|
||||
id: 'compound2',
|
||||
children: [
|
||||
{ field: 'data4', label: 'Data 4', id: 'myData4' },
|
||||
{ field: 'data5', label: 'Data 5', id: 'myData5' }
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
assert.strictEqual(grid.column(0).label, 'Data 0');
|
||||
assert.strictEqual(grid.column(3).label, 'Data 3');
|
||||
assert.strictEqual(grid.column('myData1').label, 'Data 1');
|
||||
assert.strictEqual(grid.column('myData2').label, 'Data 2');
|
||||
assert.strictEqual(grid.column('myData5').label, 'Data 5');
|
||||
|
||||
assert.strictEqual(grid.column('compound1-myData1').label, 'Data 1');
|
||||
assert.strictEqual(grid.column('compound1-myData2').label, 'Data 2');
|
||||
assert.strictEqual(grid.column('compound2-myData5').label, 'Data 5');
|
||||
});
|
||||
|
||||
test.test('grid with nested children and ids', function () {
|
||||
createGrid([
|
||||
{ field: 'data0', label: 'Data 0' },
|
||||
{
|
||||
label: 'Compound 1',
|
||||
id: 'compound1',
|
||||
children: [
|
||||
{
|
||||
label: 'Nested Compound 1',
|
||||
id: 'nested1',
|
||||
children: [
|
||||
{ field: 'data1', label: 'Data 1', id: 'myData1' },
|
||||
{ field: 'data9', label: 'Data 9', id: 'myData9' }
|
||||
]
|
||||
},
|
||||
{ field: 'data2', label: 'Data 2', id: 'myData2' }
|
||||
]
|
||||
},
|
||||
{ field: 'data3', label: 'Data 3' },
|
||||
{
|
||||
label: 'Compound 2',
|
||||
id: 'compound2',
|
||||
children: [
|
||||
{ field: 'data4', label: 'Data 4', id: 'myData4' },
|
||||
{
|
||||
label: 'Nested Compound 2',
|
||||
id: 'nested2',
|
||||
children: [
|
||||
{ field: 'data5', label: 'Data 5', id: 'myData5' },
|
||||
{ field: 'data8', label: 'Data 8', id: 'myData8' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
assert.strictEqual(grid.column('myData1').label, 'Data 1');
|
||||
assert.strictEqual(grid.column('myData2').label, 'Data 2');
|
||||
assert.strictEqual(grid.column('myData9').label, 'Data 9');
|
||||
assert.strictEqual(grid.column('myData4').label, 'Data 4');
|
||||
assert.strictEqual(grid.column('myData5').label, 'Data 5');
|
||||
assert.strictEqual(grid.column('myData8').label, 'Data 8');
|
||||
|
||||
assert.strictEqual(grid.column('nested1-myData1').label, 'Data 1');
|
||||
assert.strictEqual(grid.column('nested1-myData9').label, 'Data 9');
|
||||
assert.strictEqual(grid.column('nested2-myData5').label, 'Data 5');
|
||||
assert.strictEqual(grid.column('nested2-myData8').label, 'Data 8');
|
||||
|
||||
assert.strictEqual(grid.column('compound1-nested1-myData1').label, 'Data 1');
|
||||
assert.strictEqual(grid.column('compound1-nested1-myData9').label, 'Data 9');
|
||||
assert.strictEqual(grid.column('compound2-nested2-myData5').label, 'Data 5');
|
||||
assert.strictEqual(grid.column('compound2-nested2-myData8').label, 'Data 8');
|
||||
});
|
||||
|
||||
test.test('grid with nested children and ids hiding all headers', function () {
|
||||
createGrid([
|
||||
{ field: 'data0', label: 'Data 0' },
|
||||
{
|
||||
label: 'Compound 1',
|
||||
id: 'compound1',
|
||||
children: [
|
||||
{
|
||||
label: 'Nested Compound 1',
|
||||
id: 'nested1',
|
||||
children: [
|
||||
{ field: 'data1', label: 'Data 1', id: 'myData1' },
|
||||
{ field: 'data9', label: 'Data 9', id: 'myData9' }
|
||||
]
|
||||
},
|
||||
{ field: 'data2', label: 'Data 2', id: 'myData2' }
|
||||
]
|
||||
},
|
||||
{ field: 'data3', label: 'Data 3' },
|
||||
{
|
||||
label: 'Compound 2',
|
||||
id: 'compound2',
|
||||
children: [
|
||||
{ field: 'data4', label: 'Data 4', id: 'myData4' },
|
||||
{
|
||||
label: 'Nested Compound 2',
|
||||
id: 'nested2',
|
||||
children: [
|
||||
{ field: 'data5', label: 'Data 5', id: 'myData5' },
|
||||
{ field: 'data8', label: 'Data 8', id: 'myData8' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
], true);
|
||||
|
||||
assert.strictEqual(grid.column('myData1').label, 'Data 1');
|
||||
assert.strictEqual(grid.column('myData2').label, 'Data 2');
|
||||
assert.strictEqual(grid.column('myData9').label, 'Data 9');
|
||||
assert.strictEqual(grid.column('myData4').label, 'Data 4');
|
||||
assert.strictEqual(grid.column('myData5').label, 'Data 5');
|
||||
assert.strictEqual(grid.column('myData8').label, 'Data 8');
|
||||
|
||||
assert.strictEqual(grid.column('nested1-myData1').label, 'Data 1');
|
||||
assert.strictEqual(grid.column('nested1-myData9').label, 'Data 9');
|
||||
assert.strictEqual(grid.column('nested2-myData5').label, 'Data 5');
|
||||
assert.strictEqual(grid.column('nested2-myData8').label, 'Data 8');
|
||||
|
||||
assert.strictEqual(grid.column('compound1-nested1-myData1').label, 'Data 1');
|
||||
assert.strictEqual(grid.column('compound1-nested1-myData9').label, 'Data 9');
|
||||
assert.strictEqual(grid.column('compound2-nested2-myData5').label, 'Data 5');
|
||||
assert.strictEqual(grid.column('compound2-nested2-myData8').label, 'Data 8');
|
||||
});
|
||||
|
||||
test.test('grid with nested children and ids hiding child headers', function () {
|
||||
createGrid([
|
||||
{ field: 'data0', label: 'Data 0' },
|
||||
{
|
||||
label: 'Compound 1',
|
||||
id: 'compound1',
|
||||
children: [
|
||||
{
|
||||
label: 'Nested Compound 1',
|
||||
id: 'nested1',
|
||||
showChildHeaders: false,
|
||||
children: [
|
||||
{ field: 'data1', label: 'Data 1', id: 'myData1' },
|
||||
{ field: 'data9', label: 'Data 9', id: 'myData9' }
|
||||
]
|
||||
},
|
||||
{ field: 'data2', label: 'Data 2', id: 'myData2' }
|
||||
]
|
||||
},
|
||||
{ field: 'data3', label: 'Data 3' },
|
||||
{
|
||||
label: 'Compound 2',
|
||||
id: 'compound2',
|
||||
children: [
|
||||
{ field: 'data4', label: 'Data 4', id: 'myData4' },
|
||||
{
|
||||
label: 'Nested Compound 2',
|
||||
id: 'nested2',
|
||||
showChildHeaders: false,
|
||||
children: [
|
||||
{ field: 'data5', label: 'Data 5', id: 'myData5' },
|
||||
{ field: 'data8', label: 'Data 8', id: 'myData8' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
assert.strictEqual(grid.column('myData1').label, 'Data 1');
|
||||
assert.strictEqual(grid.column('myData2').label, 'Data 2');
|
||||
assert.strictEqual(grid.column('myData9').label, 'Data 9');
|
||||
assert.strictEqual(grid.column('myData4').label, 'Data 4');
|
||||
assert.strictEqual(grid.column('myData5').label, 'Data 5');
|
||||
assert.strictEqual(grid.column('myData8').label, 'Data 8');
|
||||
|
||||
assert.strictEqual(grid.column('nested1-myData1').label, 'Data 1');
|
||||
assert.strictEqual(grid.column('nested1-myData9').label, 'Data 9');
|
||||
assert.strictEqual(grid.column('nested2-myData5').label, 'Data 5');
|
||||
assert.strictEqual(grid.column('nested2-myData8').label, 'Data 8');
|
||||
|
||||
assert.strictEqual(grid.column('compound1-nested1-myData1').label, 'Data 1');
|
||||
assert.strictEqual(grid.column('compound1-nested1-myData9').label, 'Data 9');
|
||||
assert.strictEqual(grid.column('compound2-nested2-myData5').label, 'Data 5');
|
||||
assert.strictEqual(grid.column('compound2-nested2-myData8').label, 'Data 8');
|
||||
});
|
||||
});
|
||||
|
||||
test.suite('sort method', function () {
|
||||
test.afterEach(function () {
|
||||
grid.destroy();
|
||||
});
|
||||
|
||||
test.test('sort grid programmatically by field present in header', function () {
|
||||
createGrid({
|
||||
data0: 'Data 0',
|
||||
data1: 'Data 1',
|
||||
data2: 'Data 2',
|
||||
data3: 'Data 3',
|
||||
data4: 'Data 4'
|
||||
});
|
||||
assert.doesNotThrow(function () {
|
||||
grid.set('sort', 'data0');
|
||||
}, null, 'Sorting grid programmatically should not throw error');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,243 @@
|
||||
define([
|
||||
'intern!tdd',
|
||||
'intern/chai!assert',
|
||||
'dojo/_base/declare',
|
||||
'dojo/on',
|
||||
'dojo/query',
|
||||
'dojo/string',
|
||||
'dgrid/Grid',
|
||||
'dgrid/extensions/Pagination',
|
||||
'dgrid/test/data/createSyncStore',
|
||||
'dgrid/test/data/genericData',
|
||||
'dojo/domReady!'
|
||||
], function (test, assert, declare, on, query, string, Grid, Pagination, createSyncStore, genericData) {
|
||||
var grid,
|
||||
PaginationGrid = declare([Grid, Pagination]);
|
||||
|
||||
function getColumns() {
|
||||
return {
|
||||
id: 'id',
|
||||
col1: 'Column 1',
|
||||
col2: 'Column 2',
|
||||
col5: 'Column 5'
|
||||
};
|
||||
}
|
||||
|
||||
function createTestStore() {
|
||||
return createSyncStore({ data: genericData });
|
||||
}
|
||||
|
||||
test.suite('Pagination', function () {
|
||||
test.beforeEach(function () {
|
||||
grid = new PaginationGrid({
|
||||
collection: createTestStore(),
|
||||
columns: getColumns()
|
||||
});
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
});
|
||||
|
||||
test.afterEach(function () {
|
||||
grid.destroy();
|
||||
});
|
||||
|
||||
test.test('Pagination info updates on page switch', function () {
|
||||
// switch pages and ensure that the status message and links are
|
||||
// updated
|
||||
var disabledLinks = query('span.dgrid-page-disabled', grid.paginationLinksNode),
|
||||
expectedText = string.substitute(grid.i18nPagination.status,
|
||||
{ start: 1, end: 10, total: 100 });
|
||||
|
||||
function testAssertions(expectedPage) {
|
||||
assert.strictEqual(grid.paginationStatusNode.innerHTML, expectedText,
|
||||
'should find expected status message; received \'' + status + '\'');
|
||||
assert.strictEqual(disabledLinks.length, 1,
|
||||
'should find expected number of disabled page links: found ' +
|
||||
disabledLinks.length);
|
||||
assert.strictEqual(string.trim(disabledLinks[0].innerHTML), expectedPage,
|
||||
'link for active page (' + expectedPage + ') should be disabled');
|
||||
for (var i = 0; i < disabledLinks.length; i++) {
|
||||
assert.equal(disabledLinks[i].tabIndex, -1, 'disabled link should have -1 tabIndex');
|
||||
}
|
||||
}
|
||||
|
||||
testAssertions('1');
|
||||
|
||||
grid.gotoPage(2);
|
||||
disabledLinks = query('span.dgrid-page-disabled', grid.paginationLinksNode);
|
||||
expectedText = string.substitute(grid.i18nPagination.status, {start: 11, end: 20, total: 100});
|
||||
|
||||
testAssertions('2');
|
||||
});
|
||||
|
||||
test.test('Pagination info updates when an item is added/removed', function () {
|
||||
function testAssertions(expectedTotal, expectedLastPage) {
|
||||
assert.strictEqual(grid.paginationStatusNode.innerHTML,
|
||||
string.substitute(grid.i18nPagination.status, {
|
||||
start: 1,
|
||||
end: 10,
|
||||
total: expectedTotal
|
||||
}),
|
||||
'total displayed in status area should be ' + expectedTotal
|
||||
);
|
||||
assert.strictEqual(grid.paginationLinksNode.lastChild.innerHTML, '' + expectedLastPage,
|
||||
'last page number displayed should be ' + expectedLastPage);
|
||||
}
|
||||
|
||||
testAssertions(100, 10);
|
||||
|
||||
grid.collection.addSync({ id: 100 });
|
||||
testAssertions(101, 11);
|
||||
|
||||
grid.collection.removeSync(100);
|
||||
testAssertions(100, 10);
|
||||
});
|
||||
});
|
||||
|
||||
test.suite('Pagination size selector initialization tests', function () {
|
||||
// Each test in this suite is responsible for instantiating the grid
|
||||
test.afterEach(function () {
|
||||
grid.destroy();
|
||||
});
|
||||
|
||||
test.test('pageSizeOptions + unique rowsPerPage during creation', function () {
|
||||
grid = new PaginationGrid({
|
||||
collection: createTestStore(),
|
||||
columns: getColumns(),
|
||||
// Purposely set pageSizeOptions out of order to test setter
|
||||
pageSizeOptions: [25, 15, 5],
|
||||
// Purposely set rowsPerPage to a value not in pageSizeOptions
|
||||
rowsPerPage: 10
|
||||
});
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
|
||||
assert.strictEqual(grid.paginationSizeSelect.tagName, 'SELECT',
|
||||
'paginationSizeSelect should reference a SELECT element');
|
||||
assert.lengthOf(grid.pageSizeOptions, 4,
|
||||
'pageSizeOptions should have additional item for unique rowsPerPage');
|
||||
assert.strictEqual(grid.pageSizeOptions[0], 5,
|
||||
'pageSizeOptions should be sorted ascending');
|
||||
|
||||
// Now empty pageSizeOptions and confirm that the select was removed
|
||||
grid.set('pageSizeOptions', null);
|
||||
assert.isNull(grid.paginationSizeSelect,
|
||||
'paginationSizeSelect reference should be cleared after setting empty pageSizeOptions');
|
||||
assert.strictEqual(query('select', grid.footerNode).length, 0,
|
||||
'paginationSizeSelect node should have been destroyed');
|
||||
});
|
||||
|
||||
test.test('pageSizeOptions added after creation', function () {
|
||||
grid = new PaginationGrid({
|
||||
collection: createTestStore(),
|
||||
columns: getColumns(),
|
||||
rowsPerPage: 10
|
||||
});
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
|
||||
assert.isUndefined(grid.paginationSizeSelect,
|
||||
'paginationSizeSelect should not exist yet (no options)');
|
||||
|
||||
// Now add pageSizeOptions (purposely out of order) and confirm it
|
||||
// is properly added
|
||||
grid.set('pageSizeOptions', [25, 15, 5]);
|
||||
|
||||
assert.strictEqual(grid.paginationSizeSelect.tagName, 'SELECT',
|
||||
'paginationSizeSelect should reference a SELECT element');
|
||||
assert.lengthOf(grid.pageSizeOptions, 4,
|
||||
'pageSizeOptions should have additional item for unique rowsPerPage');
|
||||
assert.strictEqual(grid.pageSizeOptions[0], 5,
|
||||
'pageSizeOptions should be sorted ascending');
|
||||
});
|
||||
});
|
||||
|
||||
test.suite('Pagination size selector', function () {
|
||||
test.before(function () {
|
||||
grid = new PaginationGrid({
|
||||
collection: createTestStore(),
|
||||
columns: getColumns(),
|
||||
pageSizeOptions: [5, 10, 15]
|
||||
});
|
||||
document.body.appendChild(grid.domNode);
|
||||
grid.startup();
|
||||
});
|
||||
test.after(function () {
|
||||
grid.destroy();
|
||||
});
|
||||
|
||||
function verifyOptions(options, expectedCount) {
|
||||
// verify that the values of the given set of options are in increasing order
|
||||
// optionally verify that there are the expected number of options
|
||||
var opt,
|
||||
lastVal = options[0].value;
|
||||
for (var i = 1; i < options.length; i++) {
|
||||
opt = options[i];
|
||||
assert.isTrue(+lastVal < +opt.value, 'values should be in order');
|
||||
lastVal = opt.value;
|
||||
}
|
||||
if (expectedCount !== undefined) {
|
||||
assert.lengthOf(options, expectedCount,
|
||||
'selector should have expected number of options');
|
||||
}
|
||||
}
|
||||
|
||||
function rowsPerPageTest(rowsPerPage) {
|
||||
// update the grid's rowsPerPage and ensure that the selector value
|
||||
// is correct afterwards
|
||||
var select = grid.paginationSizeSelect;
|
||||
grid.set('rowsPerPage', rowsPerPage);
|
||||
assert.strictEqual(select.value, '' + rowsPerPage,
|
||||
'size select should have expected value ' + select.value);
|
||||
verifyOptions(select.options);
|
||||
}
|
||||
|
||||
function getNonSelectedValue(options) {
|
||||
// return a value that isn't selected, assuming there are at least
|
||||
// two options and unique option values
|
||||
if (options[0].selected) {
|
||||
return options[1].value;
|
||||
} else {
|
||||
return options[0].value;
|
||||
}
|
||||
}
|
||||
|
||||
test.test('setting rowsPerPage to a low value properly updates select', function () {
|
||||
rowsPerPageTest(2);
|
||||
});
|
||||
|
||||
test.test('setting rowsPerPage properly updates select', function () {
|
||||
rowsPerPageTest(7);
|
||||
});
|
||||
|
||||
test.test('setting rowsPerPage to a high value properly updates select', function () {
|
||||
rowsPerPageTest(20);
|
||||
});
|
||||
|
||||
test.test('setting rowsPerPage to an existing value doesn\'t add a value', function () {
|
||||
var selector = grid.paginationSizeSelect,
|
||||
initialCount = selector.options.length,
|
||||
value = getNonSelectedValue(selector.options);
|
||||
grid.set('rowsPerPage', +value);
|
||||
assert.strictEqual(selector.value, value,
|
||||
'size select should have expected value ' + selector.value);
|
||||
verifyOptions(selector.options, initialCount);
|
||||
});
|
||||
|
||||
test.test('selecting a value from the selector doesn\'t change the selector options', function () {
|
||||
var selector = grid.paginationSizeSelect,
|
||||
initialCount = selector.options.length,
|
||||
targetValue = getNonSelectedValue(selector.options);
|
||||
|
||||
// TODO: this would do better as a functional test;
|
||||
// as-is, we need to emit a change event manually
|
||||
selector.value = targetValue;
|
||||
on.emit(selector, 'change', {});
|
||||
assert.strictEqual(selector.value, targetValue,
|
||||
'size select should have expected value ' + selector.value);
|
||||
assert.strictEqual(+targetValue, grid.rowsPerPage,
|
||||
'rowsPerPage should have numeric value equivalent to the selected value');
|
||||
verifyOptions(selector.options, initialCount);
|
||||
});
|
||||
});
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user