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