Compare commits

...

374 Commits

Author SHA1 Message Date
Kazuki-Nakanishi
3b3d696e45 Add the node setting tlsConfigDisableLocalFiles for tls node. (#1190)
* Add the node setting tlsConfigDisableLocalFiles for tls node.

* Fix the bug that shows node setting when specified in settings.js and exportable is false.
2017-03-09 19:58:34 +00:00
Kazuki-Nakanishi
34089aec70 Allow a node to declare what settings should be made available to the editor. (#1185)
* Implement register/exportNodeSettings.

* Change normaliseRegisterTypeName to normaliseNodeTypeName. Force it to name in a camel case.
2017-03-08 14:38:33 +00:00
Nick O'Leary
fca77a868f Allow a node to declare settings that should be exported 2017-03-01 15:01:07 +00:00
Nick O'Leary
4794fe495c Add events to test helper 2017-02-15 23:15:24 +00:00
Nick O'Leary
869fdbcc6a Remove event passing for icons/examples from the api layer 2017-02-15 23:07:50 +00:00
Dave Conway-Jones
702e6d3b51 slight filed size adjust for mqtt broker port field - allow 5 digits 2017-02-14 20:59:52 +00:00
Nick O'Leary
5f1e37b7fa Leave a node to nls its own port labels 2017-02-10 22:10:53 +00:00
Nick O'Leary
ec0209b175 Allow a node to override default labels 2017-02-09 23:24:16 +00:00
Nick O'Leary
a17dcbde0f Remove console log from Switch node 2017-02-08 20:43:26 +00:00
Nick O'Leary
fbd159a23a Add placeholder text on label inputs and clear buttons 2017-02-08 10:48:26 +00:00
Nick O'Leary
599a6bf050 Add port labels to Subflow nodes 2017-02-08 10:48:25 +00:00
Nick O'Leary
185b16a858 Keep port label form in sync with output reordering 2017-02-08 10:48:25 +00:00
Nick O'Leary
e7e3ed4923 Basic node label editor 2017-02-08 10:48:25 +00:00
Nick O'Leary
47df5476ba Add RED.stack as a common ui component 2017-02-08 10:48:25 +00:00
Nick O'Leary
d7c516ab00 Port label editor starting point 2017-02-08 10:48:24 +00:00
Dave Conway-Jones
50838970ec let css node handle ip addresses without trying to parse
and only warn once if no template (and then send object anyway)
to close #1142
2017-02-07 21:14:16 +00:00
Dave Conway-Jones
1d15ee7034 let Hypriot on Pi detect gpio correctly
clean up duplicate labels
2017-02-07 21:14:16 +00:00
Dave Conway-Jones
7029541b4f Let watch node recurse into subdirectories
to close #1140
2017-02-07 21:14:16 +00:00
Dave Conway-Jones
ada8e447cc exec node can be killed on demand 2017-02-07 21:14:16 +00:00
Dave Conway-Jones
1841fc18fa let trigger node set repeated outputs 2017-02-07 21:14:16 +00:00
Nick O'Leary
f2235dacdc Shuffle promises for creating default package.json 2017-01-28 14:21:22 +00:00
Nick O'Leary
50017c28da Allow port labels be i18n identifiers 2017-01-27 22:36:00 +00:00
Nick O'Leary
85b2a03a42 Create a package.json file in userDir if one doesn't exist 2017-01-27 22:35:17 +00:00
Nick O'Leary
829087550d Add inputLabels and outputLabels to node defn + Update Change node 2017-01-27 18:11:25 +00:00
Nick O'Leary
dd6f71fe85 Resize port labels based on content 2017-01-27 16:33:11 +00:00
Nick O'Leary
92a928680c Initial port label behaviour 2017-01-26 15:38:25 +00:00
Nick O'Leary
d008b1970c Add option to parse Template result as JSON before sending 2017-01-25 17:12:53 +00:00
Nick O'Leary
4affbb8c6b Numeric validator that accepts blank should accept undefined 2017-01-25 16:11:56 +00:00
Nick O'Leary
ddb2ea4b5f autoInstallModules option must honour version/pending_version 2017-01-25 11:07:02 +00:00
Nick O'Leary
a69683183f Refuse to update a non-local node module 2017-01-24 22:50:40 +00:00
Nick O'Leary
8d34f87667 Add websocketVerifyClient option to enable custom websocket auth
Fixes #1127
2017-01-24 21:37:08 +00:00
Nick O'Leary
128c4fe222 Add visual cue as to whether the workspace is focused 2017-01-24 16:14:03 +00:00
Nick O'Leary
b10141d71f Allow statusCode/headers to be set directly within HTTP Response node 2017-01-24 14:56:48 +00:00
Nick O'Leary
68e0b35364 Allow RED.validators.number to allow blank values as valid 2017-01-24 14:28:15 +00:00
Nick O'Leary
e27f5d0460 Add node module update api and expose in palette editor 2017-01-21 23:46:44 +00:00
Nick O'Leary
0720128bd4 Support dropping json files into the editor 2017-01-19 15:34:14 +00:00
Nick O'Leary
b8888a5d46 Add RED.utils.getNodeLabel utility function 2017-01-18 15:52:09 +00:00
Nick O'Leary
0857f979ff Update ui_spec for icon module path 2017-01-18 13:14:12 +00:00
Nick O'Leary
11f4ae019c Include module name in requests for node icons 2017-01-18 13:06:22 +00:00
Nick O'Leary
64daaeb310 Add file upload support to HTTP In node 2017-01-16 22:39:30 +00:00
Nick O'Leary
0646b0060e Display buffer data properly for truncated buffers under Object property 2017-01-16 17:43:39 +00:00
Nick O'Leary
c794ca85fd Update changelog for 0.16.1 2017-01-16 10:30:36 +00:00
Nick O'Leary
5b4019dd3d Add colour swatches to debug when hex colour matched 2017-01-16 10:29:00 +00:00
Nick O'Leary
a03ccd7b59 Nodes with hasUsers set to false should not appear unused 2017-01-15 13:37:21 +00:00
Nick O'Leary
4b64aad5ce Change hard error to verbose warning if using old node.js level 2017-01-14 23:57:39 +00:00
Nick O'Leary
d146ff8794 Update debug_spec test for Error messages 2017-01-14 21:47:18 +00:00
Nick O'Leary
5349bf7628 Don't filter debug properties starting with _
Fixes #1117
2017-01-14 21:34:09 +00:00
Nick O'Leary
a79e4d1bb3 Node logged errors not displayed properly in debug pane
Fixes #1116
2017-01-14 21:33:11 +00:00
Nick O'Leary
f462435dc2 Do not look for existing nodes when checking for wires on paste
Fixes #1114
2017-01-13 14:16:12 +00:00
Nick O'Leary
48ad614441 -v option not enabling verbose mode properly 2017-01-13 00:01:19 +00:00
Nick O'Leary
f699516fdb Add node.js version check on startup 2017-01-12 10:40:04 +00:00
Nick O'Leary
ca5cbb640a Bump version 0.16 2017-01-11 20:44:53 +00:00
Nick O'Leary
0a96259ddf Update copyright header for JS Foundation 2017-01-11 15:24:33 +00:00
Nick O'Leary
d99b9c04e4 Update changelog 2017-01-11 14:34:59 +00:00
Nick O'Leary
64d261e053 Add deploy action 2017-01-11 14:33:40 +00:00
Nick O'Leary
eb027d98aa Add column headings to keymap table 2017-01-11 14:15:29 +00:00
Nick O'Leary
a95727b654 Scope input/export actions to be global 2017-01-11 14:15:14 +00:00
Nick O'Leary
4e636d7eec Fix arg passing lint error 2017-01-11 12:18:52 +00:00
Nick O'Leary
3cd53f617a Include unassigned keys to shortcut dialog 2017-01-11 11:41:25 +00:00
Nick O'Leary
b1684e82d8 Dynamically generate keyboard shortcut help dialog 2017-01-11 11:35:48 +00:00
Dave Conway-Jones
a55027b838 let copy of settings file occur on a clean install. 2017-01-11 10:12:29 +00:00
Nick O'Leary
28678acf74 Add debug logging around flow revision ids 2017-01-10 14:20:51 +00:00
Nick O'Leary
ce6594c8cc Do not tie debug src loading to needsPermission
Fixes #1111
2017-01-10 09:43:46 +00:00
Nick O'Leary
75855d5450 Initialise nodeApp regardless of httpAdmin setting
Closes #1096 #1095
2017-01-09 22:22:49 +00:00
Nick O'Leary
f248699a30 Display info tips slightly longer 2017-01-09 22:09:06 +00:00
Nick O'Leary
29594726ca Speed up reveal of search dialogs 2017-01-09 22:08:54 +00:00
Nick O'Leary
0a41b07297 Reorder Debug/Inject nodes in quick-add dialog 2017-01-09 16:41:16 +00:00
Nick O'Leary
e45cb7fac1 Ensure flows exist before delegating status/error events
Fixes #1069
2017-01-09 16:39:41 +00:00
Nick O'Leary
489dbfc72a Update package dependencies 2017-01-09 15:01:33 +00:00
Nick O'Leary
a89ae7d77a Update MQTT to latest 2.2.1 2017-01-09 14:35:45 +00:00
Nick O'Leary
a1eeff4034 Node status not being refreshed properly in the editor 2017-01-09 14:18:59 +00:00
Nick O'Leary
0e1013a570 Add install/remove dialog to increase friction
Closes #1109
2017-01-09 13:41:20 +00:00
Nick O'Leary
4562b06a60 Try to prevent auto-fill of password fields in node edit tray
Fixes #1081
2017-01-08 23:14:14 +00:00
zuhito
3c96218338 Add Japanese translation file(editor.json) (#1084) 2017-01-08 23:02:07 +00:00
Nick O'Leary
f0a4ea099c Fix whitespace in localfilesystem 2017-01-08 23:01:28 +00:00
btsimonh
c8d6693fba fix bug where savesettings did not honor local settings variables (#1073)
* fix bug where savesettings did not honor local settings variables

* don't create lib/flows on read;  It's already created in localfilesystem.init and in saveLibraryEntry -
so removed call to promiseDir, and added a return of [] if accessing a folder which did not exist.
This is important because else when settings.readOnly is true, it still creates folders.

* Fix a CI failure where path passed to getLibraryEntry is empty;
treat this case as meaning it was wanting a folder, and return empty if the folder dioes not exist

* Add a test for getLibraryEntry( type, '/' ) as called by node-red

* change newsettings to camelCase newSettings
2017-01-08 23:00:27 +00:00
Nick O'Leary
81bbdfe413 Tidy up unused/duplicate editor messages
Closes #922
2017-01-08 22:54:46 +00:00
Nick O'Leary
0e362943bf Add option to colourise debug console output
Closes #1103
2017-01-08 22:38:40 +00:00
Nick O'Leary
1e37fed90b Report node catalogue load errors
Closes #1009
2017-01-08 20:51:31 +00:00
Nick O'Leary
aafcfef387 Add property validation to nodes using typedInput 2017-01-06 23:18:50 +00:00
Nick O'Leary
4b83d8160f Add common validator for typedInput fields
Closes #1104
2017-01-06 22:20:09 +00:00
Nick O'Leary
73a41707e5 Property expressions must not be blank 2017-01-06 21:58:17 +00:00
Nick O'Leary
c989c533e8 Properly report module remove errors in palette editor
Fixes #1043
2017-01-06 16:53:54 +00:00
Nick O'Leary
707dc8c65c Update debug node console logging indicator icon
Closes #1094
2017-01-06 14:43:51 +00:00
Nick O'Leary
4c6157a06e Tidy up merge commit of validatePropertyExpression 2017-01-06 14:32:37 +00:00
Nick O'Leary
f973396821 Merge pull request #1102 from node-red/0.16
0.16
2017-01-06 14:30:52 +00:00
Nick O'Leary
e73216d4c1 Merge branch 'master' into 0.16 2017-01-06 14:30:13 +00:00
Dave Conway-Jones
e6de26736b add port if wires array > number of ports declared. 2017-01-06 14:06:30 +00:00
Nick O'Leary
d131addd63 Allow tips to be enabled/disabled via menu option 2017-01-06 13:33:23 +00:00
Nick O'Leary
0c7705beff Allow quoted property expressions
Fixes #1101
2017-01-06 11:23:53 +00:00
Dave Conway-Jones
08b11addec Let exec node (spawn) handle commands with spaces in path 2017-01-06 09:55:52 +00:00
Nick O'Leary
555f96cfaf Info-tips update 2017-01-05 23:33:19 +00:00
Nick O'Leary
59ffacb3df Fix merge conflicts 2017-01-05 10:07:23 +00:00
Nick O'Leary
83acb66f00 NLS the diff dialog 2017-01-04 22:02:35 +00:00
Nick O'Leary
1f9ae45875 Fix diff node table layout for Safari 2017-01-04 20:57:10 +00:00
Nick O'Leary
ffa628be2d Index all node properties for node search 2017-01-04 16:46:36 +00:00
Nick O'Leary
8916f6f829 Update CHANGELOG/version for 0.15.3 2017-01-04 15:11:53 +00:00
Nick O'Leary
215c8fd261 NLS type search 2017-01-01 22:14:33 +00:00
Nick O'Leary
061cc908a7 Hide common entries when filtering typeSearch 2017-01-01 21:59:09 +00:00
Nick O'Leary
18a519f9ed Remove node 0.10 from travis config 2017-01-01 11:41:03 +00:00
Nick O'Leary
7970c9dbe5 Merge changes by reimporting changed node config 2017-01-01 00:20:12 +00:00
Nick O'Leary
5ca0c066e2 Better handling of moved nodes 2017-01-01 00:20:12 +00:00
Nick O'Leary
563728c7b8 Some more merging code 2017-01-01 00:20:12 +00:00
Nick O'Leary
31a72b6562 Three-way-diff 2017-01-01 00:20:12 +00:00
Nick O'Leary
d3dfbc3034 Add proper three-way diff view 2017-01-01 00:20:11 +00:00
Josh
f143a6ba08 update welcome message to use logger so it can be turned off/on if required (#1083) 2016-12-23 11:31:23 +00:00
Dave Conway-Jones
28a65923b6 bump various package versions
(not touching mqtt and other major version)
2016-12-22 13:36:06 +00:00
Dave Conway-Jones
4ca3df77b3 Add ⇶ to debug node to indicate debugging also to console.log 2016-12-22 13:27:27 +00:00
Dave Conway-Jones
4cbe264869 Change file node to use node 4 syntax (drops support for 0.8) 2016-12-22 13:17:08 +00:00
Nick O'Leary
b6b65b6bf7 Update debug node test for circular references 2016-12-20 23:21:25 +00:00
Nick O'Leary
e7cc42a927 Use json-stringify-safe to detect circular references in debug msgs 2016-12-20 23:16:11 +00:00
Nick O'Leary
bba3ca8cc0 Avoid misinterpreting valid objects as encoded arrays in debug 2016-12-20 22:46:56 +00:00
Dave Conway-Jones
8423e2d245 add info for httprequest responseUrl property 2016-12-16 22:03:00 +00:00
Dave Conway-Jones
fc263718a1 Add res.responseUrl to httprequest node response 2016-12-16 21:54:24 +00:00
Nick O'Leary
c3a99cf5a4 Update CONTRIBUTING guide 2016-12-09 13:35:29 +00:00
Dave Conway-Jones
f6820ec615 Bump a load of packages (for 0.16 branch only)
Ready to drop node 0.10 - update ws, bcrypt, drop serial port node
2016-12-07 23:43:41 +00:00
Nick O'Leary
226ad3fe22 Add missing diff file 2016-12-07 13:51:20 +00:00
Nick O'Leary
a9b17e930c Add diff markers to tabs in diff-view 2016-12-07 13:48:30 +00:00
Nick O'Leary
932ea7ba8f Add flow diff view 2016-12-06 22:37:21 +00:00
Nick O'Leary
c720d78c39 Ensure runtime event notification gets cleared on restart 2016-12-05 14:39:34 +00:00
Nick O'Leary
8d21e441a0 Add notification when runtime stopped due to missing types
Part of #832
2016-12-05 13:24:24 +00:00
Nick O'Leary
16ecb1a9cb Overhaul keyboard handling and introduce editor actions 2016-12-04 22:59:43 +00:00
Nick O'Leary
f68acca427 Fix dynamically loading multiple node-sets from palette editor 2016-12-01 15:27:29 +00:00
Dave Conway-Jones
671d7e2beb debug - format if time if correct length/range 2016-11-28 17:28:49 +00:00
Nick O'Leary
52fc497412 Properly escape html strings passed to debug 2016-11-27 21:51:34 +00:00
Nathanaël Lécaudé
2084ad318f Tcpgetfix: Another small check (#1070)
* TCPget: Add another check for clients[connection_id]
2016-11-26 21:16:19 +00:00
Nathanaël Lécaudé
b530c1a43d TCPGet: Ensure done() is called only once (#1068)
* Add additional safety checks to avoid acting on non-existent objects

* TCPGet: yet more checks

* TCPGet: seperate connected properties

* TCPGet: properly handle node.done()
2016-11-25 18:14:51 +00:00
Nick O'Leary
f2797a4153 Fix package.json conflict 2016-11-24 20:52:48 +00:00
Nick O'Leary
659c326f89 Add jsonata snippets 2016-11-23 23:16:17 +00:00
Nick O'Leary
534b07d120 Include jsonata from dependency on build and improve func highlight 2016-11-23 23:15:30 +00:00
Nick O'Leary
de64fc8b8d Update rather than hide install button after success install 2016-11-23 10:58:38 +00:00
Nick O'Leary
1e234fcb73 Add editableList api doc comments 2016-11-23 10:58:19 +00:00
Nick O'Leary
fa9a7e725b Sort quick-add types and add most-recent used type section 2016-11-22 22:57:05 +00:00
Nick O'Leary
95b2675f03 Support query and search paths in url when opening debug sub window 2016-11-22 13:14:52 +00:00
Nick O'Leary
564902b886 Allow $ and _ at start of property identifiers
Fixes #1063
2016-11-21 21:36:18 +00:00
Nathanaël Lécaudé
071a04595a TCPGet: Separated the node.connected property for each instance (#1062)
* Add additional safety checks to avoid acting on non-existent objects

* TCPGet: yet more checks

* TCPGet: seperate connected properties
2016-11-19 16:25:54 +00:00
Nick O'Leary
eaa4b76ede Update jsonata version 2016-11-18 16:38:48 +00:00
Nicholas Humfrey
74a1713e99 Corrected 'overide' typo in XML node help (#1061)
Thanks @njh
2016-11-18 11:41:48 +00:00
Nathanaël Lécaudé
5f5aa0b2f7 TCPGet: Last property check (hopefully) (#1059)
* Add additional safety checks to avoid acting on non-existent objects

* TCPGet: yet more checks
2016-11-18 11:25:06 +00:00
Nathanaël Lécaudé
eef59fd40e Add additional safety checks to avoid acting on non-existent objects (#1057) 2016-11-17 21:04:38 +00:00
Dave Conway-Jones
361ff315e9 add --title for process name to command line options 2016-11-17 13:57:33 +00:00
Dave Conway-Jones
eeea8e530e add indicator for fire once on inject node 2016-11-17 13:56:37 +00:00
Dave Conway-Jones
8d5286703f reimplement $(env var) replace to share common code.
and add test to utils
2016-11-17 13:56:17 +00:00
Dave Conway-Jones
74f2180fa4 Fix error message for missing node html file, and add test.
To close #1053
2016-11-16 22:46:01 +00:00
Dave Conway-Jones
d042169f2e Let credentials also use $(...) substitutions from ENV
to close #1051
(and add to test)
2016-11-16 21:47:13 +00:00
Nick O'Leary
1fd87bf664 Improve debug message meta data contrast and legibility 2016-11-16 15:05:04 +00:00
Nick O'Leary
eeaff6b553 Add insert-function button to expression editor 2016-11-16 14:54:51 +00:00
Nick O'Leary
6efd048fd6 Rename insecureRedirect to requireHttps 2016-11-16 14:24:27 +00:00
Paul Slater
6e9e694f66 Add setting to cause insecure redirect (#1054)
* add support for editor insecure redirect setting

set insecureRedirect: true to cause the editor app to redirect insecure connections

* document insecureRedirect

* use req.originalUrl instead of req.url

url has the path removed, whereas originalUrl preserves the path - ie /red
2016-11-16 14:17:47 +00:00
telogis-nodered
44a0f1b505 Palette editor fixes (#1033)
* ensure remove button is only enabled for local modules when refreshing palette editor

* ensure local field is propagated to the nodes when a new module is added to the registry
2016-11-16 14:12:31 +00:00
Monkey Do
9790211891 Close comms on stopServer in test helper (#1020)
* Close comms on stopServer in test helper

Using this file in another project to test nodes, when running tests with gulp and karma the process never ends as comms are still open.
This resolves the problem.

* Moved test helper server on close to stopServer method
2016-11-16 14:09:04 +00:00
Adam Hořčica
be18cc9f2d Add support for flow and global context in Template node (#1048)
* Enable tests for flow and global context

* Add support for flow and global context in Template node

* Handle missing node context
2016-11-16 14:08:14 +00:00
Nick O'Leary
8caee09ea4 Preserve newlines in jsonata expression via tabs 2016-11-16 13:44:45 +00:00
Nick O'Leary
26f5305593 Add jsonata function help 2016-11-15 23:22:25 +00:00
Nick O'Leary
d33029027f Add expression editor for jsonata 2016-11-15 00:19:04 +00:00
Dave Conway-Jones
339aaaec57 Tcpgetfix (#1050)
* TCPget: Store incoming messages alongside the client object to keep reference
2016-11-14 20:20:27 +00:00
Dave Conway-Jones
db2425c473 Seperated info messages to their own file
auto detect size still needs work
2016-11-14 19:10:02 +00:00
Nathanaël Lécaudé
18731f6055 TCPget: Store incoming messages alongside the client object to keep reference 2016-11-14 13:30:43 -05:00
Nathanaël Lécaudé
34f1f7a31d Merge remote-tracking branch 'upstream/master' into tcpgetfix 2016-11-14 08:09:44 -05:00
Nathanaël Lécaudé
7ef153756b TCPget can now handle concurrent sessions (#1042)
* First release of multi connection tcpget

* Works when connection is left open

* Change scope of clients object

* Fix comparison to "" in tcpin

* Add security checks

* Better scope handling
2016-11-11 09:01:22 +00:00
Nick O'Leary
bf90509526 Add jsonata support to Change/Switch nodes 2016-11-10 23:58:34 +00:00
Nathanaël Lécaudé
d853eca489 Better scope handling 2016-11-10 17:35:44 -05:00
Nathanaël Lécaudé
869ae01da9 Add security checks 2016-11-10 16:45:01 -05:00
Dave Conway-Jones
d63996eea1 slight tidy of YAML PR (remove excess console.log in test)
and improve XML test coverage slightly
2016-11-10 21:29:07 +00:00
Nathanaël Lécaudé
9bbc8eda9d Added YAML parser node (#1034)
Thanks @natcl -
(sorry pressed closed by mistake !)
* Added YAML parser node

* Added YAML error strings in messages.json

* Change location of YAML library import

* Remove copyright

* Remove copyright

* Change order of yaml in Template node

* Add YAML test

* Add working test
2016-11-10 21:22:05 +00:00
Dave Conway-Jones
9cc1b03c56 small change to udp httpadmin
as it refers to both in and pout
2016-11-10 20:19:55 +00:00
Dave Conway-Jones
b1ab26e3ad update Font Awesome to 4.7.0 2016-11-10 20:15:06 +00:00
Nathanaël Lécaudé
96820418b5 Fix comparison to "" in tcpin 2016-11-10 11:17:27 -05:00
Nathanaël Lécaudé
385d9f16e9 Change scope of clients object 2016-11-09 22:33:55 -05:00
Nathanaël Lécaudé
d56fce37dd Works when connection is left open 2016-11-09 13:25:19 -05:00
Nathanaël Lécaudé
aef2c9e5cf First release of multi connection tcpget 2016-11-09 10:15:23 -05:00
Nick O'Leary
89a05c580f Handle drag whilst quick-add dialog open 2016-11-09 13:25:55 +00:00
Nick O'Leary
b85e562980 Combine quick-add and quick-join actions 2016-11-09 13:17:26 +00:00
Nick O'Leary
a0e6628757 Tweak search box styling 2016-11-08 21:18:34 +00:00
Nick O'Leary
60a41524f0 editableList delete button click event not cancelled 2016-11-08 17:01:21 +00:00
Nick O'Leary
6042395b81 Allow a node to reorder its outputs and maintain links
Fixes #1031
2016-11-08 17:00:47 +00:00
Nick O'Leary
8a5db8ce4b Handle explicitly set input widths on typedInput 2016-11-08 13:36:32 +00:00
Nick O'Leary
196d6e79e2 Don't pin change node input widths 2016-11-08 13:29:01 +00:00
Nick O'Leary
91f16215e5 Make typedInput keyboard navigable 2016-11-08 13:18:28 +00:00
Nick O'Leary
9c675a7847 Focus tray body when edit dialog opened 2016-11-08 09:58:20 +00:00
Nick O'Leary
f9e09e87d6 Hit enter to edit first node in selection 2016-11-07 21:51:03 +00:00
Nick O'Leary
73574d6293 Add quick-add node mode with cmd/ctrl-click 2016-11-07 21:25:09 +00:00
Ben Hardill
0a5a42b32a Fix node.error() not printing when passed false (#1037)
This should fix #1036
2016-11-07 18:28:35 +00:00
Nick O'Leary
de225205bd Fix safari/firefox detection of Meta key up 2016-11-06 00:24:01 +00:00
Nick O'Leary
8a47d36480 Add cmd/ctrl-click to quick add wires 2016-11-06 00:14:07 +00:00
Dave Conway-Jones
d5f3ba8d8a remove unnecessary require from JSON node 2016-11-04 19:55:02 +00:00
Nick O'Leary
782a06ce84 Tweak node info table colours 2016-11-04 14:30:41 +00:00
Nick O'Leary
5cdafc50fb Add node delete button to edit dialog 2016-11-04 14:29:04 +00:00
Nick O'Leary
0ca3cdb9ae tab-info node properties use RED.utils.createObjectElement 2016-11-03 14:34:38 +00:00
Nick O'Leary
a1d6cbd5fd Only expand strings that contain tabs/newlines 2016-11-03 14:34:38 +00:00
Nick O'Leary
6c36778cac Move debug message utils into core 2016-11-03 14:34:38 +00:00
Nick O'Leary
1c3a97a71a Make red.min.js a reusable library 2016-11-03 14:34:37 +00:00
Nick O'Leary
3489fe0cf4 Better toggling between raw/string views of buffers 2016-11-03 14:34:37 +00:00
Nick O'Leary
74b6d9dff9 Provide string view of buffers in debug messages 2016-11-03 14:34:37 +00:00
Nick O'Leary
06ee9aa05c Make strings expandable in debug 2016-11-03 14:34:37 +00:00
Nick O'Leary
f0f40a8606 Restore object keys values in debug sidebar 2016-11-03 14:34:37 +00:00
Nick O'Leary
1f2c9879bd Handle big arrays/buffers better in debug sidebar 2016-11-03 14:34:37 +00:00
Nick O'Leary
d1eb82bdf6 Show newlines/tabs in debug output 2016-11-03 14:34:37 +00:00
Nick O'Leary
8167f623e3 Update debug_spec for format changes 2016-11-03 14:34:37 +00:00
Nick O'Leary
9555e296a2 Close debug window when main window unloads 2016-11-03 14:34:37 +00:00
Nick O'Leary
f460283fa1 Full event passing between debug window and main window 2016-11-03 14:34:37 +00:00
Nick O'Leary
79da8e5a37 Move all common debug list code to its own library 2016-11-03 14:34:37 +00:00
Nick O'Leary
a35ce22218 Make debug message node id clickable 2016-11-03 14:34:36 +00:00
Nick O'Leary
1c905da8c2 Handle long strings in debug 2016-11-03 14:34:36 +00:00
Nick O'Leary
2b558768f1 Add debug filter box 2016-11-03 14:34:36 +00:00
Nick O'Leary
7607c4c882 Make inbuilt debug messages navigable 2016-11-03 14:34:36 +00:00
Nick O'Leary
c9f4813ce1 Fix debug path 2016-11-03 14:34:36 +00:00
Nick O'Leary
0428e27039 Improved type styling 2016-11-03 14:34:36 +00:00
Nick O'Leary
e30da2168d Make Debug object explorable 2016-11-03 14:34:36 +00:00
Nick O'Leary
0cd20768f4 Style the debug window to match the sidebar 2016-11-03 14:34:36 +00:00
Nick O'Leary
ab31f34862 Initial debug pop-out window 2016-11-03 14:34:36 +00:00
Dave Conway-Jones
9a4ff5cb43 fix test for CSV array input 2016-11-03 08:56:38 +00:00
Dave Conway-Jones
f66c91e18e different test for Pi (rather than use serial port name) 2016-11-03 08:56:18 +00:00
Dave Conway-Jones
a235745be7 Fix missing 0 handling for css node with array input 2016-11-02 15:49:51 +00:00
Nick O'Leary
9516da01e3 0.15.2 changelog 2016-10-28 08:48:10 +01:00
Nick O'Leary
7657bd2375 Bump 0.15.2 2016-10-28 08:43:21 +01:00
Nick O'Leary
0adcea9e7c Revert bidi changes to nodes and hide menu option until fixed
Fixes #1024
2016-10-28 08:37:33 +01:00
Dave Conway-Jones
aa8ad60083 Let xml node set options both ways
to close #1022  to close #975
Thanks @martin-doyle and @nikhildx
2016-10-26 22:06:35 +01:00
Dave Conway-Jones
5d98a86a6b bump serialport to use version 4
(precompiled versions more available)
2016-10-25 21:42:27 +01:00
Dave Conway-Jones
4418fdaed6 gpio node handle multiple bits of data returned in one go 2016-10-25 21:42:27 +01:00
Nick O'Leary
c58c45c917 HTTP In should pass application/octet-stream as buffer not string
Fixes #1023
2016-10-25 21:19:49 +01:00
Dave Conway-Jones
45eba5cabd tidy up udp node - repeat setting of var 2016-10-25 20:40:11 +01:00
Nick O'Leary
3ab0d0d865 Handle missing httpNodeRoot setting properly 2016-10-21 13:50:47 +01:00
Nick O'Leary
a6803081ab Config sidebar not handling node definition error properly 2016-10-21 13:47:54 +01:00
Nick O'Leary
8debed805b Add minimum show time to deploy spinner to avoid flicker 2016-10-21 12:59:55 +01:00
Nick O'Leary
fc9835512d Add work-in-progress update button to palette-editor 2016-10-21 10:29:26 +01:00
Nick O'Leary
5f0cab8cc2 Add log.removeHandler function 2016-10-20 23:31:40 +01:00
Nick O'Leary
bd391963bc Add Crtl/Shift/p shortcut for manage palette 2016-10-20 14:01:37 +01:00
Nick O'Leary
97fa28fb10 Add spinner to deploy button 2016-10-20 13:11:12 +01:00
Nick O'Leary
67d5b39c96 Status messages from nodes in subflows not delegated properly
Fixes #1016
2016-10-19 21:06:45 +01:00
Dave Conway-Jones
dbceef2581 fix spelling in join node info
Manual fix for #1014
Thanks @rogovski
2016-10-17 21:40:12 +01:00
Nick O'Leary
5b22ccfca6 Speed up tab scrolling 2016-10-15 20:58:27 +01:00
Nick O'Leary
714c254bab Update delay burst test to be more tolerant of timing
Fixes #1013
2016-10-14 22:35:43 +01:00
Nick O'Leary
90f4db9158 Bump 0.15.1 2016-10-13 19:53:43 +01:00
Nick O'Leary
eed470ddae Update default palette catalogue to use https 2016-10-13 16:22:25 +01:00
Nick O'Leary
49f72881f4 Disable palette editor if npm not found 2016-10-12 22:30:32 +01:00
Nick O'Leary
a76674032d Searching package catalogue should be case-insensitive
Fixes #1010
2016-10-12 20:08:08 +01:00
Nick O'Leary
ec392a7f9a contenteditable fields not handled in config nodes
Fixes #1011
2016-10-12 19:56:12 +01:00
Dave Conway-Jones
8a2ae6c480 Change html link refs from _new to _blank to be standards compliant 2016-10-12 17:53:27 +01:00
Nick O'Leary
b3796a8e24 Fix unit tests for /flows 2016-10-12 10:33:51 +01:00
Nick O'Leary
b9144ff987 Bump version 0.15.0 2016-10-12 10:27:08 +01:00
Nick O'Leary
5344949c71 Tidy up /flows api responses 2016-10-12 10:24:10 +01:00
Nick O'Leary
05cbba9a35 Exporting current flow not formatting tab node correctly 2016-10-11 21:34:52 +01:00
Nick O'Leary
325c6135cf Defeat the exec node test dragons 2016-10-11 20:31:42 +01:00
Dave Conway-Jones
fdea19a45b leave Pi GPIO pins in a sensible state on error 2016-10-11 15:37:34 +01:00
Nick O'Leary
fad63c0c18 Fix tab_config revealing unused config nodes 2016-10-11 15:06:34 +01:00
Nick O'Leary
f002560616 Exec node spawn mode should clone messages it reuses 2016-10-11 14:49:48 +01:00
Nick O'Leary
8e7d52e645 Avoid reencyrpting credentials if they haven't changed 2016-10-11 14:27:35 +01:00
Nick O'Leary
d119594cbf Tidy up exec node clean-up to remove failure-causing timing window 2016-10-11 13:25:19 +01:00
Nick O'Leary
84f7da6e93 Fix null checking in exec node test 2016-10-11 11:16:10 +01:00
Nick O'Leary
22e1bafe1b Fix exec test on node 0.10 2016-10-11 10:53:50 +01:00
Nick O'Leary
3f8e42e510 update changelog 2016-10-11 10:28:16 +01:00
Dave Conway-Jones
9704fb04d9 inject node label - show topic for timestamp mode if short 2016-10-11 09:27:02 +01:00
Nick O'Leary
dcfaf1e2b9 Update changelog 2016-10-11 00:17:06 +01:00
Nick O'Leary
42f7dc1947 Fix type checking in unit tests 2016-10-10 13:27:43 +01:00
Nick O'Leary
eb1a597456 Add npm build/test scripts
Closes #946 #660
2016-10-10 11:49:38 +01:00
Dave Conway-Jones
8368815db5 extra change tests for partial and complete match
to close #934
2016-10-10 11:48:52 +01:00
Nick O'Leary
9c6295d0d8 Lighten shade color in editor 2016-10-10 11:42:36 +01:00
Dave Conway-Jones
4d19f881e9 Let change node set type if total match
remove unnecessary 2 step move when not required.
add test for moving sub property up to main property
2016-10-10 11:10:36 +01:00
Dave Conway-Jones
3a8820397b clean up status on close for several core nodes. 2016-10-10 11:08:06 +01:00
Nick O'Leary
85b1c1fe97 Increase default apiMaxLength to 5mb and add to default settings
Closes #1001
2016-10-10 10:14:08 +01:00
Nick O'Leary
a4de9e94dd Update dependency versions 2016-10-10 10:02:41 +01:00
Nick O'Leary
0dd2c7fe24 Change node: reparse JSON set value each time to avoid pass-by-ref 2016-10-09 23:14:52 +01:00
Nick O'Leary
f22c3b549e Merge branch '0.15.0' 2016-10-09 23:00:28 +01:00
Nick O'Leary
3c60b3d2c9 Prevent search box opening when other modals are open 2016-10-09 22:54:47 +01:00
Nick O'Leary
f2d36b84b5 Don't hide install button on already-installed node modules 2016-10-09 22:23:47 +01:00
Nick O'Leary
9af08ef26a Update test helper for new flow api 2016-10-09 22:22:13 +01:00
Nick O'Leary
b4be1184fd Add v2 /flows api and deploy-overwrite protection 2016-10-09 22:02:40 +01:00
Nick O'Leary
c60e0d389c Mark nodes as changed when they are moved 2016-10-09 22:02:40 +01:00
Dave Conway-Jones
d658fe7709 move travis to node 6 and 7 - drop 5 and 0.12
move serialport  to 0.3.0 version
2016-10-06 13:31:59 +01:00
TJKoury
54036a2b4d Added parent containment option for draggable. (#1006)
* added parent containment option for draggable

* taking Nick's suggestion, #main-container it is
2016-10-02 22:45:49 +01:00
Dave Conway-Jones
2da9572a45 Better handle httprequest header capitalisation 2016-10-02 17:44:48 +01:00
Nick O'Leary
306825aa90 Enable es6 parsing in Function editor by default
Fixes #985
2016-09-30 23:51:27 +01:00
Nick O'Leary
c797073c05 Ignore bidi event handling on non-existent and non-Input elements
Closes #999
2016-09-30 23:35:05 +01:00
Nick O'Leary
d9d65d59d1 Fix timing window when scrolling search box results 2016-09-30 23:34:44 +01:00
Nick O'Leary
aad29e4487 Remove list of flows from menu 2016-09-30 23:34:26 +01:00
Nick O'Leary
b00985f99f Replace palette-edit button with menu option 2016-09-30 20:33:27 +01:00
Nick O'Leary
538a16a5fb Allow nodes to be imported with their credentials 2016-09-30 14:15:04 +01:00
Nick O'Leary
300a8d3a89 Click to close search box 2016-09-30 13:27:53 +01:00
Nick O'Leary
e3b7c5fce7 Add 'no matches' message to package search results 2016-09-30 11:19:47 +01:00
Nick O'Leary
2e87ebe800 Fix editableList sizing on safari 2016-09-30 10:46:13 +01:00
Nick O'Leary
7ed9e7cdd4 Update debug sidebar to use RED.view.reveal to show debug nodes 2016-09-29 23:49:58 +01:00
Nick O'Leary
7ff9c2885d Fix scrollable tab buttons changing location hash 2016-09-29 23:46:55 +01:00
Nick O'Leary
18c8bbb0fc Add workspace search option 2016-09-29 23:46:29 +01:00
Nick O'Leary
9a49fb9450 Add escape-to-clear to searchBox and other css fixes 2016-09-29 23:45:25 +01:00
Nick O'Leary
84457bc7b4 Add scrollOnAdd option to editableList 2016-09-29 23:44:49 +01:00
Dave Conway-Jones
15f1e2c85c Add swift markup to editor for open whisk node 2016-09-27 22:04:13 +01:00
Nick O'Leary
15e828e975 Adjust dragging tabs when partially scrolled 2016-09-27 00:05:43 +01:00
Nick O'Leary
e4626ee52b Scrollable tabs 👍 2016-09-26 22:56:28 +01:00
Nick O'Leary
1866c9c7ef Allow linking to individual flow via url hash 2016-09-24 22:57:41 +01:00
Nick O'Leary
a0f91aa814 Avoid duplicating existing subflows on import 2016-09-24 22:20:28 +01:00
Dave Conway-Jones
a89c7b1a70 Add full path tip to file node, And tidy up Pi node tips 2016-09-23 23:37:56 +01:00
Dave Conway-Jones
ded1376957 remove websocket node maxlistener warning 2016-09-23 23:36:58 +01:00
Nick O'Leary
252040f03b Add import-to-new-tab option 2016-09-23 22:02:12 +01:00
Nick O'Leary
d29abc2724 Encrypt credentials by default 2016-09-23 10:38:30 +01:00
Nick O'Leary
44c35d2644 Update test node helper module for storage api changes 2016-09-21 22:22:04 +01:00
Nick O'Leary
f9b972349d Move credential load/save storage functions under get/setFlows 2016-09-21 21:58:50 +01:00
Nick O'Leary
e06cadd761 Pass full runtime object to storage and flow sub-components 2016-09-21 10:22:04 +01:00
Nick O'Leary
ee45d6b48f Fix contenteditable div unfocused css 2016-09-20 10:10:28 +01:00
Nick O'Leary
d915b280d4 Add new options to export-nodes dialog 2016-09-19 13:54:23 +01:00
Nick O'Leary
39d90fe881 Update mqtt-broker node to use fully name-space qualified status messages 2016-09-19 09:36:38 +01:00
wajnberg
b9da1f18b4 Fixing issue 989 (#997)
* Fixing issue 989

Signed-off-by: Moshe Wajnberg <wajnberg@il.ibm.com>

* Fixing the getRangeAt problem on Chrome

Signed-off-by: Moshe Wajnberg <wajnberg@il.ibm.com>

* Fixing the getRangeAt problem on Chrome

Signed-off-by: Moshe Wajnberg <wajnberg@il.ibm.com>
2016-09-18 21:20:50 +01:00
Dave Conway-Jones
69a0934173 Merge pull request #996 from Belphemur/delay-migration
Fix migration of Delay Node
2016-09-17 15:54:27 +01:00
Antoine Aflalo
289de85754 Fix the check for nbRateUnits 2016-09-17 10:38:30 -04:00
Dave Conway-Jones
0ec95041d9 another tiny nudge for code tag 2016-09-17 15:29:54 +01:00
Dave Conway-Jones
fcb6f78d54 give <code> tag slightly more bottom space 2016-09-17 14:06:01 +01:00
Dave Conway-Jones
29e9740668 Let UDP node better share same port instance if required 2016-09-17 14:05:26 +01:00
Antoine Aflalo
ea8c6d5cce Add number of units to the delay node (rate) (#994)
* Add possibility to set the value for the rate unit

Backward compatible, if the new nbRateUnits is not set, default to 1.
This way we can delay messages to 1 msg per X seconds/minutes/hours days
instead of always 1.
Useful when interacting with API that have a uncommon rate limiting like
1req per 2 seconds.

* Fix existing testing for delay

* Add new test for the nbRateUnits

* Fix label for timed and topic for delay node

* Schrink width of Units delay rate

* pluralisation of labels

* Dynamic pluralisation respecting i18n

* Remove debug data left
2016-09-16 14:27:14 +01:00
Alice Ferrazzi
e4c951984a typo fix (#990)
typo fix in mqtt broker help text
2016-09-14 23:13:08 +01:00
Dave Conway-Jones
0071afb205 update registry loader test to normalise path for windows
Thanks shrikes
2016-09-13 22:57:20 +01:00
Nick O'Leary
d3c7ac75be Set switch node rule input widths properly 2016-09-08 21:12:39 +01:00
Nick O'Leary
55d7420abf Remove tabs 2016-09-08 20:49:44 +01:00
wajnberg
489b56456f Completing STT support (#976)
* Completing STT support

Signed-off-by: Moshe Wajnberg <wajnberg@il.ibm.com>

* Adressing Nick comments

Signed-off-by: Moshe Wajnberg <wajnberg@il.ibm.com>
2016-09-08 20:46:30 +01:00
Nick O'Leary
1f24fcb364 Ensure errors thrown by RED.events handlers don't percolate up 2016-09-05 23:09:33 +01:00
Nick O'Leary
722b31edee Safely ignore subflow instance nodes in palette editor 2016-09-02 20:31:24 +01:00
Dave Conway-Jones
765f0393b0 Add test for change node ,move to sub-property 2016-08-28 12:09:37 +01:00
Dave Conway-Jones
6868ef044b Allow http middleware to skip rawBodyParser 2016-08-28 12:02:34 +01:00
Dave Conway-Jones
5dd0622e40 Let change node move property to sub-property. 2016-08-28 12:02:34 +01:00
Dave Conway-Jones
48bdab1dcf Add info to exec warning about buffered output if using python 2016-08-28 12:02:34 +01:00
Nick O'Leary
aee483e9f1 Stop nodes being added beyond the outer bounds of the workspace 2016-08-26 16:22:06 +01:00
Nick O'Leary
8542b9bf67 Fix splice handling when a subflow input/output node is selected 2016-08-26 13:34:29 +01:00
Nick O'Leary
feaf6f2501 Remove console.log from bidi 2016-08-26 13:27:19 +01:00
Nick O'Leary
d7d30aa972 Default config nodes to global scope unless in a subflow
Closes #972
2016-08-26 13:26:42 +01:00
Nick O'Leary
91c23d1f7d Fix palette-editor handling of subflows 2016-08-26 13:21:33 +01:00
Nick O'Leary
57479edc59 Merge branch 'palette-ui' into 0.15.0 2016-08-26 13:01:03 +01:00
Nick O'Leary
4b462eaae9 Move initInputEvents to prepareInput 2016-08-26 12:50:18 +01:00
Nick O'Leary
c60fb3bc25 Move setting text direction into bidi module 2016-08-26 00:40:01 +01:00
Nick O'Leary
b17c34402d Fix some more tabs/spaces in bidi work 2016-08-26 00:28:22 +01:00
Nick O'Leary
6ad71bd222 Move bidi code under RED.text 2016-08-25 17:09:56 +01:00
wajnberg
ccc08be0ee Bidi support for Text Direction and Structured Text (#961)
* Bidi support for Text Direction and Structured Text

Signed-off-by: Moshe Wajnberg <wajnberg@il.ibm.com>

* Adding documentation for functions in bidi.js and format.js

Signed-off-by: Moshe Wajnberg <wajnberg@il.ibm.com>

* Removing unused functions from format.js

Signed-off-by: Moshe Wajnberg <wajnberg@il.ibm.com>
2016-08-25 16:47:30 +01:00
telogis-nodered
2a2fc80931 Fix jquery selector, selecting more than one help pane/popover and displaying incorrectly. (#970) 2016-08-25 10:44:23 +01:00
James Thomas
9ebca91775 Fixes removeItem not passing row data to callback. (#965)
Call to .data('data') was happening after the remove() call, which
deletes the retained data. This was passing undefined back to the
callback for removeItem.

I've changed the data retrieval to a temporary variable before the
delete call.
2016-08-21 23:05:53 +01:00
Dave Conway-Jones
456fc23463 update README link to IBM ETS blog page 2016-08-18 13:50:46 +01:00
Nick O'Leary
eb17562f4d NLS the palette editor 2016-08-14 23:08:37 +01:00
Nick O'Leary
b7dbfd5cfc Only reload catalogue when requested 2016-08-13 00:33:41 +01:00
Nick O'Leary
cdc7ab562a Add sort options to palette-editor search 2016-08-12 23:00:28 +01:00
Nick O'Leary
e6b5552cba Add some more error handlers for custom node label functions
Closes #956
2016-08-11 14:49:22 +01:00
Nick O'Leary
eecf92183f Update to new catalogue format 2016-08-10 21:59:31 +01:00
Nick O'Leary
11656382a7 Allow palette-editor to be disabled via editorTheme 2016-08-10 20:15:17 +01:00
Nick O'Leary
e4d788ad0b Add install tab to palette-editor 2016-08-09 10:43:03 +01:00
Nick O'Leary
3017442702 Move common components and add searchBox 2016-08-09 10:41:26 +01:00
Nick O'Leary
ba37db275c Add node filter to palette-editor 2016-08-05 16:39:41 +01:00
Nick O'Leary
521e669879 Enable palette-editor remove buttons 2016-08-05 13:39:14 +01:00
Nick O'Leary
12e302c10a Collapse palette modules when palette-editor closed 2016-08-04 22:28:56 +01:00
Nick O'Leary
7220af3ef0 Move palette editor to left hand side 2016-08-04 16:49:36 +01:00
Dave Conway-Jones
42f4e0fa86 TCP node: pass on latest input msg properties
to close #944
2016-08-04 15:49:38 +01:00
Dave Conway-Jones
022d066fe0 Make sure MQTT broker is really set
To close #951
2016-08-04 10:02:27 +01:00
Dave Conway-Jones
4c9d7cbeed Merge pull request #955 from natcl/master
Fix escapce character catch in TCPGet + support 0x?? sequences
2016-08-02 20:15:31 +01:00
Nathanaël Lécaudé
1541e382e4 Fix escapce character catch in TCPGet + support 0x?? sequences 2016-08-02 12:32:49 -04:00
Dave Conway-Jones
1d9488d24f Merge pull request #954 from natcl/master
Fix split character in TCP Request node
2016-08-02 16:26:37 +01:00
Nathanaël Lécaudé
6cbc1afb9b Fix split character in TCP Request node 2016-08-02 11:09:41 -04:00
Nathanaël Lécaudé
3f86b660ed Add CSS hilighting to the template node (#950)
This can be useful when using the template node to create frontends, see this post:
https://groups.google.com/d/msg/node-red/q4DKaX87Ano/Xa1mLpOdAwAJ

Thanks !
2016-08-01 22:32:02 +01:00
Dave Conway-Jones
4603f2d9ca only update switch Prev value after all rules are run 2016-08-01 12:31:35 +01:00
Nick O'Leary
da818cf420 Add initial palette sidebar 2016-07-29 12:52:00 +01:00
Nick O'Leary
86a2ed652d Update changelog 2016-07-29 10:44:52 +01:00
Nick O'Leary
269761f222 Bump version/changelog 2016-07-29 10:43:53 +01:00
Dave Conway-Jones
53ca3046b3 Add RPi.GPIO lib test for ArchLinux 2016-07-28 18:20:18 +01:00
Nick O'Leary
f484156d8e Tell ace about Function node globals
Closes #927
2016-07-28 17:14:55 +01:00
Nick O'Leary
1da8712a4a Update ace to 1.2.4 2016-07-28 17:14:38 +01:00
Nick O'Leary
dd47eba88c Add proper help text to link nodes 2016-07-28 15:58:00 +01:00
Nick O'Leary
0ade8ff7a2 Add log warning if node module required version cannot be satisfied 2016-07-28 15:43:26 +01:00
Nick O'Leary
6a528b5fdb Allow config nodes to provide a sort function for their select list 2016-07-28 13:27:34 +01:00
Nick O'Leary
7f63ddc9ea Handle importing old mqtt-broker configs that lack properties 2016-07-27 23:05:48 +01:00
Nick O'Leary
d6b326c134 Handle empty credentials file
Closes #937
2016-07-26 22:23:49 +01:00
Nick O'Leary
d944298dd7 Tidy up mqtt nodes - linting and done handling
Closes #935
2016-07-26 21:33:00 +01:00
Nick O'Leary
0136ebd2b4 Fix invalid html in TCP and HTML node edit templates 2016-07-26 16:19:27 +01:00
Nick O'Leary
45f8def1ed Bump version + change log 2016-07-23 22:59:56 +01:00
Nick O'Leary
7c6e8eeefc Cannot clear cookies with http nodes 2016-07-23 22:41:37 +01:00
Dave Conway-Jones
e81e48cde3 Fix html parse node test 2016-07-20 20:58:52 +01:00
Dave Conway-Jones
8eebb6ea2d let HTML parse node allow msg.select set select
to close #943
2016-07-20 20:08:50 +01:00
Nick O'Leary
ad8290ebcb Validate nodes on import after any references have been remapped 2016-07-20 11:30:49 +01:00
Nick O'Leary
15b6f6268b Debug node handles objects without constructor property
Fixes #933
2016-07-15 22:41:35 +01:00
Nick O'Leary
92d5af7446 Ensure 'false' property values are displayed in info panel
Fixes #940
2016-07-15 22:33:17 +01:00
Nick O'Leary
d57425a15e Fix node enable/disable over restart - load configs after settings init 2016-07-15 00:11:28 +01:00
313 changed files with 23248 additions and 4401 deletions

View File

@@ -11,14 +11,11 @@ addons:
- gcc-4.8
matrix:
allow_failures:
- node_js: "5"
- node_js: "6"
- node_js: "7"
node_js:
- "7"
- "6"
- "5"
- "4"
- "0.12"
- "0.10"
script:
- istanbul cover ./node_modules/.bin/grunt --report lcovonly && istanbul report text && ( cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js || true ) && rm -rf coverage
before_script:

View File

@@ -1,3 +1,234 @@
#### 0.16.1: Maintenance Release
- Add colour swatches to debug when hex colour matched
- Nodes with hasUsers set to false should not appear unused
- Change hard error to verbose warning if using old node.js level
- Don't filter debug properties starting with _ Fixes #1117
- Node logged errors not displayed properly in debug pane Fixes #1116
- Do not look for existing nodes when checking for wires on paste Fixes #1114
- -v option not enabling verbose mode properly
- Add node.js version check on startup
#### 0.16.0: Milestone Release
Runtime
- Drop support for node 0.10 and 0.12
Nodes
- Add option to colourise debug console output Closes #1103
- Add property validation to nodes using typedInput
- Add common validator for typedInput fields Closes #1104
- Update debug node console logging indicator icon Closes #1094
- Let exec node (spawn) handle commands with spaces in path
- Add symbol to debug node to indicate debugging also to console.log
- Change file node to use node 4 syntax (drops support for 0.8)
- add info for httprequest responseUrl property
- Add res.responseUrl to httprequest node response
- Add support for flow and global context in Template node (#1048)
- Added YAML parser node (#1034)
- node-red-node-serialport removed as a default node
Editor
- Add install/remove dialog to increase friction Closes #1109
- Report node catalogue load errors Closes #1009
- Properly report module remove errors in palette editor Fixes #1043
- Update rather than hide install button after success install
- Tweak search box styling
- Display info tips slightly longer
- Allow tips to be enabled/disabled via menu option
- Info-tips update
- Make typedInput keyboard navigable
- update Font Awesome to 4.7.0
- Add expression editor for jsonata
- Overhaul keyboard handling and introduce editor actions
- Add Japanese translation file(editor.json) (#1084)
- Add quick-add node mode with cmd/ctrl-click
- Add cmd/ctrl-click to quick add wires
- Use json-stringify-safe to detect circular references in debug msgs
- debug - format if time if correct length/range
- Make Debug object explorable
- Initial debug pop-out window
- Add proper three-way diff view
- Focus tray body when edit dialog opened
- Hit enter to edit first node in selection
- Add node delete button to edit dialog
- Add notification when runtime stopped due to missing types Part of #832
Fixes
- Do not tie debug src loading to needsPermission Fixes #1111
- Initialise nodeApp regardless of httpAdmin setting Closes #1096 #1095
- Speed up reveal of search dialogs
- Ensure flows exist before delegating status/error events Fixes #1069
- Update package dependencies
- Update MQTT to latest 2.2.1
- Node status not being refreshed properly in the editor
- Try to prevent auto-fill of password fields in node edit tray Fixes #1081
- Fix whitespace in localfilesystem
- fix bug where savesettings did not honor local settings variables (#1073)
- Tidy up unused/duplicate editor messages Closes #922
- Property expressions must not be blank
- Tidy up merge commit of validatePropertyExpression
- add port if wires array > number of ports declared.
- Allow quoted property expressions Fixes #1101
- Index all node properties for node search
- Remove node 0.10 from travis config
- update welcome message to use logger so it can be turned off/on if required (#1083)
- Fix dynamically loading multiple node-sets from palette editor
- Allow a node to reorder its outputs and maintain links Fixes #1031
#### 0.15.3: Maintenance Release
- Tcpgetfix: Another small check (#1070)
- TCPGet: Ensure done() is called only once (#1068)
- Allow $ and _ at start of property identifiers Fixes #1063
- TCPGet: Separated the node.connected property for each instance (#1062)
- Corrected 'overide' typo in XML node help (#1061)
- TCPGet: Last property check (hopefully) (#1059)
- Add additional safety checks to avoid acting on non-existent objects (#1057)
- add --title for process name to command line options
- add indicator for fire once on inject node
- reimplement $(env var) replace to share common code.
- Fix error message for missing node html file, and add test.
- Let credentials also use $(...) substitutions from ENV
- Rename insecureRedirect to requireHttps
- Add setting to cause insecure redirect (#1054)
- Palette editor fixes (#1033)
- Close comms on stopServer in test helper (#1020)
- Tcpgetfix (#1050)
- TCPget: Store incoming messages alongside the client object to keep reference
- Merge remote-tracking branch 'upstream/master' into tcpgetfix
- TCPget can now handle concurrent sessions (#1042)
- Better scope handling
- Add security checks
- small change to udp httpadmin
- Fix comparison to "" in tcpin
- Change scope of clients object
- Works when connection is left open
- First release of multi connection tcpget
- Fix node.error() not printing when passed false (#1037)
- fix test for CSV array input
- different test for Pi (rather than use serial port name)
- Fix missing 0 handling for css node with array input
#### 0.15.2: Maintenance Release
- Revert bidi changes to nodes and hide menu option until fixed Fixes #1024
- Let xml node set options both ways
- Bump serialport to use version 4
- gpio node handle multiple bits of data returned in one go
- HTTP In should pass application/octet-stream as buffer not string Fixes #1023
- Handle missing httpNodeRoot setting properly
- Config sidebar not handling node definition error properly
- Add minimum show time to deploy spinner to avoid flicker
- Add work-in-progress update button to palette-editor
- Add log.removeHandler function
- Add Crtl/Shift/p shortcut for manage palette
- Add spinner to deploy button
- Status messages from nodes in subflows not delegated properly Fixes #1016
- fix spelling in join node info
- Speed up tab scrolling
- Update delay burst test to be more tolerant of timing Fixes #1013
#### 0.15.1: Maintenance Release
- Update default palette catalogue to use https
- Disable palette editor if npm not found - and fix for Windows
- Searching package catalogue should be case-insensitive Fixes #1010
- contenteditable fields not handled in config nodes Fixes #1011
- Change html link refs from `_new` to `_blank` to be standards compliant
#### 0.15.0: Milestone Release
Runtime
- Increase default apiMaxLength to 5mb and add to default settings Closes #1001
- Add v2 /flows api and deploy-overwrite protection
- Encrypt credentials by default
- Ensure errors thrown by RED.events handlers don't percolate up
Editor
- Mark nodes as changed when they are moved
- Added parent containment option for draggable. (#1006)
- Ignore bidi event handling on non-existent and non-Input elements Closes #999
- Remove list of flows from menu
- Allow nodes to be imported with their credentials
- Add workspace search option
- Add scrollOnAdd option to editableList
- Add swift markup to editor for open whisk node
- Scrollable tabs 👍
- Allow linking to individual flow via url hash
- Avoid duplicating existing subflows on import
- Add import-to-new-tab option
- Add new options to export-nodes dialog
- Stop nodes being added beyond the outer bounds of the workspace
- Default config nodes to global scope unless in a subflow Closes #972
- Bidi support for Text Direction and Structured Text (#961)
- Fix jQuery selector, selecting more than one help pane/popover and displaying incorrectly. (#970)
- Fixes removeItem not passing row data to callback. (#965)
- Move common components and add searchBox
- Add initial palette sidebar
Nodes
- Inject node label - show topic for timestamp mode if short
- Let change node set type if total match
- Clean up status on close for several core nodes.
- Change node: re-parse JSON set value each time to avoid pass-by-ref
- Better handle HTTP Request header capitalisation
- Enable ES6 parsing in Function editor by default Fixes #985
- Update debug sidebar to use RED.view.reveal to show debug nodes
- Add full path tip to file node, And tidy up Pi node tips
- Remove WebSocket node maxlistener warning
- Update mqtt-broker node to use fully name-space qualified status messages
- Let UDP node better share same port instance if required
- Add number of units to the delay node (rate) (#994)
- Allow http middleware to skip rawBodyParser
- Let change node move property to sub-property.
- Add info to exec warning about buffered output if using python
- TCP node: pass on latest input msg properties
- Make sure MQTT broker is really set
- Fix escape character catch in TCPGet + support 0x?? sequences
- Fix split character in TCP Request node
- Add CSS highlighting to the template node (#950)
- Only update switch previous value after all rules are run
Other
- Add npm build/test scripts Closes #946 #660
- Move travis to node 6 and 7 - drop 5 and 0.12
#### 0.14.6: Maintenance Release
Fixes
- Tell ace about Function node globals. Closes #927
- Tidy up mqtt nodes - linting and done handling. Closes #935
- Fix invalid html in TCP and HTML node edit templates
- Add proper help text to link nodes
- Handle importing old mqtt-broker configs that lack properties
- Update ace to 1.2.4
- Allow config nodes to provide a sort function for their select list
- Add log warning if node module required version cannot be satisfied
- Handle empty credentials file. Closes #937
- Add RPi.GPIO lib test for ArchLinux
#### 0.14.5: Maintenance Release
Fixes
- Cannot clear cookies with http nodes
- let HTML parse node allow msg.select set select
- Validate nodes on import after any references have been remapped
- Debug node handles objects without constructor property Fixes #933
- Ensure 'false' property values are displayed in info panel Fixes #940
- Fix node enable/disable over restart - load configs after settings init
#### 0.14.4: Maintenance Release
Nodes
@@ -8,7 +239,7 @@ Nodes
- Inject node should reuse the message it is triggered with Closes #914
- Stop trigger node re-using old message
- Allow node.status text to be 'falsey' values
Fixes
- Handle DOMException when embedded in an iframe of different origin Fixes #932

View File

@@ -38,21 +38,13 @@ If you want to raise a pull-request with a new feature, or a refactoring
of existing code, it may well get rejected if you haven't discussed it on
the [mailing list](https://groups.google.com/forum/#!forum/node-red) first.
### Contributor License Agreement
All contributors need to sign the JS Foundation's Contributor License Agreement.
It is an online process and quick to do. You can read the details of the agreement
here: https://cla.js.foundation/node-red/node-red.
In order for us to accept pull-requests, the contributor must first complete
a Contributor License Agreement (CLA). This clarifies the intellectual
property license granted with any contribution. It is for your protection as a
Contributor as well as the protection of IBM and its customers; it does not
change your rights to use your own Contributions for any other purpose.
If you raise a pull-request without having signed the CLA, you will be prompted
to do so automatically.
You can download the CLAs here:
- [individual](http://nodered.org/cla/node-red-cla-individual.pdf)
- [corporate](http://nodered.org/cla/node-red-cla-corporate.pdf)
If you are an IBMer, please contact us directly as the contribution process is
slightly different.
### Coding standards

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2013, 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -98,36 +98,46 @@ module.exports = function(grunt) {
src: [
// Ensure editor source files are concatenated in
// the right order
"editor/js/main.js",
"editor/js/red.js",
"editor/js/events.js",
"editor/js/i18n.js",
"editor/js/settings.js",
"editor/js/user.js",
"editor/js/comms.js",
"editor/js/text/bidi.js",
"editor/js/text/format.js",
"editor/js/ui/state.js",
"editor/js/nodes.js",
"editor/js/history.js",
"editor/js/validators.js",
"editor/js/ui/utils.js",
"editor/js/ui/common/editableList.js",
"editor/js/ui/common/menu.js",
"editor/js/ui/common/popover.js",
"editor/js/ui/common/searchBox.js",
"editor/js/ui/common/tabs.js",
"editor/js/ui/common/stack.js",
"editor/js/ui/common/typedInput.js",
"editor/js/ui/actions.js",
"editor/js/ui/deploy.js",
"editor/js/ui/menu.js",
"editor/js/ui/diff.js",
"editor/js/ui/keyboard.js",
"editor/js/ui/tabs.js",
"editor/js/ui/popover.js",
"editor/js/ui/workspaces.js",
"editor/js/ui/view.js",
"editor/js/ui/sidebar.js",
"editor/js/ui/palette.js",
"editor/js/ui/tab-info.js",
"editor/js/ui/tab-config.js",
"editor/js/ui/palette-editor.js",
"editor/js/ui/editor.js",
"editor/js/ui/tray.js",
"editor/js/ui/clipboard.js",
"editor/js/ui/library.js",
"editor/js/ui/notifications.js",
"editor/js/ui/search.js",
"editor/js/ui/typeSearch.js",
"editor/js/ui/subflow.js",
"editor/js/ui/touch/radialMenu.js",
"editor/js/ui/typedInput.js",
"editor/js/ui/editableList.js"
"editor/js/ui/touch/radialMenu.js"
],
dest: "public/red/red.js"
},
@@ -145,6 +155,10 @@ module.exports = function(grunt) {
"public/vendor/vendor.css": [
// TODO: resolve relative resource paths in
// bootstrap/FA/jquery
],
"public/vendor/jsonata/jsonata.js": [
"node_modules/jsonata/jsonata.js",
"editor/vendor/jsonata/formatter.js"
]
}
}
@@ -152,7 +166,12 @@ module.exports = function(grunt) {
uglify: {
build: {
files: {
'public/red/red.min.js': 'public/red/red.js'
'public/red/red.min.js': 'public/red/red.js',
'public/red/main.min.js': 'public/red/main.js',
'public/vendor/jsonata/jsonata.min.js': 'public/vendor/jsonata/jsonata.js',
'public/vendor/ace/mode-jsonata.js': 'editor/vendor/jsonata/mode-jsonata.js',
'public/vendor/ace/worker-jsonata.js': 'editor/vendor/jsonata/worker-jsonata.js',
'public/vendor/ace/snippets/jsonata.js': 'editor/vendor/jsonata/snippets-jsonata.js'
}
}
},
@@ -178,12 +197,18 @@ module.exports = function(grunt) {
'red/api/locales/en-US/editor.json',
'red/runtime/locales/en-US/runtime.json'
]
},
keymaps: {
src: [
'editor/js/keymap.json'
]
}
},
attachCopyright: {
js: {
src: [
'public/red/red.min.js'
'public/red/red.min.js',
'public/red/main.min.js'
]
},
css: {
@@ -213,7 +238,7 @@ module.exports = function(grunt) {
files: [
'editor/js/**/*.js'
],
tasks: ['concat','uglify','attachCopyright:js']
tasks: ['copy:build','concat','uglify','attachCopyright:js']
},
sass: {
files: [
@@ -229,6 +254,12 @@ module.exports = function(grunt) {
],
tasks: ['jsonlint:messages']
},
keymaps: {
files: [
'editor/js/keymap.json'
],
tasks: ['jsonlint:keymaps','copy:build']
},
misc: {
files: [
'CHANGELOG.md'
@@ -262,40 +293,49 @@ module.exports = function(grunt) {
copy: {
build: {
files:[{
cwd: 'editor/images',
src: '**',
expand: true,
dest: 'public/red/images/'
},
{
cwd: 'editor/vendor',
src: [
'ace/**',
//'bootstrap/css/**',
'bootstrap/img/**',
'jquery/css/**',
'font-awesome/**'
],
expand: true,
dest: 'public/vendor/'
},
{
cwd: 'editor/icons',
src: '**',
expand: true,
dest: 'public/icons/'
},
{
expand: true,
src: ['editor/index.html','editor/favicon.ico'],
dest: 'public/',
flatten: true
},
{
src: 'CHANGELOG.md',
dest: 'public/red/about'
}
files:[
{
src: 'editor/js/main.js',
dest: 'public/red/main.js'
},
{
src: 'editor/js/keymap.json',
dest: 'public/red/keymap.json'
},
{
cwd: 'editor/images',
src: '**',
expand: true,
dest: 'public/red/images/'
},
{
cwd: 'editor/vendor',
src: [
'ace/**',
//'bootstrap/css/**',
'bootstrap/img/**',
'jquery/css/**',
'font-awesome/**'
],
expand: true,
dest: 'public/vendor/'
},
{
cwd: 'editor/icons',
src: '**',
expand: true,
dest: 'public/icons/'
},
{
expand: true,
src: ['editor/index.html','editor/favicon.ico'],
dest: 'public/',
flatten: true
},
{
src: 'CHANGELOG.md',
dest: 'public/red/about'
}
]
},
release: {
@@ -360,7 +400,7 @@ module.exports = function(grunt) {
grunt.registerMultiTask('attachCopyright', function() {
var files = this.data.src;
var copyright = "/**\n"+
" * Copyright 2013, 2015 IBM Corp.\n"+
" * Copyright JS Foundation and other contributors, http://js.foundation\n"+
" *\n"+
" * Licensed under the Apache License, Version 2.0 (the \"License\");\n"+
" * you may not use this file except in compliance with the License.\n"+
@@ -421,7 +461,7 @@ module.exports = function(grunt) {
grunt.registerTask('build',
'Builds editor content',
['clean:build','concat:build','concat:vendor','uglify:build','sass:build','jsonlint:messages','copy:build','attachCopyright']);
['clean:build','jsonlint','concat:build','concat:vendor','copy:build','uglify:build','sass:build','attachCopyright']);
grunt.registerTask('dev',
'Developer mode: run node-red, watch for source changes and build/restart',

View File

@@ -1,3 +1,4 @@
Copyright JS Foundation and other contributors, http://js.foundation
Apache License
Version 2.0, January 2004

View File

@@ -29,24 +29,23 @@ For further help, or general discussion, please use the
If you want to run the latest code from git, here's how to get started:
1. Install grunt, the build tool
npm install -g grunt-cli
2. Clone the code:
1. Clone the code:
git clone https://github.com/node-red/node-red.git
cd node-red
3. Install the node-red dependencies
2. Install the node-red dependencies
npm install
4. Build the code
3. Build the code
grunt build
npm run build
5. Run
4. Run
npm start
or
node red.js
@@ -61,13 +60,15 @@ This project adheres to the [Contributor Covenant 1.4](http://contributor-covena
## Authors
Node-RED is a creation of [IBM Emerging Technology](http://ibm.com/blogs/et).
Node-RED is a project of the [JS Foundation](http://js.foundation).
It was created by [IBM Emerging Technology](https://www.ibm.com/blogs/emerging-technology/).
* Nick O'Leary [@knolleary](http://twitter.com/knolleary)
* Dave Conway-Jones [@ceejay](http://twitter.com/ceejay)
For more open-source projects from IBM, head over [here](http://ibm.github.io).
## Copyright and license
Copyright 2013, 2016 IBM Corp. under [the Apache 2.0 license](LICENSE).
Copyright JS Foundation and other contributors, http://js.foundation under [the Apache 2.0 license](LICENSE).

View File

@@ -1,6 +1,6 @@
#!/bin/bash
#
# Copyright 2015 IBM Corp.
# Copyright JS Foundation and other contributors, http://js.foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

BIN
editor/icons/cog.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 B

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2014, 2016 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,7 +35,12 @@
function emit(evt,arg) {
if (handlers[evt]) {
for (var i=0;i<handlers[evt].length;i++) {
handlers[evt][i](arg);
try {
handlers[evt][i](arg);
} catch(err) {
console.log("RED.events.emit error: ["+evt+"] "+(err.toString()));
console.log(err);
}
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2013, 2016 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,289 @@
RED.history = (function() {
var undo_history = [];
function undoEvent(ev) {
var i;
var len;
var node;
var subflow;
var modifiedTabs = {};
if (ev) {
if (ev.t == 'multi') {
len = ev.events.length;
for (i=len-1;i>=0;i--) {
undoEvent(ev.events[i]);
}
} else if (ev.t == 'replace') {
RED.nodes.clear();
var imported = RED.nodes.import(ev.config);
imported[0].forEach(function(n) {
if (ev.changed[n.id]) {
n.changed = true;
}
})
RED.nodes.version(ev.rev);
} else if (ev.t == 'add') {
if (ev.nodes) {
for (i=0;i<ev.nodes.length;i++) {
node = RED.nodes.node(ev.nodes[i]);
if (node.z) {
modifiedTabs[node.z] = true;
}
RED.nodes.remove(ev.nodes[i]);
}
}
if (ev.links) {
for (i=0;i<ev.links.length;i++) {
RED.nodes.removeLink(ev.links[i]);
}
}
if (ev.workspaces) {
for (i=0;i<ev.workspaces.length;i++) {
RED.nodes.removeWorkspace(ev.workspaces[i].id);
RED.workspaces.remove(ev.workspaces[i]);
}
}
if (ev.subflows) {
for (i=0;i<ev.subflows.length;i++) {
RED.nodes.removeSubflow(ev.subflows[i]);
RED.workspaces.remove(ev.subflows[i]);
}
}
if (ev.subflow) {
if (ev.subflow.instances) {
ev.subflow.instances.forEach(function(n) {
var node = RED.nodes.node(n.id);
if (node) {
node.changed = n.changed;
node.dirty = true;
}
});
}
if (ev.subflow.hasOwnProperty('changed')) {
subflow = RED.nodes.subflow(ev.subflow.id);
if (subflow) {
subflow.changed = ev.subflow.changed;
}
}
}
if (ev.removedLinks) {
for (i=0;i<ev.removedLinks.length;i++) {
RED.nodes.addLink(ev.removedLinks[i]);
}
}
} else if (ev.t == "delete") {
if (ev.workspaces) {
for (i=0;i<ev.workspaces.length;i++) {
RED.nodes.addWorkspace(ev.workspaces[i]);
RED.workspaces.add(ev.workspaces[i]);
}
}
if (ev.subflow && ev.subflow.subflow) {
RED.nodes.addSubflow(ev.subflow.subflow);
}
if (ev.subflowInputs && ev.subflowInputs.length > 0) {
subflow = RED.nodes.subflow(ev.subflowInputs[0].z);
subflow.in.push(ev.subflowInputs[0]);
subflow.in[0].dirty = true;
}
if (ev.subflowOutputs && ev.subflowOutputs.length > 0) {
subflow = RED.nodes.subflow(ev.subflowOutputs[0].z);
ev.subflowOutputs.sort(function(a,b) { return a.i-b.i});
for (i=0;i<ev.subflowOutputs.length;i++) {
var output = ev.subflowOutputs[i];
subflow.out.splice(output.i,0,output);
for (var j=output.i+1;j<subflow.out.length;j++) {
subflow.out[j].i++;
subflow.out[j].dirty = true;
}
RED.nodes.eachLink(function(l) {
if (l.source.type == "subflow:"+subflow.id) {
if (l.sourcePort >= output.i) {
l.sourcePort++;
}
}
});
}
}
if (ev.subflow && ev.subflow.hasOwnProperty('instances')) {
ev.subflow.instances.forEach(function(n) {
var node = RED.nodes.node(n.id);
if (node) {
node.changed = n.changed;
node.dirty = true;
}
});
}
if (subflow) {
RED.nodes.filterNodes({type:"subflow:"+subflow.id}).forEach(function(n) {
n.inputs = subflow.in.length;
n.outputs = subflow.out.length;
while (n.outputs > n.ports.length) {
n.ports.push(n.ports.length);
}
n.resize = true;
n.dirty = true;
});
}
if (ev.nodes) {
for (i=0;i<ev.nodes.length;i++) {
RED.nodes.add(ev.nodes[i]);
modifiedTabs[ev.nodes[i].z] = true;
}
}
if (ev.links) {
for (i=0;i<ev.links.length;i++) {
RED.nodes.addLink(ev.links[i]);
}
}
if (ev.changes) {
for (i in ev.changes) {
if (ev.changes.hasOwnProperty(i)) {
node = RED.nodes.node(i);
if (node) {
for (var d in ev.changes[i]) {
if (ev.changes[i].hasOwnProperty(d)) {
node[d] = ev.changes[i][d];
}
}
node.dirty = true;
}
}
}
}
} else if (ev.t == "move") {
for (i=0;i<ev.nodes.length;i++) {
var n = ev.nodes[i];
n.n.x = n.ox;
n.n.y = n.oy;
n.n.dirty = true;
n.n.changed = n.changed;
}
// A move could have caused a link splice
if (ev.links) {
for (i=0;i<ev.links.length;i++) {
RED.nodes.removeLink(ev.links[i]);
}
}
if (ev.removedLinks) {
for (i=0;i<ev.removedLinks.length;i++) {
RED.nodes.addLink(ev.removedLinks[i]);
}
}
} else if (ev.t == "edit") {
for (i in ev.changes) {
if (ev.changes.hasOwnProperty(i)) {
if (ev.node._def.defaults[i] && ev.node._def.defaults[i].type) {
// This is a config node property
var currentConfigNode = RED.nodes.node(ev.node[i]);
if (currentConfigNode) {
currentConfigNode.users.splice(currentConfigNode.users.indexOf(ev.node),1);
}
var newConfigNode = RED.nodes.node(ev.changes[i]);
if (newConfigNode) {
newConfigNode.users.push(ev.node);
}
}
ev.node[i] = ev.changes[i];
}
}
if (ev.subflow) {
if (ev.subflow.hasOwnProperty('inputCount')) {
if (ev.node.in.length > ev.subflow.inputCount) {
ev.node.in.splice(ev.subflow.inputCount);
} else if (ev.subflow.inputs.length > 0) {
ev.node.in = ev.node.in.concat(ev.subflow.inputs);
}
}
if (ev.subflow.hasOwnProperty('outputCount')) {
if (ev.node.out.length > ev.subflow.outputCount) {
ev.node.out.splice(ev.subflow.outputCount);
} else if (ev.subflow.outputs.length > 0) {
ev.node.out = ev.node.out.concat(ev.subflow.outputs);
}
}
if (ev.subflow.hasOwnProperty('instances')) {
ev.subflow.instances.forEach(function(n) {
var node = RED.nodes.node(n.id);
if (node) {
node.changed = n.changed;
node.dirty = true;
}
});
}
RED.nodes.filterNodes({type:"subflow:"+ev.node.id}).forEach(function(n) {
n.inputs = ev.node.in.length;
n.outputs = ev.node.out.length;
RED.editor.updateNodeProperties(n);
});
} else {
var outputMap;
if (ev.outputMap) {
outputMap = {};
for (var port in ev.outputMap) {
if (ev.outputMap.hasOwnProperty(port) && ev.outputMap[port] !== "-1") {
outputMap[ev.outputMap[port]] = port;
}
}
}
RED.editor.updateNodeProperties(ev.node,outputMap);
RED.editor.validateNode(ev.node);
}
if (ev.links) {
for (i=0;i<ev.links.length;i++) {
RED.nodes.addLink(ev.links[i]);
}
}
ev.node.dirty = true;
ev.node.changed = ev.changed;
} else if (ev.t == "createSubflow") {
if (ev.nodes) {
RED.nodes.filterNodes({z:ev.subflow.subflow.id}).forEach(function(n) {
n.z = ev.activeWorkspace;
n.dirty = true;
});
for (i=0;i<ev.nodes.length;i++) {
RED.nodes.remove(ev.nodes[i]);
}
}
if (ev.links) {
for (i=0;i<ev.links.length;i++) {
RED.nodes.removeLink(ev.links[i]);
}
}
RED.nodes.removeSubflow(ev.subflow.subflow);
RED.workspaces.remove(ev.subflow.subflow);
if (ev.removedLinks) {
for (i=0;i<ev.removedLinks.length;i++) {
RED.nodes.addLink(ev.removedLinks[i]);
}
}
} else if (ev.t == "reorder") {
if (ev.order) {
RED.workspaces.order(ev.order);
}
}
Object.keys(modifiedTabs).forEach(function(id) {
var subflow = RED.nodes.subflow(id);
if (subflow) {
RED.editor.validateNode(subflow);
}
});
RED.nodes.dirty(ev.dirty);
RED.view.redraw(true);
RED.palette.refresh();
RED.workspaces.refresh();
RED.sidebar.config.refresh();
}
}
return {
//TODO: this function is a placeholder until there is a 'save' event that can be listened to
markAllDirty: function() {
@@ -34,263 +317,7 @@ RED.history = (function() {
},
pop: function() {
var ev = undo_history.pop();
var i;
var node;
var subflow;
var modifiedTabs = {};
if (ev) {
if (ev.t == 'add') {
if (ev.nodes) {
for (i=0;i<ev.nodes.length;i++) {
node = RED.nodes.node(ev.nodes[i]);
if (node.z) {
modifiedTabs[node.z] = true;
}
RED.nodes.remove(ev.nodes[i]);
}
}
if (ev.links) {
for (i=0;i<ev.links.length;i++) {
RED.nodes.removeLink(ev.links[i]);
}
}
if (ev.workspaces) {
for (i=0;i<ev.workspaces.length;i++) {
RED.nodes.removeWorkspace(ev.workspaces[i].id);
RED.workspaces.remove(ev.workspaces[i]);
}
}
if (ev.subflows) {
for (i=0;i<ev.subflows.length;i++) {
RED.nodes.removeSubflow(ev.subflows[i]);
RED.workspaces.remove(ev.subflows[i]);
}
}
if (ev.subflow) {
if (ev.subflow.instances) {
ev.subflow.instances.forEach(function(n) {
var node = RED.nodes.node(n.id);
if (node) {
node.changed = n.changed;
node.dirty = true;
}
});
}
if (ev.subflow.hasOwnProperty('changed')) {
subflow = RED.nodes.subflow(ev.subflow.id);
if (subflow) {
subflow.changed = ev.subflow.changed;
}
}
}
if (ev.removedLinks) {
for (i=0;i<ev.removedLinks.length;i++) {
RED.nodes.addLink(ev.removedLinks[i]);
}
}
} else if (ev.t == "delete") {
if (ev.workspaces) {
for (i=0;i<ev.workspaces.length;i++) {
RED.nodes.addWorkspace(ev.workspaces[i]);
RED.workspaces.add(ev.workspaces[i]);
}
}
if (ev.subflow && ev.subflow.subflow) {
RED.nodes.addSubflow(ev.subflow.subflow);
}
if (ev.subflowInputs && ev.subflowInputs.length > 0) {
subflow = RED.nodes.subflow(ev.subflowInputs[0].z);
subflow.in.push(ev.subflowInputs[0]);
subflow.in[0].dirty = true;
}
if (ev.subflowOutputs && ev.subflowOutputs.length > 0) {
subflow = RED.nodes.subflow(ev.subflowOutputs[0].z);
ev.subflowOutputs.sort(function(a,b) { return a.i-b.i});
for (i=0;i<ev.subflowOutputs.length;i++) {
var output = ev.subflowOutputs[i];
subflow.out.splice(output.i,0,output);
for (var j=output.i+1;j<subflow.out.length;j++) {
subflow.out[j].i++;
subflow.out[j].dirty = true;
}
RED.nodes.eachLink(function(l) {
if (l.source.type == "subflow:"+subflow.id) {
if (l.sourcePort >= output.i) {
l.sourcePort++;
}
}
});
}
}
if (ev.subflow && ev.subflow.hasOwnProperty('instances')) {
ev.subflow.instances.forEach(function(n) {
var node = RED.nodes.node(n.id);
if (node) {
node.changed = n.changed;
node.dirty = true;
}
});
}
if (subflow) {
RED.nodes.filterNodes({type:"subflow:"+subflow.id}).forEach(function(n) {
n.inputs = subflow.in.length;
n.outputs = subflow.out.length;
while (n.outputs > n.ports.length) {
n.ports.push(n.ports.length);
}
n.resize = true;
n.dirty = true;
});
}
if (ev.nodes) {
for (i=0;i<ev.nodes.length;i++) {
RED.nodes.add(ev.nodes[i]);
modifiedTabs[ev.nodes[i].z] = true;
}
}
if (ev.links) {
for (i=0;i<ev.links.length;i++) {
RED.nodes.addLink(ev.links[i]);
}
}
if (ev.changes) {
for (i in ev.changes) {
if (ev.changes.hasOwnProperty(i)) {
node = RED.nodes.node(i);
if (node) {
for (var d in ev.changes[i]) {
if (ev.changes[i].hasOwnProperty(d)) {
node[d] = ev.changes[i][d];
}
}
node.dirty = true;
}
}
}
}
} else if (ev.t == "move") {
for (i=0;i<ev.nodes.length;i++) {
var n = ev.nodes[i];
n.n.x = n.ox;
n.n.y = n.oy;
n.n.dirty = true;
}
// A move could have caused a link splice
if (ev.links) {
for (i=0;i<ev.links.length;i++) {
RED.nodes.removeLink(ev.links[i]);
}
}
if (ev.removedLinks) {
for (i=0;i<ev.removedLinks.length;i++) {
RED.nodes.addLink(ev.removedLinks[i]);
}
}
} else if (ev.t == "edit") {
for (i in ev.changes) {
if (ev.changes.hasOwnProperty(i)) {
if (ev.node._def.defaults[i].type) {
// This is a config node property
var currentConfigNode = RED.nodes.node(ev.node[i]);
if (currentConfigNode) {
currentConfigNode.users.splice(currentConfigNode.users.indexOf(ev.node),1);
}
var newConfigNode = RED.nodes.node(ev.changes[i]);
if (newConfigNode) {
newConfigNode.users.push(ev.node);
}
}
ev.node[i] = ev.changes[i];
}
}
if (ev.subflow) {
if (ev.subflow.hasOwnProperty('inputCount')) {
if (ev.node.in.length > ev.subflow.inputCount) {
ev.node.in.splice(ev.subflow.inputCount);
} else if (ev.subflow.inputs.length > 0) {
ev.node.in = ev.node.in.concat(ev.subflow.inputs);
}
}
if (ev.subflow.hasOwnProperty('outputCount')) {
if (ev.node.out.length > ev.subflow.outputCount) {
ev.node.out.splice(ev.subflow.outputCount);
} else if (ev.subflow.outputs.length > 0) {
ev.node.out = ev.node.out.concat(ev.subflow.outputs);
}
}
if (ev.subflow.hasOwnProperty('instances')) {
ev.subflow.instances.forEach(function(n) {
var node = RED.nodes.node(n.id);
if (node) {
node.changed = n.changed;
node.dirty = true;
}
});
}
RED.nodes.filterNodes({type:"subflow:"+ev.node.id}).forEach(function(n) {
n.inputs = ev.node.in.length;
n.outputs = ev.node.out.length;
RED.editor.updateNodeProperties(n);
});
if (ev.node.type === 'subflow') {
$("#menu-item-workspace-menu-"+ev.node.id.replace(".","-")).text(ev.node.name);
}
} else {
RED.editor.updateNodeProperties(ev.node);
RED.editor.validateNode(ev.node);
}
if (ev.links) {
for (i=0;i<ev.links.length;i++) {
RED.nodes.addLink(ev.links[i]);
}
}
ev.node.dirty = true;
ev.node.changed = ev.changed;
} else if (ev.t == "createSubflow") {
if (ev.nodes) {
RED.nodes.filterNodes({z:ev.subflow.subflow.id}).forEach(function(n) {
n.z = ev.activeWorkspace;
n.dirty = true;
});
for (i=0;i<ev.nodes.length;i++) {
RED.nodes.remove(ev.nodes[i]);
}
}
if (ev.links) {
for (i=0;i<ev.links.length;i++) {
RED.nodes.removeLink(ev.links[i]);
}
}
RED.nodes.removeSubflow(ev.subflow.subflow);
RED.workspaces.remove(ev.subflow.subflow);
if (ev.removedLinks) {
for (i=0;i<ev.removedLinks.length;i++) {
RED.nodes.addLink(ev.removedLinks[i]);
}
}
} else if (ev.t == "reorder") {
if (ev.order) {
RED.workspaces.order(ev.order);
}
}
Object.keys(modifiedTabs).forEach(function(id) {
var subflow = RED.nodes.subflow(id);
if (subflow) {
RED.editor.validateNode(subflow);
}
});
RED.nodes.dirty(ev.dirty);
RED.view.redraw(true);
RED.palette.refresh();
RED.workspaces.refresh();
RED.sidebar.config.refresh();
}
undoEvent(ev);
},
peek: function() {
return undo_history[undo_history.length-1];

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2013, 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@ RED.i18n = (function() {
dynamicLoad: false,
load:'current',
ns: {
namespaces: ["editor","node-red"],
namespaces: ["editor","node-red","jsonata","infotips"],
defaultNs: "editor"
},
fallbackLng: ['en-US'],

38
editor/js/keymap.json Normal file
View File

@@ -0,0 +1,38 @@
{
"*": {
"ctrl-shift-p":"core:manage-palette",
"ctrl-f": "core:search",
"ctrl-=": "core:zoom-in",
"ctrl--": "core:zoom-out",
"ctrl-0": "core:zoom-reset",
"ctrl-enter": "core:confirm-edit-tray",
"ctrl-escape": "core:cancel-edit-tray",
"ctrl-g i": "core:show-info-tab",
"ctrl-g d": "core:show-debug-tab",
"ctrl-g c": "core:show-config-tab",
"ctrl-e": "core:show-export-dialog",
"ctrl-i": "core:show-import-dialog",
"ctrl-space": "core:toggle-sidebar"
},
"workspace": {
"backspace": "core:delete-selection",
"delete": "core:delete-selection",
"enter": "core:edit-selected-node",
"ctrl-c": "core:copy-selection-to-internal-clipboard",
"ctrl-x": "core:cut-selection-to-internal-clipboard",
"ctrl-v": "core:paste-from-internal-clipboard",
"ctrl-z": "core:undo",
"ctrl-a": "core:select-all-nodes",
"shift-?": "core:show-help",
"up": "core:move-selection-up",
"right": "core:move-selection-right",
"down": "core:move-selection-down",
"left": "core:move-selection-left",
"shift-up": "core:step-selection-up",
"shift-right": "core:step-selection-right",
"shift-down": "core:step-selection-down",
"shift-left": "core:step-selection-left",
"ctrl-shift-j": "core:show-previous-tab",
"ctrl-shift-k": "core:show-next-tab"
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2013, 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
var RED = (function() {
(function() {
function loadNodeList() {
$.ajax({
@@ -25,7 +24,6 @@ var RED = (function() {
url: 'nodes',
success: function(data) {
RED.nodes.setNodeList(data);
var nsCount = 0;
for (var i=0;i<data.length;i++) {
var ns = data[i];
@@ -56,11 +54,9 @@ var RED = (function() {
success: function(data) {
$("body").append(data);
$("body").i18n();
$(".palette-spinner").hide();
$(".palette-scroll").show();
$("#palette-search").show();
$("#palette > .palette-spinner").hide();
$(".palette-scroll").removeClass("hide");
$("#palette-search").removeClass("hide");
loadFlows();
}
});
@@ -69,14 +65,36 @@ var RED = (function() {
function loadFlows() {
$.ajax({
headers: {
"Accept":"application/json"
"Accept":"application/json",
},
cache: false,
url: 'flows',
success: function(nodes) {
RED.nodes.import(nodes);
var currentHash = window.location.hash;
RED.nodes.version(nodes.rev);
RED.nodes.import(nodes.flows);
RED.nodes.dirty(false);
RED.view.redraw(true);
if (/^#flow\/.+$/.test(currentHash)) {
RED.workspaces.show(currentHash.substring(6));
}
var persistentNotifications = {};
RED.comms.subscribe("notification/#",function(topic,msg) {
var parts = topic.split("/");
var notificationId = parts[1];
if (msg.text) {
var text = RED._(msg.text,{default:msg.text});
if (!persistentNotifications.hasOwnProperty(notificationId)) {
persistentNotifications[notificationId] = RED.notify(text,msg.type,msg.timeout === undefined,msg.timeout);
} else {
persistentNotifications[notificationId].update(text,msg.timeout);
}
} else if (persistentNotifications.hasOwnProperty(notificationId)) {
persistentNotifications[notificationId].close();
delete persistentNotifications[notificationId];
}
});
RED.comms.subscribe("status/#",function(topic,msg) {
var parts = topic.split("/");
var node = RED.nodes.node(parts[1]);
@@ -85,21 +103,17 @@ var RED = (function() {
msg.text = node._(msg.text.toString(),{defaultValue:msg.text.toString()});
}
node.status = msg;
if (statusEnabled) {
node.dirty = true;
RED.view.redraw();
}
node.dirty = true;
RED.view.redraw();
}
});
RED.comms.subscribe("node/#",function(topic,msg) {
var i,m;
var typeList;
var info;
if (topic == "node/added") {
var addedTypes = [];
for (i=0;i<msg.length;i++) {
m = msg[i];
msg.forEach(function(m) {
var id = m.id;
RED.nodes.addNodeSet(m);
addedTypes = addedTypes.concat(m.types);
@@ -108,7 +122,7 @@ var RED = (function() {
$("body").append(data);
});
});
}
});
if (addedTypes.length) {
typeList = "<ul><li>"+addedTypes.join("</li><li>")+"</li></ul>";
RED.notify(RED._("palette.event.nodeAdded", {count:addedTypes.length})+typeList,"success");
@@ -143,6 +157,9 @@ var RED = (function() {
typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
RED.notify(RED._("palette.event.nodeDisabled", {count:msg.types.length})+typeList,"success");
}
} else if (topic == "node/upgraded") {
RED.notify(RED._("palette.event.nodeUpgraded", {module:msg.module,version:msg.version}),"success");
RED.nodes.registry.setModulePendingUpdated(msg.module,msg.version);
}
// Refresh flow library to ensure any examples are updated
RED.library.loadFlowLibrary();
@@ -162,72 +179,85 @@ var RED = (function() {
});
}
var statusEnabled = false;
function toggleStatus(state) {
statusEnabled = state;
RED.view.status(statusEnabled);
}
function loadEditor() {
RED.menu.init({id:"btn-sidemenu",
options: [
{id:"menu-item-view-menu",label:RED._("menu.label.view.view"),options:[
{id:"menu-item-view-show-grid",label:RED._("menu.label.view.showGrid"),toggle:true,onselect:RED.view.toggleShowGrid},
{id:"menu-item-view-snap-grid",label:RED._("menu.label.view.snapGrid"),toggle:true,onselect:RED.view.toggleSnapGrid},
{id:"menu-item-status",label:RED._("menu.label.displayStatus"),toggle:true,onselect:toggleStatus, selected: true},
null,
{id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:RED.sidebar.toggleSidebar, selected: true}
]},
null,
{id:"menu-item-import",label:RED._("menu.label.import"),options:[
{id:"menu-item-import-clipboard",label:RED._("menu.label.clipboard"),onselect:RED.clipboard.import},
{id:"menu-item-import-library",label:RED._("menu.label.library"),options:[]}
]},
{id:"menu-item-export",label:RED._("menu.label.export"),disabled:true,options:[
{id:"menu-item-export-clipboard",label:RED._("menu.label.clipboard"),disabled:true,onselect:RED.clipboard.export},
{id:"menu-item-export-library",label:RED._("menu.label.library"),disabled:true,onselect:RED.library.export}
]},
null,
{id:"menu-item-config-nodes",label:RED._("menu.label.displayConfig"),onselect:function() {}},
{id:"menu-item-workspace",label:RED._("menu.label.flows"),options:[
{id:"menu-item-workspace-add",label:RED._("menu.label.add"),onselect:RED.workspaces.add},
{id:"menu-item-workspace-edit",label:RED._("menu.label.rename"),onselect:RED.workspaces.edit},
{id:"menu-item-workspace-delete",label:RED._("menu.label.delete"),onselect:RED.workspaces.remove},
null
]},
{id:"menu-item-subflow",label:RED._("menu.label.subflows"), options: [
{id:"menu-item-subflow-create",label:RED._("menu.label.createSubflow"),onselect:RED.subflow.createSubflow},
{id:"menu-item-subflow-convert",label:RED._("menu.label.selectionToSubflow"),disabled:true,onselect:RED.subflow.convertToSubflow},
]},
null,
{id:"menu-item-keyboard-shortcuts",label:RED._("menu.label.keyboardShortcuts"),onselect:RED.keyboard.showHelp},
{id:"menu-item-help",
label: RED.settings.theme("menu.menu-item-help.label","Node-RED Website"),
href: RED.settings.theme("menu.menu-item-help.url","http://nodered.org/docs")
},
{id:"menu-item-node-red-version", label:"v"+RED.settings.version, onselect: showAbout }
]
var menuOptions = [];
menuOptions.push({id:"menu-item-view-menu",label:RED._("menu.label.view.view"),options:[
{id:"menu-item-view-show-grid",label:RED._("menu.label.view.showGrid"),toggle:true,onselect:"core:toggle-show-grid"},
{id:"menu-item-view-snap-grid",label:RED._("menu.label.view.snapGrid"),toggle:true,onselect:"core:toggle-snap-grid"},
{id:"menu-item-status",label:RED._("menu.label.displayStatus"),toggle:true,onselect:"core:toggle-status", selected: true},
null,
// {id:"menu-item-bidi",label:RED._("menu.label.view.textDir"),options:[
// {id:"menu-item-bidi-default",toggle:"text-direction",label:RED._("menu.label.view.defaultDir"),selected: true, onselect:function(s) { if(s){RED.text.bidi.setTextDirection("")}}},
// {id:"menu-item-bidi-ltr",toggle:"text-direction",label:RED._("menu.label.view.ltr"), onselect:function(s) { if(s){RED.text.bidi.setTextDirection("ltr")}}},
// {id:"menu-item-bidi-rtl",toggle:"text-direction",label:RED._("menu.label.view.rtl"), onselect:function(s) { if(s){RED.text.bidi.setTextDirection("rtl")}}},
// {id:"menu-item-bidi-auto",toggle:"text-direction",label:RED._("menu.label.view.auto"), onselect:function(s) { if(s){RED.text.bidi.setTextDirection("auto")}}}
// ]},
// null,
{id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:"core:toggle-sidebar", selected: true}
]});
menuOptions.push(null);
menuOptions.push({id:"menu-item-import",label:RED._("menu.label.import"),options:[
{id:"menu-item-import-clipboard",label:RED._("menu.label.clipboard"),onselect:"core:show-import-dialog"},
{id:"menu-item-import-library",label:RED._("menu.label.library"),options:[]}
]});
menuOptions.push({id:"menu-item-export",label:RED._("menu.label.export"),disabled:true,options:[
{id:"menu-item-export-clipboard",label:RED._("menu.label.clipboard"),disabled:true,onselect:"core:show-export-dialog"},
{id:"menu-item-export-library",label:RED._("menu.label.library"),disabled:true,onselect:"core:library-export"}
]});
menuOptions.push(null);
menuOptions.push({id:"menu-item-search",label:RED._("menu.label.search"),onselect:"core:search"});
menuOptions.push(null);
menuOptions.push({id:"menu-item-config-nodes",label:RED._("menu.label.displayConfig"),onselect:"core:show-config-tab"});
menuOptions.push({id:"menu-item-workspace",label:RED._("menu.label.flows"),options:[
{id:"menu-item-workspace-add",label:RED._("menu.label.add"),onselect:"core:add-flow"},
{id:"menu-item-workspace-edit",label:RED._("menu.label.rename"),onselect:"core:edit-flow"},
{id:"menu-item-workspace-delete",label:RED._("menu.label.delete"),onselect:"core:remove-flow"}
]});
menuOptions.push({id:"menu-item-subflow",label:RED._("menu.label.subflows"), options: [
{id:"menu-item-subflow-create",label:RED._("menu.label.createSubflow"),onselect:"core:create-subflow"},
{id:"menu-item-subflow-convert",label:RED._("menu.label.selectionToSubflow"),disabled:true,onselect:"core:convert-to-subflow"},
]});
menuOptions.push(null);
if (RED.settings.theme('palette.editable') !== false) {
RED.palette.editor.init();
menuOptions.push({id:"menu-item-edit-palette",label:RED._("menu.label.editPalette"),onselect:"core:manage-palette"});
menuOptions.push(null);
}
menuOptions.push({id:"menu-item-keyboard-shortcuts",label:RED._("menu.label.keyboardShortcuts"),onselect:"core:show-help"});
menuOptions.push({id:"menu-item-show-tips",label:RED._("menu.label.showTips"),toggle:true,selected:true,onselect:"core:toggle-show-tips"});
menuOptions.push({id:"menu-item-help",
label: RED.settings.theme("menu.menu-item-help.label","Node-RED website"),
href: RED.settings.theme("menu.menu-item-help.url","http://nodered.org/docs")
});
menuOptions.push({id:"menu-item-node-red-version", label:"v"+RED.settings.version, onselect: "core:show-about" });
RED.user.init();
RED.library.init();
RED.palette.init();
RED.sidebar.init();
RED.subflow.init();
RED.workspaces.init();
RED.clipboard.init();
RED.search.init();
RED.view.init();
RED.editor.init();
RED.keyboard.init();
RED.diff.init();
RED.menu.init({id:"btn-sidemenu",options: menuOptions});
RED.deploy.init(RED.settings.theme("deployButton",null));
RED.keyboard.add("workspace", /* ? */ 191,{shift:true},function() {RED.keyboard.showHelp();d3.event.preventDefault();});
RED.actions.add("core:show-about", showAbout);
RED.comms.connect();
$("#main-container").show();
$(".header-toolbar").show();
loadNodeList();
}
@@ -243,8 +273,4 @@ var RED = (function() {
RED.settings.init(loadEditor);
})
});
return {
};
})();

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2013, 2016 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,9 @@ RED.nodes = (function() {
var workspaces = {};
var workspacesOrder =[];
var subflows = {};
var loadedFlowVersion = null;
var initialLoad;
var dirty = false;
@@ -32,15 +35,32 @@ RED.nodes = (function() {
}
var registry = (function() {
var moduleList = {};
var nodeList = [];
var nodeSets = {};
var typeToId = {};
var nodeDefinitions = {};
var exports = {
setModulePendingUpdated: function(module,version) {
moduleList[module].pending_version = version;
RED.events.emit("registry:module-updated",{module:module,version:version});
},
getModule: function(module) {
return moduleList[module];
},
getNodeSetForType: function(nodeType) {
return exports.getNodeSet(typeToId[nodeType]);
},
getModuleList: function() {
return moduleList;
},
getNodeList: function() {
return nodeList;
},
getNodeTypes: function() {
return Object.keys(nodeDefinitions);
},
setNodeList: function(list) {
nodeList = [];
for(var i=0;i<list.length;i++) {
@@ -55,27 +75,36 @@ RED.nodes = (function() {
typeToId[ns.types[j]] = ns.id;
}
nodeList.push(ns);
moduleList[ns.module] = moduleList[ns.module] || {
name:ns.module,
version:ns.version,
local:ns.local,
sets:{}
};
if (ns.pending_version) {
moduleList[ns.module].pending_version = ns.pending_version;
}
moduleList[ns.module].sets[ns.name] = ns;
RED.events.emit("registry:node-set-added",ns);
},
removeNodeSet: function(id) {
var ns = nodeSets[id];
for (var j=0;j<ns.types.length;j++) {
if (ns.added) {
// TODO: too tightly coupled into palette UI
RED.palette.remove(ns.types[j]);
var def = nodeDefinitions[ns.types[j]];
if (def.onpaletteremove && typeof def.onpaletteremove === "function") {
def.onpaletteremove.call(def);
}
}
delete typeToId[ns.types[j]];
}
delete nodeSets[id];
for (var i=0;i<nodeList.length;i++) {
if (nodeList[i].id == id) {
if (nodeList[i].id === id) {
nodeList.splice(i,1);
break;
}
}
delete moduleList[ns.module].sets[ns.name];
if (Object.keys(moduleList[ns.module].sets).length === 0) {
delete moduleList[ns.module];
}
RED.events.emit("registry:node-set-removed",ns);
return ns;
},
getNodeSet: function(id) {
@@ -84,32 +113,20 @@ RED.nodes = (function() {
enableNodeSet: function(id) {
var ns = nodeSets[id];
ns.enabled = true;
for (var j=0;j<ns.types.length;j++) {
// TODO: too tightly coupled into palette UI
RED.palette.show(ns.types[j]);
var def = nodeDefinitions[ns.types[j]];
if (def.onpaletteadd && typeof def.onpaletteadd === "function") {
def.onpaletteadd.call(def);
}
}
RED.events.emit("registry:node-set-enabled",ns);
},
disableNodeSet: function(id) {
var ns = nodeSets[id];
ns.enabled = false;
for (var j=0;j<ns.types.length;j++) {
// TODO: too tightly coupled into palette UI
RED.palette.hide(ns.types[j]);
var def = nodeDefinitions[ns.types[j]];
if (def.onpaletteremove && typeof def.onpaletteremove === "function") {
def.onpaletteremove.call(def);
}
}
RED.events.emit("registry:node-set-disabled",ns);
},
registerNodeType: function(nt,def) {
nodeDefinitions[nt] = def;
def.type = nt;
if (def.category != "subflows") {
def.set = nodeSets[typeToId[nt]];
nodeSets[typeToId[nt]].added = true;
nodeSets[typeToId[nt]].enabled = true;
var ns;
if (def.set.module === "node-red") {
@@ -119,18 +136,20 @@ RED.nodes = (function() {
}
def["_"] = function() {
var args = Array.prototype.slice.call(arguments, 0);
var original = args[0];
if (args[0].indexOf(":") === -1) {
args[0] = ns+":"+args[0];
}
return RED._.apply(null,args);
var result = RED._.apply(null,args);
if (result === args[0]) {
result = original;
}
return result;
}
// TODO: too tightly coupled into palette UI
}
RED.palette.add(nt,def);
if (def.onpaletteadd && typeof def.onpaletteadd === "function") {
def.onpaletteadd.call(def);
}
RED.events.emit("registry:node-type-added",nt);
},
removeNodeType: function(nt) {
if (nt.substring(0,8) != "subflow:") {
@@ -138,7 +157,7 @@ RED.nodes = (function() {
throw new Error("this api is subflow only. called with:",nt);
}
delete nodeDefinitions[nt];
RED.palette.remove(nt);
RED.events.emit("registry:node-type-removed",nt);
},
getNodeType: function(nt) {
return nodeDefinitions[nt];
@@ -154,11 +173,14 @@ RED.nodes = (function() {
function addNode(n) {
if (n.type.indexOf("subflow") !== 0) {
n["_"] = n._def._;
} else {
n["_"] = RED._;
}
if (n._def.category == "config") {
configNodes[n.id] = n;
} else {
n.ports = [];
if (n.wires && (n.wires.length > n.outputs)) { n.outputs = n.wires.length; }
if (n.outputs) {
for (var i=0;i<n.outputs;i++) {
n.ports.push(i);
@@ -309,7 +331,6 @@ RED.nodes = (function() {
});
sf.name = subflowName;
}
subflows[sf.id] = sf;
RED.nodes.registerType("subflow:"+sf.id, {
defaults:{name:{value:""}},
@@ -322,12 +343,13 @@ RED.nodes = (function() {
label: function() { return this.name||RED.nodes.subflow(sf.id).name },
labelStyle: function() { return this.name?"node_label_italic":""; },
paletteLabel: function() { return RED.nodes.subflow(sf.id).name },
inputLabels: function(i) { return sf.inputLabels?sf.inputLabels[i]:null },
outputLabels: function(i) { return sf.outputLabels?sf.outputLabels[i]:null },
set:{
module: "node-red"
}
});
sf._def = RED.nodes.getType("subflow:"+sf.id);
}
function getSubflow(id) {
return subflows[id];
@@ -396,11 +418,15 @@ RED.nodes = (function() {
* Converts a node to an exportable JSON Object
**/
function convertNode(n, exportCreds) {
if (n.type === 'tab') {
return convertWorkspace(n);
}
exportCreds = exportCreds || false;
var node = {};
node.id = n.id;
node.type = n.type;
node.z = n.z;
if (node.type == "unknown") {
for (var p in n._orig) {
if (n._orig.hasOwnProperty(p)) {
@@ -419,11 +445,12 @@ RED.nodes = (function() {
for (var cred in n._def.credentials) {
if (n._def.credentials.hasOwnProperty(cred)) {
if (n._def.credentials[cred].type == 'password') {
if (n.credentials["has_"+cred] != n.credentials._["has_"+cred] ||
if (!n.credentials._ ||
n.credentials["has_"+cred] != n.credentials._["has_"+cred] ||
(n.credentials["has_"+cred] && n.credentials[cred])) {
credentialSet[cred] = n.credentials[cred];
}
} else if (n.credentials[cred] != null && n.credentials[cred] != n.credentials._[cred]) {
} else if (n.credentials[cred] != null && (!n.credentials._ || n.credentials[cred] != n.credentials._[cred])) {
credentialSet[cred] = n.credentials[cred];
}
}
@@ -447,6 +474,13 @@ RED.nodes = (function() {
node.wires[w.sourcePort].push(w.target.id);
}
}
if (n.inputs > 0 && n.inputLabels && !/^\s*$/.test(n.inputLabels.join(""))) {
node.inputLabels = n.inputLabels.slice();
}
if (n.outputs > 0 && n.outputLabels && !/^\s*$/.test(n.outputLabels.join(""))) {
node.outputLabels = n.outputLabels.slice();
}
}
return node;
}
@@ -484,6 +518,13 @@ RED.nodes = (function() {
node.out.push(nOut);
});
if (node.in.length > 0 && n.inputLabels && !/^\s*$/.test(n.inputLabels.join(""))) {
node.inputLabels = n.inputLabels.slice();
}
if (node.out.length > 0 && n.outputLabels && !/^\s*$/.test(n.outputLabels.join(""))) {
node.outputLabels = n.outputLabels.slice();
}
return node;
}
@@ -537,7 +578,10 @@ RED.nodes = (function() {
}
//TODO: rename this (createCompleteNodeSet)
function createCompleteNodeSet() {
function createCompleteNodeSet(exportCredentials) {
if (exportCredentials === undefined) {
exportCredentials = true;
}
var nns = [];
var i;
for (i=0;i<workspacesOrder.length;i++) {
@@ -552,16 +596,55 @@ RED.nodes = (function() {
}
for (i in configNodes) {
if (configNodes.hasOwnProperty(i)) {
nns.push(convertNode(configNodes[i], true));
nns.push(convertNode(configNodes[i], exportCredentials));
}
}
for (i=0;i<nodes.length;i++) {
var node = nodes[i];
nns.push(convertNode(node, true));
nns.push(convertNode(node, exportCredentials));
}
return nns;
}
function checkForMatchingSubflow(subflow,subflowNodes) {
var i;
var match = null;
try {
RED.nodes.eachSubflow(function(sf) {
if (sf.name != subflow.name ||
sf.info != subflow.info ||
sf.in.length != subflow.in.length ||
sf.out.length != subflow.out.length) {
return;
}
var sfNodes = RED.nodes.filterNodes({z:sf.id});
if (sfNodes.length != subflowNodes.length) {
return;
}
var subflowNodeSet = [subflow].concat(subflowNodes);
var sfNodeSet = [sf].concat(sfNodes);
var exportableSubflowNodes = JSON.stringify(subflowNodeSet);
var exportableSFNodes = JSON.stringify(createExportableNodeSet(sfNodeSet));
var nodeMap = {};
for (i=0;i<sfNodes.length;i++) {
exportableSubflowNodes = exportableSubflowNodes.replace(new RegExp("\""+subflowNodes[i].id+"\"","g"),'"'+sfNodes[i].id+'"');
}
exportableSubflowNodes = exportableSubflowNodes.replace(new RegExp("\""+subflow.id+"\"","g"),'"'+sf.id+'"');
if (exportableSubflowNodes !== exportableSFNodes) {
return;
}
match = sf;
throw new Error();
});
} catch(err) {
console.log(err.stack);
}
return match;
}
function compareNodes(nodeA,nodeB,idMustMatch) {
if (idMustMatch && nodeA.id != nodeB.id) {
return false;
@@ -591,10 +674,11 @@ RED.nodes = (function() {
return true;
}
function importNodes(newNodesObj,createNewIds) {
function importNodes(newNodesObj,createNewIds,createMissingWorkspace) {
var i;
var n;
var newNodes;
var nodeZmap = {};
if (typeof newNodesObj === "string") {
if (newNodesObj === "") {
return;
@@ -613,6 +697,9 @@ RED.nodes = (function() {
if (!$.isArray(newNodes)) {
newNodes = [newNodes];
}
if (!initialLoad) {
initialLoad = JSON.parse(JSON.stringify(newNodes));
}
var unknownTypes = [];
for (i=0;i<newNodes.length;i++) {
n = newNodes[i];
@@ -625,6 +712,11 @@ RED.nodes = (function() {
unknownTypes.indexOf(n.type)==-1) {
unknownTypes.push(n.type);
}
if (n.z) {
nodeZmap[n.z] = nodeZmap[n.z] || [];
nodeZmap[n.z].push(n);
}
}
if (unknownTypes.length > 0) {
var typeList = "<ul><li>"+unknownTypes.join("</li><li>")+"</li></ul>";
@@ -633,17 +725,19 @@ RED.nodes = (function() {
}
var activeWorkspace = RED.workspaces.active();
//TODO: check the z of the subflow instance and check _that_ if it exists
var activeSubflow = getSubflow(activeWorkspace);
if (activeSubflow) {
for (i=0;i<newNodes.length;i++) {
var m = /^subflow:(.+)$/.exec(newNodes[i].type);
if (m) {
var subflowId = m[1];
for (i=0;i<newNodes.length;i++) {
var m = /^subflow:(.+)$/.exec(newNodes[i].type);
if (m) {
var subflowId = m[1];
var parent = getSubflow(newNodes[i].z || activeWorkspace);
if (parent) {
var err;
if (subflowId === activeSubflow.id) {
if (subflowId === parent.id) {
err = new Error(RED._("notification.errors.cannotAddSubflowToItself"));
}
if (subflowContains(m[1],activeSubflow.id)) {
if (subflowContains(subflowId,parent.id)) {
err = new Error(RED._("notification.errors.cannotAddCircularReference"));
}
if (err) {
@@ -659,12 +753,15 @@ RED.nodes = (function() {
var workspace_map = {};
var new_subflows = [];
var subflow_map = {};
var subflow_blacklist = {};
var node_map = {};
var new_nodes = [];
var new_links = [];
var nid;
var def;
var configNode;
var missingWorkspace = null;
var d;
// Find all tabs and subflow templates
for (i=0;i<newNodes.length;i++) {
@@ -686,28 +783,33 @@ RED.nodes = (function() {
RED.workspaces.add(n);
new_workspaces.push(n);
} else if (n.type === "subflow") {
subflow_map[n.id] = n;
if (createNewIds) {
nid = getID();
n.id = nid;
var matchingSubflow = checkForMatchingSubflow(n,nodeZmap[n.id]);
if (matchingSubflow) {
subflow_blacklist[n.id] = matchingSubflow;
} else {
subflow_map[n.id] = n;
if (createNewIds) {
nid = getID();
n.id = nid;
}
// TODO: handle createNewIds - map old to new subflow ids
n.in.forEach(function(input,i) {
input.type = "subflow";
input.direction = "in";
input.z = n.id;
input.i = i;
input.id = getID();
});
n.out.forEach(function(output,i) {
output.type = "subflow";
output.direction = "out";
output.z = n.id;
output.i = i;
output.id = getID();
});
new_subflows.push(n);
addSubflow(n,createNewIds);
}
// TODO: handle createNewIds - map old to new subflow ids
n.in.forEach(function(input,i) {
input.type = "subflow";
input.direction = "in";
input.z = n.id;
input.i = i;
input.id = getID();
});
n.out.forEach(function(output,i) {
output.type = "subflow";
output.direction = "out";
output.z = n.id;
output.i = i;
output.id = getID();
});
new_subflows.push(n);
addSubflow(n,createNewIds);
}
}
@@ -728,12 +830,22 @@ RED.nodes = (function() {
var existingConfigNode = null;
if (createNewIds) {
if (n.z) {
if (subflow_map[n.z]) {
if (subflow_blacklist[n.z]) {
continue;
} else if (subflow_map[n.z]) {
n.z = subflow_map[n.z].id;
} else {
n.z = workspace_map[n.z];
if (!workspaces[n.z]) {
n.z = activeWorkspace;
if (createMissingWorkspace) {
if (missingWorkspace === null) {
missingWorkspace = RED.workspaces.add(null,true);
new_workspaces.push(missingWorkspace);
}
n.z = missingWorkspace.id;
} else {
n.z = activeWorkspace;
}
}
}
}
@@ -757,10 +869,19 @@ RED.nodes = (function() {
}
if (!existingConfigNode) { //} || !compareNodes(existingConfigNode,n,true) || existingConfigNode._def.exclusive || existingConfigNode.z !== n.z) {
configNode = {id:n.id, z:n.z, type:n.type, users:[]};
for (var d in def.defaults) {
configNode = {id:n.id, z:n.z, type:n.type, users:[], _config:{}};
for (d in def.defaults) {
if (def.defaults.hasOwnProperty(d)) {
configNode[d] = n[d];
configNode._config[d] = JSON.stringify(n[d]);
}
}
if (def.hasOwnProperty('credentials') && n.hasOwnProperty('credentials')) {
configNode.credentials = {};
for (d in def.credentials) {
if (def.credentials.hasOwnProperty(d) && n.credentials.hasOwnProperty(d)) {
configNode.credentials[d] = n.credentials[d];
}
}
}
configNode.label = def.label;
@@ -782,28 +903,56 @@ RED.nodes = (function() {
if (n.type !== "workspace" && n.type !== "tab" && n.type !== "subflow") {
def = registry.getNodeType(n.type);
if (!def || def.category != "config") {
var node = {x:n.x,y:n.y,z:n.z,type:0,wires:n.wires,changed:false};
var node = {
x:n.x,
y:n.y,
z:n.z,
type:0,
wires:n.wires,
inputLabels: n.inputLabels,
outputLabels: n.outputLabels,
changed:false,
_config:{}
};
if (createNewIds) {
if (subflow_map[node.z]) {
if (subflow_blacklist[n.z]) {
continue;
} else if (subflow_map[node.z]) {
node.z = subflow_map[node.z].id;
} else {
node.z = workspace_map[node.z];
if (!workspaces[node.z]) {
node.z = activeWorkspace;
if (createMissingWorkspace) {
if (missingWorkspace === null) {
missingWorkspace = RED.workspaces.add(null,true);
new_workspaces.push(missingWorkspace);
}
node.z = missingWorkspace.id;
} else {
node.z = activeWorkspace;
}
}
}
node.id = getID();
} else {
node.id = n.id;
if (node.z == null || (!workspaces[node.z] && !subflow_map[node.z])) {
node.z = activeWorkspace;
if (createMissingWorkspace) {
if (missingWorkspace === null) {
missingWorkspace = RED.workspaces.add(null,true);
new_workspaces.push(missingWorkspace);
}
node.z = missingWorkspace.id;
} else {
node.z = activeWorkspace;
}
}
}
node.type = n.type;
node._def = def;
if (n.type.substring(0,7) === "subflow") {
var parentId = n.type.split(":")[1];
var subflow = subflow_map[parentId]||getSubflow(parentId);
var subflow = subflow_blacklist[parentId]||subflow_map[parentId]||getSubflow(parentId);
if (createNewIds) {
parentId = subflow.id;
node.type = "subflow:"+parentId;
@@ -844,9 +993,20 @@ RED.nodes = (function() {
if (node._def.category != "config") {
node.inputs = n.inputs||node._def.inputs;
node.outputs = n.outputs||node._def.outputs;
for (var d2 in node._def.defaults) {
if (node._def.defaults.hasOwnProperty(d2)) {
node[d2] = n[d2];
for (d in node._def.defaults) {
if (node._def.defaults.hasOwnProperty(d)) {
node[d] = n[d];
node._config[d] = JSON.stringify(n[d]);
}
}
node._config.x = node.x;
node._config.y = node.y;
if (node._def.hasOwnProperty('credentials') && n.hasOwnProperty('credentials')) {
node.credentials = {};
for (d in node._def.credentials) {
if (node._def.credentials.hasOwnProperty(d) && n.credentials.hasOwnProperty(d)) {
node.credentials[d] = n.credentials[d];
}
}
}
}
@@ -869,7 +1029,6 @@ RED.nodes = (function() {
"link out":"links"
}
// Remap all wires and config node references
for (i=0;i<new_nodes.length;i++) {
n = new_nodes[i];
@@ -877,7 +1036,7 @@ RED.nodes = (function() {
for (var w1=0;w1<n.wires.length;w1++) {
var wires = (n.wires[w1] instanceof Array)?n.wires[w1]:[n.wires[w1]];
for (var w2=0;w2<wires.length;w2++) {
if (wires[w2] in node_map) {
if (node_map.hasOwnProperty(wires[w2])) {
var link = {source:n,sourcePort:w1,target:node_map[wires[w2]]};
addLink(link);
new_links.push(link);
@@ -912,6 +1071,10 @@ RED.nodes = (function() {
return (otherNode && otherNode.z === activeWorkspace)
});
}
// With all properties now remapped to point at valid nodes,
// we can validate the node
RED.editor.validateNode(n);
}
for (i=0;i<new_subflows.length;i++) {
n = new_subflows[i];
@@ -939,7 +1102,7 @@ RED.nodes = (function() {
}
RED.workspaces.refresh();
return [new_nodes,new_links,new_workspaces,new_subflows];
return [new_nodes,new_links,new_workspaces,new_subflows,missingWorkspace];
}
// TODO: supports filter.z|type
@@ -1007,6 +1170,46 @@ RED.nodes = (function() {
}
}
function flowVersion(version) {
if (version !== undefined) {
loadedFlowVersion = version;
} else {
return loadedFlowVersion;
}
}
function clear() {
nodes = [];
links = [];
configNodes = {};
workspacesOrder = [];
var subflowIds = Object.keys(subflows);
subflowIds.forEach(function(id) {
RED.subflow.removeSubflow(id)
});
var workspaceIds = Object.keys(workspaces);
workspaceIds.forEach(function(id) {
RED.workspaces.remove(workspaces[id]);
});
defaultWorkspace = null;
RED.nodes.dirty(true);
RED.view.redraw(true);
RED.palette.refresh();
RED.workspaces.refresh();
RED.sidebar.config.refresh();
// var node_defs = {};
// var nodes = [];
// var configNodes = {};
// var links = [];
// var defaultWorkspace;
// var workspaces = {};
// var workspacesOrder =[];
// var subflows = {};
// var loadedFlowVersion = null;
}
return {
registry:registry,
setNodeList: registry.setNodeList,
@@ -1023,6 +1226,7 @@ RED.nodes = (function() {
add: addNode,
remove: removeNode,
clear: clear,
addLink: addLink,
removeLink: removeLink,
@@ -1070,6 +1274,15 @@ RED.nodes = (function() {
node: getNode,
version: flowVersion,
originalFlow: function(flow) {
if (flow === undefined) {
return initialLoad;
} else {
initialLoad = flow;
}
},
filterNodes: filterNodes,
filterLinks: filterLinks,

16
editor/js/red.js Normal file
View File

@@ -0,0 +1,16 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
var RED = {};

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2014 IBM, Antoine Aflalo
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -84,6 +84,7 @@ RED.settings = (function () {
if (auth_tokens) {
jqXHR.setRequestHeader("Authorization","Bearer "+auth_tokens.access_token);
}
jqXHR.setRequestHeader("Node-RED-API-Version","v2");
}
}
});

130
editor/js/text/bidi.js Normal file
View File

@@ -0,0 +1,130 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
RED.text = {};
RED.text.bidi = (function() {
var textDir = "";
var LRE = "\u202A",
RLE = "\u202B",
PDF = "\u202C";
function isRTLValue(stringValue) {
var length = stringValue.length;
for (var i=0;i<length;i++) {
if (isBidiChar(stringValue.charCodeAt(i))) {
return true;
}
else if(isLatinChar(stringValue.charCodeAt(i))) {
return false;
}
}
return false;
}
function isBidiChar(c) {
return (c >= 0x05d0 && c <= 0x05ff)||
(c >= 0x0600 && c <= 0x065f)||
(c >= 0x066a && c <= 0x06ef)||
(c >= 0x06fa && c <= 0x07ff)||
(c >= 0xfb1d && c <= 0xfdff)||
(c >= 0xfe70 && c <= 0xfefc);
}
function isLatinChar(c){
return (c > 64 && c < 91)||(c > 96 && c < 123)
}
/**
* Determines the text direction of a given string.
* @param value - the string
*/
function resolveBaseTextDir(value) {
if (textDir == "auto") {
if (isRTLValue(value)) {
return "rtl";
} else {
return "ltr";
}
}
else {
return textDir;
}
}
function onInputChange() {
$(this).attr("dir", resolveBaseTextDir($(this).val()));
}
/**
* Adds event listeners to the Input to ensure its text-direction attribute
* is properly set based on its content.
* @param input - the input field
*/
function prepareInput(input) {
input.on("keyup",onInputChange).on("paste",onInputChange).on("cut",onInputChange);
// Set the initial text direction
onInputChange.call(input);
}
/**
* Enforces the text direction of a given string by adding
* UCC (Unicode Control Characters)
* @param value - the string
*/
function enforceTextDirectionWithUCC(value) {
if (value) {
var dir = resolveBaseTextDir(value);
if (dir == "ltr") {
return LRE + value + PDF;
}
else if (dir == "rtl") {
return RLE + value + PDF;
}
}
return value;
}
/**
* Enforces the text direction for all the spans with style bidiAware under
* workspace or sidebar div
*/
function enforceTextDirectionOnPage() {
$("#workspace").find('span.bidiAware').each(function() {
$(this).attr("dir", resolveBaseTextDir($(this).html()));
});
$("#sidebar").find('span.bidiAware').each(function() {
$(this).attr("dir", resolveBaseTextDir($(this).text()));
});
}
/**
* Sets the text direction preference
* @param dir - the text direction preference
*/
function setTextDirection(dir) {
textDir = dir;
RED.nodes.eachNode(function(n) { n.dirty = true;});
RED.view.redraw();
RED.palette.refresh();
enforceTextDirectionOnPage();
}
return {
setTextDirection: setTextDirection,
enforceTextDirectionWithUCC: enforceTextDirectionWithUCC,
resolveBaseTextDir: resolveBaseTextDir,
prepareInput: prepareInput
}
})();

1330
editor/js/text/format.js Normal file

File diff suppressed because it is too large Load Diff

35
editor/js/ui/actions.js Normal file
View File

@@ -0,0 +1,35 @@
RED.actions = (function() {
var actions = {
}
function addAction(name,handler) {
actions[name] = handler;
}
function removeAction(name) {
delete actions[name];
}
function getAction(name) {
return actions[name];
}
function invokeAction(name) {
if (actions.hasOwnProperty(name)) {
actions[name]();
}
}
function listActions() {
var result = [];
Object.keys(actions).forEach(function(action) {
var shortcut = RED.keyboard.getShortcut(action);
result.push({id:action,scope:shortcut?shortcut.scope:undefined,key:shortcut?shortcut.key:undefined})
})
return result;
}
return {
add: addAction,
remove: removeAction,
get: getAction,
invoke: invokeAction,
list: listActions
}
})();

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ RED.clipboard = (function() {
var dialogContainer;
var exportNodesDialog;
var importNodesDialog;
var disabled = false;
function setupDialogs() {
dialog = $('<div id="clipboard-dialog" class="hide node-red-dialog"><form class="dialog-form form-horizontal"></form></div>')
@@ -46,12 +47,24 @@ RED.clipboard = (function() {
$( this ).dialog( "close" );
}
},
{
id: "clipboard-dialog-copy",
class: "primary",
text: RED._("clipboard.export.copy"),
click: function() {
$("#clipboard-export").select();
document.execCommand("copy");
document.getSelection().removeAllRanges();
RED.notify(RED._("clipboard.nodesExported"));
$( this ).dialog( "close" );
}
},
{
id: "clipboard-dialog-ok",
class: "primary",
text: RED._("common.label.import"),
click: function() {
RED.view.importNodes($("#clipboard-import").val());
RED.view.importNodes($("#clipboard-import").val(),$("#import-tab > a.selected").attr('id') === 'import-tab-new');
$( this ).dialog( "close" );
}
}
@@ -65,18 +78,36 @@ RED.clipboard = (function() {
dialogContainer = dialog.children(".dialog-form");
exportNodesDialog = '<div class="form-row">'+
'<label for="node-input-export" style="display: block; width:100%;"><i class="fa fa-clipboard"></i> '+RED._("clipboard.nodes")+'</label>'+
'<textarea readonly style="resize: none; width: 100%; border-radius: 0px;font-family: monospace; font-size: 12px; background:#eee; padding-left: 0.5em; box-sizing:border-box;" id="clipboard-export" rows="5"></textarea>'+
exportNodesDialog =
'<div class="form-row">'+
'<label style="width:auto;margin-right: 10px;" data-i18n="clipboard.export.copy"></label>'+
'<span id="export-range-group" class="button-group">'+
'<a id="export-range-selected" class="editor-button toggle" href="#" data-i18n="clipboard.export.selected"></a>'+
'<a id="export-range-flow" class="editor-button toggle" href="#" data-i18n="clipboard.export.current"></a>'+
'<a id="export-range-full" class="editor-button toggle" href="#" data-i18n="clipboard.export.all"></a>'+
'</span>'+
'</div>'+
'<div class="form-row">'+
'<textarea readonly style="resize: none; width: 100%; border-radius: 4px;font-family: monospace; font-size: 12px; background:#f3f3f3; padding-left: 0.5em; box-sizing:border-box;" id="clipboard-export" rows="5"></textarea>'+
'</div>'+
'<div class="form-tips">'+
RED._("clipboard.selectNodes")+
'<div class="form-row" style="text-align: right;">'+
'<span id="export-format-group" class="button-group">'+
'<a id="export-format-mini" class="editor-button editor-button-small toggle" href="#" data-i18n="clipboard.export.compact"></a>'+
'<a id="export-format-full" class="editor-button editor-button-small toggle" href="#" data-i18n="clipboard.export.formatted"></a>'+
'</span>'+
'</div>';
importNodesDialog = '<div class="form-row">'+
'<textarea style="resize: none; width: 100%; border-radius: 0px;font-family: monospace; font-size: 12px; background:#eee; padding-left: 0.5em; box-sizing:border-box;" id="clipboard-import" rows="5" placeholder="'+
RED._("clipboard.pasteNodes")+
'"></textarea>'+
'</div>'+
'<div class="form-row">'+
'<label style="width:auto;margin-right: 10px;" data-i18n="clipboard.import.import"></label>'+
'<span id="import-tab" class="button-group">'+
'<a id="import-tab-current" class="editor-button toggle selected" href="#" data-i18n="clipboard.export.current"></a>'+
'<a id="import-tab-new" class="editor-button toggle" href="#" data-i18n="clipboard.import.newFlow"></a>'+
'</span>'+
'</div>';
}
@@ -98,49 +129,143 @@ RED.clipboard = (function() {
}
function importNodes() {
if (disabled) {
return;
}
dialogContainer.empty();
dialogContainer.append($(importNodesDialog));
dialogContainer.i18n();
$("#clipboard-dialog-ok").show();
$("#clipboard-dialog-cancel").show();
$("#clipboard-dialog-close").hide();
$("#clipboard-dialog-copy").hide();
$("#clipboard-dialog-ok").button("disable");
$("#clipboard-import").keyup(validateImport);
$("#clipboard-import").on('paste',function() { setTimeout(validateImport,10)});
$("#import-tab > a").click(function(evt) {
evt.preventDefault();
if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
return;
}
$(this).parent().children().removeClass('selected');
$(this).addClass('selected');
});
dialog.dialog("option","title",RED._("clipboard.importNodes")).dialog("open");
}
function exportNodes() {
if (disabled) {
return;
}
dialogContainer.empty();
dialogContainer.append($(exportNodesDialog));
dialogContainer.i18n();
$("#export-format-group > a").click(function(evt) {
evt.preventDefault();
if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
return;
}
$(this).parent().children().removeClass('selected');
$(this).addClass('selected');
var flow = $("#clipboard-export").val();
if (flow.length > 0) {
var nodes = JSON.parse(flow);
var format = $(this).attr('id');
if (format === 'export-format-full') {
flow = JSON.stringify(nodes,null,4);
} else {
flow = JSON.stringify(nodes);
}
$("#clipboard-export").val(flow);
}
});
$("#export-range-group > a").click(function(evt) {
evt.preventDefault();
if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
return;
}
$(this).parent().children().removeClass('selected');
$(this).addClass('selected');
var type = $(this).attr('id');
var flow = "";
var nodes = null;
if (type === 'export-range-selected') {
var selection = RED.view.selection();
nodes = RED.nodes.createExportableNodeSet(selection.nodes);
} else if (type === 'export-range-flow') {
var activeWorkspace = RED.workspaces.active();
nodes = RED.nodes.filterNodes({z:activeWorkspace});
var parentNode = RED.nodes.workspace(activeWorkspace)||RED.nodes.subflow(activeWorkspace);
nodes.unshift(parentNode);
nodes = RED.nodes.createExportableNodeSet(nodes);
} else if (type === 'export-range-full') {
nodes = RED.nodes.createCompleteNodeSet(false);
}
if (nodes !== null) {
if (RED.settings.flowFilePretty) {
flow = JSON.stringify(nodes,null,4);
} else {
flow = JSON.stringify(nodes);
}
}
if (flow.length > 0) {
$("#export-copy").removeClass('disabled');
} else {
$("#export-copy").addClass('disabled');
}
$("#clipboard-export").val(flow);
})
$("#clipboard-dialog-ok").hide();
$("#clipboard-dialog-cancel").hide();
$("#clipboard-dialog-close").show();
$("#clipboard-dialog-copy").hide();
$("#clipboard-dialog-close").hide();
var selection = RED.view.selection();
if (selection.nodes) {
var nns = RED.nodes.createExportableNodeSet(selection.nodes);
if (RED.settings.flowFilePretty) {
nns = JSON.stringify(nns,null,4);
} else {
nns = JSON.stringify(nns);
}
$("#clipboard-export")
.val(nns)
.focus(function() {
var textarea = $(this);
textarea.select();
textarea.mouseup(function() {
textarea.unbind("mouseup");
return false;
})
});
dialog.dialog("option","title",RED._("clipboard.exportNodes")).dialog( "open" );
$("#export-range-selected").click();
} else {
$("#export-range-selected").addClass('disabled').removeClass('selected');
$("#export-range-flow").click();
}
if (RED.settings.flowFilePretty) {
$("#export-format-full").click();
} else {
$("#export-format-mini").click();
}
$("#clipboard-export")
.focus(function() {
var textarea = $(this);
textarea.select();
textarea.mouseup(function() {
textarea.unbind("mouseup");
return false;
})
});
dialog.dialog("option","title",RED._("clipboard.exportNodes")).dialog( "open" );
setTimeout(function() {
$("#clipboard-export").focus();
if (!document.queryCommandEnabled("copy")) {
$("#clipboard-dialog-cancel").hide();
$("#clipboard-dialog-close").show();
} else {
$("#clipboard-dialog-cancel").show();
$("#clipboard-dialog-copy").show();
}
},0);
}
function hideDropTarget() {
$("#dropTarget").hide();
RED.keyboard.remove(/* ESCAPE */ 27);
RED.keyboard.remove("escape");
}
return {
@@ -157,18 +282,32 @@ RED.clipboard = (function() {
RED.menu.setDisabled("menu-item-export-library",false);
}
});
RED.keyboard.add("workspace", /* e */ 69,{ctrl:true},function(){exportNodes();d3.event.preventDefault();});
RED.keyboard.add("workspace", /* i */ 73,{ctrl:true},function(){importNodes();d3.event.preventDefault();});
RED.actions.add("core:show-export-dialog",exportNodes);
RED.actions.add("core:show-import-dialog",importNodes);
RED.events.on("editor:open",function() { disabled = true; });
RED.events.on("editor:close",function() { disabled = false; });
RED.events.on("search:open",function() { disabled = true; });
RED.events.on("search:close",function() { disabled = false; });
RED.events.on("type-search:open",function() { disabled = true; });
RED.events.on("type-search:close",function() { disabled = false; });
RED.events.on("palette-editor:open",function() { disabled = true; });
RED.events.on("palette-editor:close",function() { disabled = false; });
$('#chart').on("dragenter",function(event) {
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 ||
$.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
$("#dropTarget").css({display:'table'});
RED.keyboard.add("*", /* ESCAPE */ 27,hideDropTarget);
RED.keyboard.add("*", "escape" ,hideDropTarget);
}
});
$('#dropTarget').on("dragover",function(event) {
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 ||
$.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
event.preventDefault();
}
})
@@ -176,10 +315,24 @@ RED.clipboard = (function() {
hideDropTarget();
})
.on("drop",function(event) {
var data = event.originalEvent.dataTransfer.getData("text/plain");
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
var data = event.originalEvent.dataTransfer.getData("text/plain");
data = data.substring(data.indexOf('['),data.lastIndexOf(']')+1);
RED.view.importNodes(data);
} else if ($.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
var files = event.originalEvent.dataTransfer.files;
if (files.length === 1) {
var file = files[0];
var reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
RED.view.importNodes(e.target.result);
};
})(file);
reader.readAsText(file);
}
}
hideDropTarget();
data = data.substring(data.indexOf('['),data.lastIndexOf(']')+1);
RED.view.importNodes(data);
event.preventDefault();
});

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2016 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,6 +27,9 @@
* - removable : boolean - whether to display delete button on items
* - addItem : function(row,index,itemData) - when an item is added
* - removeItem : function(itemData) - called when an item is removed
* - filter : function(itemData) - called for each item to determine if it should be shown
* - sort : function(itemDataA,itemDataB) - called to sort items
* - scrollOnAdd : boolean - whether to scroll to newly added items
* methods:
* - addItem(itemData)
* - removeItem(itemData)
@@ -34,6 +37,9 @@
* - height(height)
* - items()
* - empty()
* - filter(filter)
* - sort(sort)
* - length()
*/
$.widget( "nodered.editableList", {
_create: function() {
@@ -66,11 +72,30 @@
that.addItem({});
});
}
if (this.element.css("position") === "absolute") {
["top","left","bottom","right"].forEach(function(s) {
var v = that.element.css(s);
if (s!=="auto" && s!=="") {
that.topContainer.css(s,v);
that.uiContainer.css(s,"0");
that.element.css(s,'auto');
}
})
this.element.css("position","static");
this.topContainer.css("position","absolute");
this.uiContainer.css("position","absolute");
}
this.uiContainer.addClass("red-ui-editableList-container");
this.uiHeight = this.element.height();
this.activeFilter = this.options.filter||null;
this.activeSort = this.options.sort||null;
this.scrollOnAdd = this.options.scrollOnAdd;
if (this.scrollOnAdd === undefined) {
this.scrollOnAdd = true;
}
var minHeight = this.element.css("minHeight");
if (minHeight !== '0px') {
this.uiContainer.css("minHeight",minHeight);
@@ -141,6 +166,42 @@
},
_destroy: function() {
},
_refreshFilter: function() {
var that = this;
var count = 0;
if (!this.activeFilter) {
this.element.children().show();
}
var items = this.items();
items.each(function (i,el) {
var data = el.data('data');
try {
if (that.activeFilter(data)) {
el.parent().show();
count++;
} else {
el.parent().hide();
}
} catch(err) {
console.log(err);
el.parent().show();
count++;
}
});
return count;
},
_refreshSort: function() {
if (this.activeSort) {
var items = this.element.children();
var that = this;
items.sort(function(A,B) {
return that.activeSort($(A).find(".red-ui-editableList-item-content").data('data'),$(B).find(".red-ui-editableList-item-content").data('data'));
});
$.each(items,function(idx,li) {
that.element.append(li);
})
}
},
width: function(desiredWidth) {
this.uiWidth = desiredWidth;
this._resize();
@@ -152,7 +213,23 @@
addItem: function(data) {
var that = this;
data = data || {};
var li = $('<li>').appendTo(this.element);
var li = $('<li>');
var added = false;
if (this.activeSort) {
var items = this.items();
var skip = false;
items.each(function(i,el) {
if (added) { return }
var itemData = el.data('data');
if (that.activeSort(data,itemData) < 0) {
li.insertBefore(el.closest("li"));
added = true;
}
});
}
if (!added) {
li.appendTo(this.element);
}
var row = $('<div/>').addClass("red-ui-editableList-item-content").appendTo(li);
row.data('data',data);
if (this.options.sortable === true) {
@@ -163,12 +240,14 @@
var deleteButton = $('<a/>',{href:"#",class:"red-ui-editableList-item-remove editor-button editor-button-small"}).appendTo(li);
$('<i/>',{class:"fa fa-remove"}).appendTo(deleteButton);
li.addClass("red-ui-editableList-item-removable");
deleteButton.click(function() {
deleteButton.click(function(evt) {
evt.preventDefault();
var data = row.data('data');
li.addClass("red-ui-editableList-item-deleting")
li.fadeOut(300, function() {
$(this).remove();
if (that.options.removeItem) {
that.options.removeItem(row.data('data'));
that.options.removeItem(data);
}
});
});
@@ -177,9 +256,20 @@
var index = that.element.children().length-1;
setTimeout(function() {
that.options.addItem(row,index,data);
setTimeout(function() {
that.uiContainer.scrollTop(that.element.height());
},0);
if (that.activeFilter) {
try {
if (!that.activeFilter(data)) {
li.hide();
}
} catch(err) {
}
}
if (!that.activeSort && that.scrollOnAdd) {
setTimeout(function() {
that.uiContainer.scrollTop(that.element.height());
},0);
}
},0);
}
},
@@ -197,6 +287,21 @@
},
empty: function() {
this.element.empty();
},
filter: function(filter) {
if (filter !== undefined) {
this.activeFilter = filter;
}
return this._refreshFilter();
},
sort: function(sort) {
if (sort !== undefined) {
this.activeSort = sort;
}
return this._refreshSort();
},
length: function() {
return this.element.children().length;
}
});
})(jQuery);

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2014, 2016 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,9 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
RED.menu = (function() {
var menuItems = {};
@@ -34,17 +31,17 @@ RED.menu = (function() {
var savedStateActive = isSavedStateActive(opt.id);
if (savedStateActive) {
link.addClass("active");
opt.onselect.call(opt, true);
triggerAction(opt.id,true);
} else if (savedStateActive === false) {
link.removeClass("active");
opt.onselect.call(opt, false);
triggerAction(opt.id,false);
} else if (opt.hasOwnProperty("selected")) {
if (opt.selected) {
link.addClass("active");
} else {
link.removeClass("active");
}
opt.onselect.call(opt, opt.selected);
triggerAction(opt.id,opt.selected);
}
}
@@ -107,10 +104,12 @@ RED.menu = (function() {
setSelected(opt.id, !selected);
}
} else {
opt.onselect.call(opt);
triggerAction(opt.id);
}
});
setInitialState();
if (opt.toggle) {
setInitialState();
}
} else if (opt.href) {
link.attr("target","_blank").attr("href",opt.href);
} else if (!opt.options) {
@@ -164,6 +163,19 @@ RED.menu = (function() {
}
}
function triggerAction(id, args) {
var opt = menuItems[id];
var callback = opt.onselect;
if (typeof opt.onselect === 'string') {
callback = RED.actions.get(opt.onselect);
}
if (callback) {
callback.call(opt,args);
} else {
console.log("No callback for",id,opt.onselect);
}
}
function isSavedStateActive(id) {
return RED.settings.get("menu-" + id);
}
@@ -187,11 +199,15 @@ RED.menu = (function() {
$("#"+id).removeClass("active");
}
if (opt && opt.onselect) {
opt.onselect.call(opt,state);
triggerAction(opt.id,state);
}
setSavedState(id, state);
}
function toggleSelected(id) {
setSelected(id,!isSelected(id));
}
function setDisabled(id,state) {
if (state) {
$("#"+id).parent().addClass("disabled");
@@ -231,16 +247,6 @@ RED.menu = (function() {
var opt = menuItems[id];
if (opt) {
opt.onselect = action;
// $("#"+id).click(function() {
// if ($(this).parent().hasClass("disabled")) {
// return;
// }
// if (menuItems[id].toggle) {
// setSelected(id,!isSelected(id));
// } else {
// menuItems[id].onselect.call(menuItems[id]);
// }
// });
}
}
@@ -248,6 +254,7 @@ RED.menu = (function() {
init: createMenu,
setSelected: setSelected,
isSelected: isSelected,
toggleSelected: toggleSelected,
setDisabled: setDisabled,
addItem: addItem,
removeItem: removeItem,

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -0,0 +1,96 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
(function($) {
$.widget( "nodered.searchBox", {
_create: function() {
var that = this;
this.currentTimeout = null;
this.lastSent = "";
this.element.val("");
this.uiContainer = this.element.wrap("<div>").parent();
this.uiContainer.addClass("red-ui-searchBox-container");
$('<i class="fa fa-search"></i>').prependTo(this.uiContainer);
this.clearButton = $('<a href="#"><i class="fa fa-times"></i></a>').appendTo(this.uiContainer);
this.clearButton.on("click",function(e) {
e.preventDefault();
that.element.val("");
that._change("",true);
that.element.focus();
});
this.resultCount = $('<span>',{class:"red-ui-searchBox-resultCount hide"}).appendTo(this.uiContainer);
this.element.val("");
this.element.on("keydown",function(evt) {
if (evt.keyCode === 27) {
that.element.val("");
}
})
this.element.on("keyup",function(evt) {
that._change($(this).val());
});
this.element.on("focus",function() {
$("body").one("mousedown",function() {
that.element.blur();
});
});
},
_change: function(val,instant) {
var fireEvent = false;
if (val === "") {
this.clearButton.hide();
fireEvent = true;
} else {
this.clearButton.show();
fireEvent = (val.length >= (this.options.minimumLength||0));
}
var current = this.element.val();
fireEvent = fireEvent && current !== this.lastSent;
if (fireEvent) {
if (!instant && this.options.delay > 0) {
clearTimeout(this.currentTimeout);
var that = this;
this.currentTimeout = setTimeout(function() {
that.lastSent = that.element.val();
that._trigger("change");
},this.options.delay);
} else {
this._trigger("change");
}
}
},
value: function(val) {
if (val === undefined) {
return this.element.val();
} else {
this.element.val(val);
this._change(val);
}
},
count: function(val) {
if (val === undefined || val === null || val === "") {
this.resultCount.text("").hide();
} else {
this.resultCount.text(val).show();
}
}
});
})(jQuery);

View File

@@ -0,0 +1,95 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
RED.stack = (function() {
function createStack(options) {
var container = options.container;
var entries = [];
return {
add: function(entry) {
entries.push(entry);
var entryContainer = $('<div class="palette-category">').appendTo(container);
var header = $('<div class="palette-header"></div>').appendTo(entryContainer);
var icon = $('<i class="fa fa-angle-down"></i>').appendTo(header);
$('<span></span>').html(entry.title).appendTo(header);
entry.content = $('<div class="editor-tray-content"></div>').appendTo(entryContainer);
if (entry.expanded) {
icon.addClass("expanded");
} else {
entry.content.hide();
}
header.click(function() {
if (options.singleExpanded) {
if (!entry.isExpanded()) {
for (var i=0;i<entries.length;i++) {
if (entries[i].isExpanded()) {
entries[i].collapse();
}
}
entry.expand();
}
} else {
entry.toggle();
}
});
entry.toggle = function() {
if (entry.isExpanded()) {
entry.collapse();
return false;
} else {
entry.expand();
return true;
}
};
entry.expand = function() {
if (!entry.isExpanded()) {
if (entry.onexpand) {
entry.onexpand.call(entry);
}
icon.addClass("expanded");
entry.content.slideDown(200);
return true;
}
};
entry.collapse = function() {
if (entry.isExpanded()) {
icon.removeClass("expanded");
entry.content.slideUp(200);
return true;
}
};
entry.isExpanded = function() {
return icon.hasClass("expanded");
};
return entry;
},
}
}
return {
create: createStack
}
})();

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2013, 2016 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,23 +17,86 @@
RED.tabs = (function() {
function createTabs(options) {
var tabs = {};
var currentTabWidth;
var currentActiveTabWidth = 0;
var ul = $("#"+options.id);
ul.addClass("red-ui-tabs");
var wrapper = ul.wrap( "<div>" ).parent();
var scrollContainer = ul.wrap( "<div>" ).parent();
wrapper.addClass("red-ui-tabs");
if (options.addButton && typeof options.addButton === 'function') {
wrapper.addClass("red-ui-tabs-add");
var addButton = $('<div class="red-ui-tab-button"><a href="#"><i class="fa fa-plus"></i></a></div>').appendTo(wrapper);
addButton.find('a').click(function(evt) {
evt.preventDefault();
options.addButton();
})
}
var scrollLeft;
var scrollRight;
if (options.scrollable) {
wrapper.addClass("red-ui-tabs-scrollable");
scrollContainer.addClass("red-ui-tabs-scroll-container");
scrollContainer.scroll(updateScroll);
scrollLeft = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-left"><a href="#" style="display:none;"><i class="fa fa-caret-left"></i></a></div>').appendTo(wrapper).find("a");
scrollLeft.on('mousedown',function(evt) { scrollEventHandler(evt,'-=150') }).on('click',function(evt){ evt.preventDefault();});
scrollRight = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-right"><a href="#" style="display:none;"><i class="fa fa-caret-right"></i></a></div>').appendTo(wrapper).find("a");
scrollRight.on('mousedown',function(evt) { scrollEventHandler(evt,'+=150') }).on('click',function(evt){ evt.preventDefault();});
}
function scrollEventHandler(evt,dir) {
evt.preventDefault();
if ($(this).hasClass('disabled')) {
return;
}
var currentScrollLeft = scrollContainer.scrollLeft();
scrollContainer.animate( { scrollLeft: dir }, 100);
var interval = setInterval(function() {
var newScrollLeft = scrollContainer.scrollLeft()
if (newScrollLeft === currentScrollLeft) {
clearInterval(interval);
return;
}
currentScrollLeft = newScrollLeft;
scrollContainer.animate( { scrollLeft: dir }, 100);
},100);
$(this).one('mouseup',function() {
clearInterval(interval);
})
}
ul.children().first().addClass("active");
ul.children().addClass("red-ui-tab");
function onTabClick() {
if (options.onclick) {
options.onclick(tabs[$(this).attr('href').slice(1)]);
}
activateTab($(this));
return false;
}
function updateScroll() {
if (ul.children().length !== 0) {
var sl = scrollContainer.scrollLeft();
var scWidth = scrollContainer.width();
var ulWidth = ul.width();
if (sl === 0) {
scrollLeft.hide();
} else {
scrollLeft.show();
}
if (sl === ulWidth-scWidth) {
scrollRight.hide();
} else {
scrollRight.show();
}
}
}
function onTabDblClick() {
if (options.ondblclick) {
options.ondblclick(tabs[$(this).attr('href').slice(1)]);
@@ -45,10 +108,21 @@ RED.tabs = (function() {
if (typeof link === "string") {
link = ul.find("a[href='#"+link+"']");
}
if (link.length === 0) {
return;
}
if (!link.parent().hasClass("active")) {
ul.children().removeClass("active");
ul.children().css({"transition": "width 100ms"});
link.parent().addClass("active");
if (options.scrollable) {
var pos = link.parent().position().left;
if (pos-21 < 0) {
scrollContainer.animate( { scrollLeft: '+='+(pos-50) }, 300);
} else if (pos + 120 > scrollContainer.width()) {
scrollContainer.animate( { scrollLeft: '+='+(pos + 140-scrollContainer.width()) }, 300);
}
}
if (options.onchange) {
options.onchange(tabs[link.attr('href').slice(1)]);
}
@@ -58,26 +132,44 @@ RED.tabs = (function() {
},100);
}
}
function activatePreviousTab() {
var previous = ul.find("li.active").prev();
if (previous.length > 0) {
activateTab(previous.find("a"));
}
}
function activateNextTab() {
var next = ul.find("li.active").next();
if (next.length > 0) {
activateTab(next.find("a"));
}
}
function updateTabWidths() {
var tabs = ul.find("li.red-ui-tab");
var width = ul.width();
var width = wrapper.width();
var tabCount = tabs.size();
var tabWidth = (width-12-(tabCount*6))/tabCount;
currentTabWidth = 100*tabWidth/width;
currentTabWidth = (100*tabWidth/width)+"%";
currentActiveTabWidth = currentTabWidth+"%";
if (options.hasOwnProperty("minimumActiveTabWidth")) {
if (options.scrollable) {
tabWidth = Math.max(tabWidth,140);
currentTabWidth = tabWidth+"px";
currentActiveTabWidth = 0;
var listWidth = Math.max(wrapper.width(),12+(tabWidth+6)*tabCount);
ul.width(listWidth);
updateScroll();
} else if (options.hasOwnProperty("minimumActiveTabWidth")) {
if (tabWidth < options.minimumActiveTabWidth) {
tabCount -= 1;
tabWidth = (width-12-options.minimumActiveTabWidth-(tabCount*6))/tabCount;
currentTabWidth = 100*tabWidth/width;
currentTabWidth = (100*tabWidth/width)+"%";
currentActiveTabWidth = options.minimumActiveTabWidth+"px";
} else {
currentActiveTabWidth = 0;
}
}
tabs.css({width:currentTabWidth+"%"});
tabs.css({width:currentTabWidth});
if (tabWidth < 50) {
ul.find(".red-ui-tab-close").hide();
ul.find(".red-ui-tab-icon").hide();
@@ -97,7 +189,9 @@ RED.tabs = (function() {
}
ul.find("li.red-ui-tab a").on("click",onTabClick).on("dblclick",onTabDblClick);
updateTabWidths();
setTimeout(function() {
updateTabWidths();
},0);
function removeTab(id) {
@@ -126,7 +220,8 @@ RED.tabs = (function() {
if (tab.icon) {
$('<img src="'+tab.icon+'" class="red-ui-tab-icon"/>').appendTo(link);
}
$('<span/>').text(tab.label).appendTo(link);
var span = $('<span/>',{class:"bidiAware"}).text(tab.label).appendTo(link);
span.attr('dir', RED.text.bidi.resolveBaseTextDir(tab.label));
link.on("click",onTabClick);
link.on("dblclick",onTabDblClick);
@@ -187,8 +282,8 @@ RED.tabs = (function() {
}
},
drag: function(event,ui) {
ui.position.left += tabElements[tabDragIndex].left;
var tabCenter = ui.position.left + tabElements[tabDragIndex].width/2;
ui.position.left += tabElements[tabDragIndex].left+scrollContainer.scrollLeft();
var tabCenter = ui.position.left + tabElements[tabDragIndex].width/2 - scrollContainer.scrollLeft();
for (var i=0;i<tabElements.length;i++) {
if (i === tabDragIndex) {
continue;
@@ -209,8 +304,6 @@ RED.tabs = (function() {
break;
}
}
// console.log(ui.position.left,ui.offset.left);
},
stop: function(event,ui) {
ul.children().css({position:"relative",left:"",transition:""});
@@ -228,6 +321,8 @@ RED.tabs = (function() {
},
removeTab: removeTab,
activateTab: activateTab,
nextTab: activateNextTab,
previousTab: activatePreviousTab,
resize: updateTabWidths,
count: function() {
return ul.find("li.red-ui-tab").size();
@@ -239,7 +334,7 @@ RED.tabs = (function() {
tabs[id].label = label;
var tab = ul.find("a[href='#"+id+"']");
tab.attr("title",label);
tab.find("span").text(label);
tab.find("span").text(label).attr('dir', RED.text.bidi.resolveBaseTextDir(label));
updateTabWidths();
},
order: function(order) {

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015, 2016 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,87 +14,31 @@
* limitations under the License.
**/
(function($) {
function validateExpression(str) {
var length = str.length;
var start = 0;
var inString = false;
var inBox = false;
var quoteChar;
var v;
for (var i=0;i<length;i++) {
var c = str[i];
if (!inString) {
if (c === "'" || c === '"') {
if (!inBox) {
return false;
}
inString = true;
quoteChar = c;
start = i+1;
} else if (c === '.') {
if (i===0 || i===length-1) {
return false;
}
// Next char is a-z
if (!/[a-z0-9]/i.test(str[i+1])) {
return false;
}
start = i+1;
} else if (c === '[') {
if (i === 0) {
return false;
}
if (i===length-1) {
return false;
}
// Next char is either a quote or a number
if (!/["'\d]/.test(str[i+1])) {
return false;
}
start = i+1;
inBox = true;
} else if (c === ']') {
if (!inBox) {
return false;
}
if (start != i) {
v = str.substring(start,i);
if (!/^\d+$/.test(v)) {
return false;
}
}
start = i+1;
inBox = false;
} else if (c === ' ') {
return false;
}
} else {
if (c === quoteChar) {
// Next char must be a ]
if (!/\]/.test(str[i+1])) {
return false;
}
start = i+1;
inString = false;
}
}
}
if (inBox || inString) {
return false;
}
return true;
}
var allOptions = {
msg: {value:"msg",label:"msg.",validate:validateExpression},
flow: {value:"flow",label:"flow.",validate:validateExpression},
global: {value:"global",label:"global.",validate:validateExpression},
msg: {value:"msg",label:"msg.",validate:RED.utils.validatePropertyExpression},
flow: {value:"flow",label:"flow.",validate:RED.utils.validatePropertyExpression},
global: {value:"global",label:"global.",validate:RED.utils.validatePropertyExpression},
str: {value:"str",label:"string",icon:"red/images/typedInput/az.png"},
num: {value:"num",label:"number",icon:"red/images/typedInput/09.png",validate:/^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/},
bool: {value:"bool",label:"boolean",icon:"red/images/typedInput/bool.png",options:["true","false"]},
json: {value:"json",label:"JSON",icon:"red/images/typedInput/json.png", validate: function(v) { try{JSON.parse(v);return true;}catch(e){return false;}}},
re: {value:"re",label:"regular expression",icon:"red/images/typedInput/re.png"},
date: {value:"date",label:"timestamp",hasValue:false}
date: {value:"date",label:"timestamp",hasValue:false},
jsonata: {
value: "jsonata",
label: "expression",
icon: "red/images/typedInput/expr.png",
validate: function(v) { try{jsonata(v);return true;}catch(e){return false;}},
expand:function() {
var that = this;
RED.editor.editExpression({
value: this.value().replace(/\t/g,"\n"),
complete: function(v) {
that.value(v.replace(/\n/g,"\t"));
}
})
}
}
};
var nlsd = false;
@@ -117,7 +61,7 @@
this.uiSelect = this.elementDiv.wrap( "<div>" ).parent();
var attrStyle = this.element.attr('style');
var m;
if ((m = /width\s*:\s*(\d+%)/i.exec(attrStyle)) !== null) {
if ((m = /width\s*:\s*(\d+(%|px))/i.exec(attrStyle)) !== null) {
this.element.css('width','100%');
this.uiSelect.width(m[1]);
this.uiWidth = null;
@@ -133,7 +77,7 @@
this.options.types = this.options.types||Object.keys(allOptions);
this.selectTrigger = $('<a href="#"></a>').prependTo(this.uiSelect);
this.selectTrigger = $('<button tabindex="0"></button>').prependTo(this.uiSelect);
$('<i class="fa fa-sort-desc"></i>').appendTo(this.selectTrigger);
this.selectLabel = $('<span></span>').appendTo(this.selectTrigger);
@@ -160,32 +104,72 @@
})
this.selectTrigger.click(function(event) {
event.preventDefault();
if (that.typeList.length > 1) {
that._showMenu(that.menu,that.selectTrigger);
} else {
that.element.focus();
}
that._showTypeMenu();
});
this.selectTrigger.on('keydown',function(evt) {
if (evt.keyCode === 40) {
// Down
that._showTypeMenu();
}
}).on('focus', function() {
that.uiSelect.addClass('red-ui-typedInput-focus');
})
// explicitly set optionSelectTrigger display to inline-block otherwise jQ sets it to 'inline'
this.optionSelectTrigger = $('<a href="#" class="red-ui-typedInput-option-trigger" style="display:inline-block"><i class="fa fa-sort-desc"></i></a>').appendTo(this.uiSelect);
this.optionSelectLabel = $('<span></span>').prependTo(this.optionSelectTrigger);
this.optionSelectTrigger = $('<button tabindex="0" class="red-ui-typedInput-option-trigger" style="display:inline-block"><span class="red-ui-typedInput-option-caret"><i class="fa fa-sort-desc"></i></span></button>').appendTo(this.uiSelect);
this.optionSelectLabel = $('<span class="red-ui-typedInput-option-label"></span>').prependTo(this.optionSelectTrigger);
this.optionSelectTrigger.click(function(event) {
event.preventDefault();
if (that.optionMenu) {
that.optionMenu.css({
minWidth:that.optionSelectLabel.width()
});
that._showMenu(that.optionMenu,that.optionSelectLabel)
that._showOptionSelectMenu();
}).on('keydown', function(evt) {
if (evt.keyCode === 40) {
// Down
that._showOptionSelectMenu();
}
}).on('blur', function() {
that.uiSelect.removeClass('red-ui-typedInput-focus');
}).on('focus', function() {
that.uiSelect.addClass('red-ui-typedInput-focus');
});
this.optionExpandButton = $('<button tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"><i class="fa fa-ellipsis-h"></i></button>').appendTo(this.uiSelect);
this.type(this.options.default||this.typeList[0].value);
},
_showTypeMenu: function() {
if (this.typeList.length > 1) {
this._showMenu(this.menu,this.selectTrigger);
this.menu.find("[value='"+this.propertyType+"']").focus();
} else {
this.element.focus();
}
},
_showOptionSelectMenu: function() {
if (this.optionMenu) {
this.optionMenu.css({
minWidth:this.optionSelectLabel.width()
});
this._showMenu(this.optionMenu,this.optionSelectLabel);
var selectedOption = this.optionMenu.find("[value='"+this.value()+"']");
if (selectedOption.length === 0) {
selectedOption = this.optionMenu.children(":first");
}
selectedOption.focus();
}
},
_hideMenu: function(menu) {
$(document).off("mousedown.close-property-select");
menu.hide();
this.element.focus();
if (this.elementDiv.is(":visible")) {
this.element.focus();
} else if (this.optionSelectTrigger.is(":visible")){
this.optionSelectTrigger.focus();
} else {
this.selectTrigger.focus();
}
},
_createMenu: function(opts,callback) {
var that = this;
@@ -194,7 +178,7 @@
if (typeof opt === 'string') {
opt = {value:opt,label:opt};
}
var op = $('<a href="#">').attr("value",opt.value).appendTo(menu);
var op = $('<a href="#"></a>').attr("value",opt.value).appendTo(menu);
if (opt.label) {
op.text(opt.label);
}
@@ -214,6 +198,21 @@
display: "none",
});
menu.appendTo(document.body);
menu.on('keydown', function(evt) {
if (evt.keyCode === 40) {
// DOWN
$(this).children(":focus").next().focus();
} else if (evt.keyCode === 38) {
// UP
$(this).children(":focus").prev().focus();
} else if (evt.keyCode === 27) {
that._hideMenu(menu);
}
})
return menu;
},
@@ -267,13 +266,18 @@
this.uiSelect.width(this.uiWidth);
}
if (this.typeMap[this.propertyType] && this.typeMap[this.propertyType].hasValue === false) {
this.selectTrigger.css('width',"100%");
this.selectTrigger.addClass("red-ui-typedInput-full-width");
} else {
this.selectTrigger.width('auto');
this.selectTrigger.removeClass("red-ui-typedInput-full-width");
var labelWidth = this._getLabelWidth(this.selectTrigger);
this.elementDiv.css('left',labelWidth+"px");
if (this.optionExpandButton.is(":visible")) {
this.elementDiv.css('right',"22px");
} else {
this.elementDiv.css('right','0');
}
if (this.optionSelectTrigger) {
this.optionSelectTrigger.css('left',(labelWidth+5)+"px");
this.optionSelectTrigger.css({'left':(labelWidth)+"px",'width':'calc( 100% - '+labelWidth+'px )'});
}
}
},
@@ -341,6 +345,9 @@
this.selectLabel.text(opt.label);
}
if (opt.options) {
if (this.optionExpandButton) {
this.optionExpandButton.hide();
}
if (this.optionSelectTrigger) {
this.optionSelectTrigger.show();
this.elementDiv.hide();
@@ -374,6 +381,16 @@
}
this.elementDiv.show();
}
if (opt.expand && typeof opt.expand === 'function') {
this.optionExpandButton.show();
this.optionExpandButton.off('click');
this.optionExpandButton.on('click',function(evt) {
evt.preventDefault();
opt.expand.call(that);
})
} else {
this.optionExpandButton.hide();
}
this.element.trigger('change',this.propertyType,this.value());
}
if (image) {

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2016 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,12 +30,13 @@ RED.deploy = (function() {
var deploymentType = "full";
var currentDiff = null;
function changeDeploymentType(type) {
deploymentType = type;
$("#btn-deploy img").attr("src",deploymentTypes[type].img);
$("#btn-deploy-icon").attr("src",deploymentTypes[type].img);
}
/**
* options:
* type: "default" - Button with drop-down options - no further customisation available
@@ -49,7 +50,15 @@ RED.deploy = (function() {
if (type == "default") {
$('<li><span class="deploy-button-group button-group">'+
'<a id="btn-deploy" class="deploy-button disabled" href="#"><img id="btn-deploy-icon" src="red/images/deploy-full-o.png"> <span>'+RED._("deploy.deploy")+'</span></a>'+
'<a id="btn-deploy" class="deploy-button disabled" href="#">'+
'<span class="deploy-button-content">'+
'<img id="btn-deploy-icon" src="red/images/deploy-full-o.png"> '+
'<span>'+RED._("deploy.deploy")+'</span>'+
'</span>'+
'<span class="deploy-button-spinner hide">'+
'<img src="red/images/spin.svg"/>'+
'</span>'+
'</a>'+
'<a id="btn-deploy-options" data-toggle="dropdown" class="deploy-button" href="#"><i class="fa fa-caret-down"></i></a>'+
'</span></li>').prependTo(".header-toolbar");
RED.menu.init({id:"btn-deploy-options",
@@ -68,27 +77,56 @@ RED.deploy = (function() {
$('<li><span class="deploy-button-group button-group">'+
'<a id="btn-deploy" class="deploy-button disabled" href="#">'+
(icon?'<img id="btn-deploy-icon" src="'+icon+'"> ':'')+
'<span>'+label+'</span></a>'+
'<span class="deploy-button-content">'+
(icon?'<img id="btn-deploy-icon" src="'+icon+'"> ':'')+
'<span>'+label+'</span>'+
'</span>'+
'<span class="deploy-button-spinner hide">'+
'<img src="red/images/spin.svg"/>'+
'</span>'+
'</a>'+
'</span></li>').prependTo(".header-toolbar");
}
$('#btn-deploy').click(function() { save(); });
RED.actions.add("core:deploy-flows",save);
$( "#node-dialog-confirm-deploy" ).dialog({
title: "Confirm deploy",
title: RED._('deploy.confirm.button.confirm'),
modal: true,
autoOpen: false,
width: 550,
height: "auto",
buttons: [
{
text: RED._("deploy.confirm.button.cancel"),
text: RED._("common.label.cancel"),
click: function() {
$( this ).dialog( "close" );
}
},
{
id: "node-dialog-confirm-deploy-review",
text: RED._("deploy.confirm.button.review"),
class: "primary disabled",
click: function() {
if (!$("#node-dialog-confirm-deploy-review").hasClass('disabled')) {
RED.diff.showRemoteDiff();
$( this ).dialog( "close" );
}
}
},
{
id: "node-dialog-confirm-deploy-merge",
text: RED._("deploy.confirm.button.merge"),
class: "primary disabled",
click: function() {
RED.diff.mergeDiff(currentDiff);
$( this ).dialog( "close" );
}
},
{
id: "node-dialog-confirm-deploy-deploy",
text: RED._("deploy.confirm.button.confirm"),
class: "primary",
click: function() {
@@ -97,7 +135,7 @@ RED.deploy = (function() {
if (ignoreChecked) {
ignoreDeployWarnings[$( "#node-dialog-confirm-deploy-type" ).val()] = true;
}
save(true);
save(true,$( "#node-dialog-confirm-deploy-type" ).val() === "conflict");
$( this ).dialog( "close" );
}
}
@@ -109,6 +147,42 @@ RED.deploy = (function() {
'<label style="display:inline;" for="node-dialog-confirm-deploy-hide"> do not warn about this again</label>'+
'<input type="hidden" id="node-dialog-confirm-deploy-type">'+
'</div>');
},
open: function() {
if ($( "#node-dialog-confirm-deploy-type" ).val() === "conflict") {
$("#node-dialog-confirm-deploy-deploy").hide();
$("#node-dialog-confirm-deploy-review").addClass('disabled').show();
$("#node-dialog-confirm-deploy-merge").addClass('disabled').show();
currentDiff = null;
$("#node-dialog-confirm-deploy-conflict-checking").show();
$("#node-dialog-confirm-deploy-conflict-auto-merge").hide();
$("#node-dialog-confirm-deploy-conflict-manual-merge").hide();
var now = Date.now();
RED.diff.getRemoteDiff(function(diff) {
var ellapsed = Math.max(1000 - (Date.now()-now), 0);
currentDiff = diff;
setTimeout(function() {
$("#node-dialog-confirm-deploy-conflict-checking").hide();
var d = Object.keys(diff.conflicts);
if (d.length === 0) {
$("#node-dialog-confirm-deploy-conflict-auto-merge").show();
$("#node-dialog-confirm-deploy-merge").removeClass('disabled')
} else {
$("#node-dialog-confirm-deploy-conflict-manual-merge").show();
}
$("#node-dialog-confirm-deploy-review").removeClass('disabled')
},ellapsed);
})
$("#node-dialog-confirm-deploy-hide").parent().hide();
} else {
$("#node-dialog-confirm-deploy-deploy").show();
$("#node-dialog-confirm-deploy-review").hide();
$("#node-dialog-confirm-deploy-merge").hide();
$("#node-dialog-confirm-deploy-hide").parent().show();
}
}
});
@@ -123,6 +197,8 @@ RED.deploy = (function() {
$("#btn-deploy").addClass("disabled");
}
});
}
function getNodeInfo(node) {
@@ -136,13 +212,7 @@ RED.deploy = (function() {
tabLabel = tab.label;
}
}
var label = "";
if (typeof node._def.label == "function") {
label = node._def.label.call(node);
} else {
label = node._def.label;
}
label = label || node.id;
var label = RED.utils.getNodeLabel(node,node.id);
return {tab:tabLabel,type:node.type,label:label};
}
function sortNodeInfo(A,B) {
@@ -155,11 +225,18 @@ RED.deploy = (function() {
return 0;
}
function save(force) {
if (RED.nodes.dirty()) {
//$("#debug-tab-clear").click(); // uncomment this to auto clear debug on deploy
function resolveConflict(currentNodes) {
$( "#node-dialog-confirm-deploy-config" ).hide();
$( "#node-dialog-confirm-deploy-unknown" ).hide();
$( "#node-dialog-confirm-deploy-unused" ).hide();
$( "#node-dialog-confirm-deploy-conflict" ).show();
$( "#node-dialog-confirm-deploy-type" ).val("conflict");
$( "#node-dialog-confirm-deploy" ).dialog( "open" );
}
if (!force) {
function save(skipValidation,force) {
if (!$("#btn-deploy").hasClass("disabled")) {
if (!skipValidation) {
var hasUnknown = false;
var hasInvalid = false;
var hasUnusedConfig = false;
@@ -191,6 +268,7 @@ RED.deploy = (function() {
$( "#node-dialog-confirm-deploy-config" ).hide();
$( "#node-dialog-confirm-deploy-unknown" ).hide();
$( "#node-dialog-confirm-deploy-unused" ).hide();
$( "#node-dialog-confirm-deploy-conflict" ).hide();
var showWarning = false;
@@ -224,24 +302,31 @@ RED.deploy = (function() {
}
}
var nns = RED.nodes.createCompleteNodeSet();
$("#btn-deploy-icon").removeClass('fa-download');
$("#btn-deploy-icon").addClass('spinner');
RED.nodes.dirty(false);
var startTime = Date.now();
$(".deploy-button-content").css('opacity',0);
$(".deploy-button-spinner").show();
$("#btn-deploy").addClass("disabled");
var data = {flows:nns};
if (!force) {
data.rev = RED.nodes.version();
}
$.ajax({
url:"flows",
type: "POST",
data: JSON.stringify(nns),
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
headers: {
"Node-RED-Deployment-Type":deploymentType
}
}).done(function(data,textStatus,xhr) {
RED.nodes.dirty(false);
RED.nodes.version(data.rev);
RED.nodes.originalFlow(nns);
if (hasUnusedConfig) {
RED.notify(
'<p>'+RED._("deploy.successfulDeploy")+'</p>'+
@@ -259,30 +344,39 @@ RED.deploy = (function() {
}
});
RED.nodes.eachConfig(function (confNode) {
confNode.changed = false;
if (confNode.credentials) {
delete confNode.credentials;
}
});
RED.nodes.eachWorkspace(function(ws) {
ws.changed = false;
})
// Once deployed, cannot undo back to a clean state
RED.history.markAllDirty();
RED.view.redraw();
RED.events.emit("deploy");
}).fail(function(xhr,textStatus,err) {
RED.nodes.dirty(true);
$("#btn-deploy").removeClass("disabled");
if (xhr.status === 401) {
RED.notify(RED._("deploy.deployFailed",{message:RED._("user.notAuthorized")}),"error");
} else if (xhr.status === 409) {
resolveConflict(nns);
} else if (xhr.responseText) {
RED.notify(RED._("deploy.deployFailed",{message:xhr.responseText}),"error");
} else {
RED.notify(RED._("deploy.deployFailed",{message:RED._("deploy.errors.noResponse")}),"error");
}
}).always(function() {
$("#btn-deploy-icon").removeClass('spinner');
$("#btn-deploy-icon").addClass('fa-download');
var delta = Math.max(0,300-(Date.now()-startTime));
setTimeout(function() {
$(".deploy-button-content").css('opacity',1);
$(".deploy-button-spinner").hide();
},delta);
});
}
}
return {
init: init
}

1271
editor/js/ui/diff.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2013, 2016 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -128,7 +128,11 @@ RED.editor = (function() {
valid = value !== "";
}
if (valid && "validate" in definition[property]) {
valid = definition[property].validate.call(node,value);
try {
valid = definition[property].validate.call(node,value);
} catch(err) {
console.log("Validation error:",node.type,node.id,"property: "+property,"value:",value,err);
}
}
if (valid && definition[property].type && RED.nodes.getType(definition[property].type) && !("validate" in definition[property])) {
if (!value || value == "_ADD_") {
@@ -159,7 +163,11 @@ RED.editor = (function() {
function validateNodeEditorProperty(node,defaults,property,prefix) {
var input = $("#"+prefix+"-"+property);
if (input.length > 0) {
if (!validateNodeProperty(node, defaults, property,input.val())) {
var value = input.val();
if (defaults[property].hasOwnProperty("format") && defaults[property].format !== "" && input[0].nodeName === "DIV") {
value = input.text();
}
if (!validateNodeProperty(node, defaults, property,value)) {
input.addClass("input-error");
} else {
input.removeClass("input-error");
@@ -172,19 +180,31 @@ RED.editor = (function() {
* Marks the node as dirty and needing a size check.
* Removes any links to non-existant outputs.
* @param node - the node that has been updated
* @param outputMap - (optional) a map of old->new port numbers if wires should be moved
* @returns {array} the links that were removed due to this update
*/
function updateNodeProperties(node) {
function updateNodeProperties(node, outputMap) {
node.resize = true;
node.dirty = true;
var removedLinks = [];
if (node.ports) {
if (outputMap) {
RED.nodes.eachLink(function(l) {
if (l.source === node && outputMap.hasOwnProperty(l.sourcePort)) {
if (outputMap[l.sourcePort] === "-1") {
removedLinks.push(l);
} else {
l.sourcePort = outputMap[l.sourcePort];
}
}
});
}
if (node.outputs < node.ports.length) {
while (node.outputs < node.ports.length) {
node.ports.pop();
}
RED.nodes.eachLink(function(l) {
if (l.source === node && l.sourcePort >= node.outputs) {
if (l.source === node && l.sourcePort >= node.outputs && removedLinks.indexOf(l) === -1) {
removedLinks.push(l);
}
});
@@ -245,12 +265,8 @@ RED.editor = (function() {
var configNode = RED.nodes.node(node[property]);
var node_def = RED.nodes.getType(type);
if (configNode && node_def.label) {
if (typeof node_def.label == "function") {
label = node_def.label.call(configNode);
} else {
label = node_def.label;
}
if (configNode) {
label = RED.utils.getNodeLabel(configNode,configNode.id);
}
input.val(label);
}
@@ -286,17 +302,30 @@ RED.editor = (function() {
* @param node - the node being edited
* @param property - the name of the field
* @param prefix - the prefix to use in the input element ids (node-input|node-config-input)
* @param definition - the definition of the field
*/
function preparePropertyEditor(node,property,prefix) {
function preparePropertyEditor(node,property,prefix,definition) {
var input = $("#"+prefix+"-"+property);
if (input.length === 0) {
return;
}
if (input.attr('type') === "checkbox") {
input.prop('checked',node[property]);
} else {
}
else {
var val = node[property];
if (val == null) {
val = "";
}
input.val(val);
if (definition !== undefined && definition[property].hasOwnProperty("format") && definition[property].format !== "" && input[0].nodeName === "DIV") {
input.html(RED.text.format.getHtml(val, definition[property].format, {}, false, "en"));
RED.text.format.attach(input[0], definition[property].format, {}, false, "en");
} else {
input.val(val);
if (input[0].nodeName === 'INPUT' || input[0].nodeName === 'TEXTAREA') {
RED.text.bidi.prepareInput(input);
}
}
}
}
@@ -308,11 +337,20 @@ RED.editor = (function() {
* @param prefix - the prefix to use in the input element ids (node-input|node-config-input)
*/
function attachPropertyChangeHandler(node,definition,property,prefix) {
$("#"+prefix+"-"+property).change(function(event,skipValidation) {
if (!skipValidation) {
validateNodeEditor(node,prefix);
}
});
var input = $("#"+prefix+"-"+property);
if (definition !== undefined && "format" in definition[property] && definition[property].format !== "" && input[0].nodeName === "DIV") {
$("#"+prefix+"-"+property).on('change keyup', function(event,skipValidation) {
if (!skipValidation) {
validateNodeEditor(node,prefix);
}
});
} else {
$("#"+prefix+"-"+property).change(function(event,skipValidation) {
if (!skipValidation) {
validateNodeEditor(node,prefix);
}
});
}
}
/**
@@ -336,7 +374,7 @@ RED.editor = (function() {
$('#' + prefix + '-' + cred).val('');
}
} else {
preparePropertyEditor(credData, cred, prefix);
preparePropertyEditor(credData, cred, prefix, credDef);
}
attachPropertyChangeHandler(node, credDef, cred, prefix);
}
@@ -396,10 +434,10 @@ RED.editor = (function() {
}
} else {
console.log("Unknown type:", definition.defaults[d].type);
preparePropertyEditor(node,d,prefix);
preparePropertyEditor(node,d,prefix,definition.defaults);
}
} else {
preparePropertyEditor(node,d,prefix);
preparePropertyEditor(node,d,prefix,definition.defaults);
}
attachPropertyChangeHandler(node,definition.defaults,d,prefix);
}
@@ -447,12 +485,13 @@ RED.editor = (function() {
}
function getEditStackTitle() {
var title = '<ul class="editor-tray-breadcrumbs">';
for (var i=0;i<editStack.length;i++) {
var node = editStack[i];
var label = node.type;
if (node.type === 'subflow') {
if (node.type === '_expression') {
label = "Expression editor";
} else if (node.type === 'subflow') {
label = RED._("subflow.editSubflow",{name:node.name})
} else if (node.type.indexOf("subflow:")===0) {
var subflow = RED.nodes.subflow(node.type.substring(8));
@@ -479,6 +518,148 @@ RED.editor = (function() {
return title;
}
function buildEditForm(container,formId,type,ns) {
var dialogForm = $('<form id="'+formId+'" class="form-horizontal" autocomplete="off"></form>').appendTo(container);
dialogForm.html($("script[data-template-name='"+type+"']").html());
ns = ns||"node-red";
dialogForm.find('[data-i18n]').each(function() {
var current = $(this).attr("data-i18n");
var keys = current.split(";");
for (var i=0;i<keys.length;i++) {
var key = keys[i];
if (key.indexOf(":") === -1) {
var prefix = "";
if (key.indexOf("[")===0) {
var parts = key.split("]");
prefix = parts[0]+"]";
key = parts[1];
}
keys[i] = prefix+ns+":"+key;
}
}
$(this).attr("data-i18n",keys.join(";"));
});
// Add dummy fields to prevent 'Enter' submitting the form in some
// cases, and also prevent browser auto-fill of password
// Add in reverse order as they are prepended...
$('<input type="password" style="display: none;" />').prependTo(dialogForm);
$('<input type="text" style="display: none;" />').prependTo(dialogForm);
dialogForm.submit(function(e) { e.preventDefault();});
return dialogForm;
}
function refreshLabelForm(container,node) {
var inputPlaceholder = node._def.inputLabels?RED._("editor.defaultLabel"):RED._("editor.noDefaultLabel");
var outputPlaceholder = node._def.outputLabels?RED._("editor.defaultLabel"):RED._("editor.noDefaultLabel");
var inputsDiv = $("#node-label-form-inputs");
var outputsDiv = $("#node-label-form-outputs");
var inputCount = node.inputs || node._def.inputs || 0;
var children = inputsDiv.children();
if (children.length < inputCount) {
for (i = children.length;i<inputCount;i++) {
buildLabelRow("input",i,"",inputPlaceholder).appendTo(inputsDiv);
}
} else if (children.length > inputCount) {
for (i=inputCount;i<children.length;i++) {
$(children[i]).remove();
}
}
var outputCount;
var i;
var formOutputs = $("#node-input-outputs").val();
if (formOutputs === undefined) {
outputCount = node.outputs || node._def.outputs || 0;
} else if (isNaN(formOutputs)) {
var outputMap = JSON.parse(formOutputs);
var keys = Object.keys(outputMap);
outputCount = 0;
var rows = [];
keys.forEach(function(p) {
var row = $("#node-label-form-output-"+p).parent();
if (row.length === 0 && outputMap[p] !== -1) {
row = buildLabelRow("output",p,"",outputPlaceholder);
}
if (outputMap[p] !== -1) {
outputCount++;
rows.push({i:parseInt(outputMap[p]),r:row});
}
});
rows.sort(function(A,B) {
return A.i-B.i;
})
outputsDiv.children().detach();
rows.forEach(function(r,i) {
r.r.find("label").html((i+1)+".");
r.r.appendTo(outputsDiv);
})
} else {
outputCount = Math.max(0,parseInt(formOutputs));
}
children = outputsDiv.children();
if (children.length < outputCount) {
for (i = children.length;i<outputCount;i++) {
buildLabelRow("output",i,"").appendTo(outputsDiv);
}
} else if (children.length > outputCount) {
for (i=outputCount;i<children.length;i++) {
$(children[i]).remove();
}
}
}
function buildLabelRow(type, index, value, placeHolder) {
var result = $('<div>',{style:"margin: 5px 0px"});
var id = "node-label-form-"+type+"-"+index;
$('<label>',{for:id,style:"margin-right: 20px; text-align: right; width: 30px;"}).html((index+1)+".").appendTo(result);
var input = $('<input>',{type:"text",id:id, placeholder: placeHolder}).val(value).appendTo(result);
var clear = $('<button class="editor-button editor-button-small" style="margin-left: 10px"><i class="fa fa-times"></i></button>').appendTo(result);
clear.click(function(evt) {
evt.preventDefault();
input.val("");
})
return result;
}
function buildLabelForm(container,node) {
var dialogForm = $('<form class="dialog-form form-horizontal" autocomplete="off"></form>').appendTo(container);
var inputCount = node.inputs || node._def.inputs || 0;
var outputCount = node.outputs || node._def.outputs || 0;
if (node.type === 'subflow') {
inputCount = node.in.length;
outputCount = node.out.length;
}
var inputLabels = node.inputLabels || [];
var outputLabels = node.outputLabels || [];
var inputPlaceholder = node._def.inputLabels?RED._("editor.defaultLabel"):RED._("editor.noDefaultLabel");
var outputPlaceholder = node._def.outputLabels?RED._("editor.defaultLabel"):RED._("editor.noDefaultLabel");
var i,row;
$('<div class="form-row"><i class="fa fa-tag"></i> <span data-i18n="editor.labelInputs"></span><div id="node-label-form-inputs"></div></div>').appendTo(dialogForm);
var inputsDiv = $("#node-label-form-inputs");
if (inputCount > 0) {
for (i=0;i<inputCount;i++) {
buildLabelRow("input",i,inputLabels[i],inputPlaceholder).appendTo(inputsDiv);
}
} else {
}
$('<div class="form-row"><i class="fa fa-tag"></i> <span data-i18n="editor.labelOutputs"></span><div id="node-label-form-outputs"></div></div>').appendTo(dialogForm);
var outputsDiv = $("#node-label-form-outputs");
if (outputCount > 0) {
for (i=0;i<outputCount;i++) {
buildLabelRow("output",i,outputLabels[i],outputPlaceholder).appendTo(outputsDiv);
}
} else {
}
}
function showEditDialog(node) {
var editing_node = node;
editStack.push(node);
@@ -490,6 +671,33 @@ RED.editor = (function() {
var trayOptions = {
title: getEditStackTitle(),
buttons: [
{
id: "node-dialog-delete",
class: 'leftButton',
text: RED._("common.label.delete"),
click: function() {
var startDirty = RED.nodes.dirty();
var removedNodes = [];
var removedLinks = [];
var removedEntities = RED.nodes.remove(editing_node.id);
removedNodes.push(editing_node);
removedNodes = removedNodes.concat(removedEntities.nodes);
removedLinks = removedLinks.concat(removedEntities.links);
var historyEvent = {
t:'delete',
nodes:removedNodes,
links:removedLinks,
changes: {},
dirty: startDirty
}
RED.nodes.dirty(true);
RED.view.redraw(true);
RED.history.push(historyEvent);
RED.tray.close();
}
},
{
id: "node-dialog-cancel",
text: RED._("common.label.cancel"),
@@ -535,6 +743,7 @@ RED.editor = (function() {
var changed = false;
var wasDirty = RED.nodes.dirty();
var d;
var outputMap;
if (editing_node._def.oneditsave) {
var oldValues = {};
@@ -573,19 +782,55 @@ RED.editor = (function() {
}
}
var newValue;
if (editing_node._def.defaults) {
for (d in editing_node._def.defaults) {
if (editing_node._def.defaults.hasOwnProperty(d)) {
var input = $("#node-input-"+d);
var newValue;
if (input.attr('type') === "checkbox") {
newValue = input.prop('checked');
} else if ("format" in editing_node._def.defaults[d] && editing_node._def.defaults[d].format !== "" && input[0].nodeName === "DIV") {
newValue = input.text();
} else {
newValue = input.val();
}
if (newValue != null) {
if (d === "outputs" && (newValue.trim() === "" || isNaN(newValue))) {
continue;
if (d === "outputs") {
if (newValue.trim() === "") {
continue;
}
if (isNaN(newValue)) {
outputMap = JSON.parse(newValue);
var outputCount = 0;
var outputsChanged = false;
var keys = Object.keys(outputMap);
keys.forEach(function(p) {
if (isNaN(p)) {
// New output;
outputCount ++;
delete outputMap[p];
} else {
outputMap[p] = outputMap[p]+"";
if (outputMap[p] !== "-1") {
outputCount++;
if (outputMap[p] !== p) {
// Output moved
outputsChanged = true;
} else {
delete outputMap[p];
}
} else {
// Output removed
outputsChanged = true;
}
}
});
newValue = outputCount;
if (outputsChanged) {
changed = true;
}
}
}
if (editing_node[d] != newValue) {
if (editing_node._def.defaults[d].type) {
@@ -617,8 +862,31 @@ RED.editor = (function() {
var credsChanged = updateNodeCredentials(editing_node,credDefinition,prefix);
changed = changed || credsChanged;
}
// if (editing_node.hasOwnProperty("_outputs")) {
// outputMap = editing_node._outputs;
// delete editing_node._outputs;
// if (Object.keys(outputMap).length > 0) {
// changed = true;
// }
// }
var removedLinks = updateNodeProperties(editing_node,outputMap);
var inputLabels = $("#node-label-form-inputs").children().find("input");
var outputLabels = $("#node-label-form-outputs").children().find("input");
newValue = inputLabels.map(function() { return $(this).val();}).toArray().slice(0,editing_node.inputs);
if (JSON.stringify(newValue) !== JSON.stringify(editing_node.inputLabels)) {
changes.inputLabels = editing_node.inputLabels;
editing_node.inputLabels = newValue;
changed = true;
}
newValue = outputLabels.map(function() { return $(this).val();}).toArray().slice(0,editing_node.outputs);
if (JSON.stringify(newValue) !== JSON.stringify(editing_node.outputLabels)) {
changes.outputLabels = editing_node.outputLabels;
editing_node.outputLabels = newValue;
changed = true;
}
var removedLinks = updateNodeProperties(editing_node);
if (changed) {
var wasChanged = editing_node.changed;
editing_node.changed = true;
@@ -648,6 +916,9 @@ RED.editor = (function() {
dirty:wasDirty,
changed:wasChanged
};
if (outputMap) {
historyEvent.outputMap = outputMap;
}
if (subflowInstances) {
historyEvent.subflow = {
instances:subflowInstances
@@ -664,8 +935,9 @@ RED.editor = (function() {
],
resize: function(dimensions) {
editTrayWidthCache[type] = dimensions.width;
$(".editor-tray-content").height(dimensions.height - 78);
var form = $(".editor-tray-content form").height(dimensions.height - 78 - 40);
if (editing_node && editing_node._def.oneditresize) {
var form = $("#dialog-form");
try {
editing_node._def.oneditresize.call(editing_node,{width:form.width(),height:form.height()});
} catch(err) {
@@ -674,38 +946,39 @@ RED.editor = (function() {
}
},
open: function(tray) {
var trayFooter = tray.find(".editor-tray-footer");
var trayBody = tray.find('.editor-tray-body');
trayBody.parent().css('overflow','hidden');
var stack = RED.stack.create({
container: trayBody,
singleExpanded: true
});
var nodeProperties = stack.add({
title: RED._("editor.nodeProperties"),
expanded: true
});
var portLabels = stack.add({
title: RED._("editor.portLabels"),
onexpand: function() {
refreshLabelForm(this.content,node);
}
});
if (editing_node) {
RED.sidebar.info.refresh(editing_node);
}
var trayBody = tray.find('.editor-tray-body');
var dialogForm = $('<form id="dialog-form" class="form-horizontal"></form>').appendTo(trayBody);
dialogForm.html($("script[data-template-name='"+type+"']").html());
var ns;
if (node._def.set.module === "node-red") {
ns = "node-red";
} else {
ns = node._def.set.id;
}
dialogForm.find('[data-i18n]').each(function() {
var current = $(this).attr("data-i18n");
var keys = current.split(";");
for (var i=0;i<keys.length;i++) {
var key = keys[i];
if (key.indexOf(":") === -1) {
var prefix = "";
if (key.indexOf("[")===0) {
var parts = key.split("]");
prefix = parts[0]+"]";
key = parts[1];
}
keys[i] = prefix+ns+":"+key;
}
}
$(this).attr("data-i18n",keys.join(";"));
});
$('<input type="text" style="display: none;" />').prependTo(dialogForm);
buildEditForm(nodeProperties.content,"dialog-form",type,ns);
buildLabelForm(portLabels.content,node);
prepareEditDialog(node,node._def,"node-input");
dialogForm.i18n();
trayBody.i18n();
},
close: function() {
if (RED.view.state() != RED.state.IMPORT_DRAGGING) {
@@ -759,16 +1032,17 @@ RED.editor = (function() {
} else {
ns = node_def.set.id;
}
var activeWorkspace = RED.nodes.workspace(RED.workspaces.active());
if (!activeWorkspace) {
activeWorkspace = RED.nodes.subflow(RED.workspaces.active());
var configNodeScope = ""; // default to global
var activeSubflow = RED.nodes.subflow(RED.workspaces.active());
if (activeSubflow) {
configNodeScope = activeSubflow.id;
}
if (editing_config_node == null) {
editing_config_node = {
id: RED.nodes.id(),
_def: node_def,
type: type,
z: activeWorkspace.id,
z: configNodeScope,
users: []
}
for (var d in node_def.defaults) {
@@ -795,7 +1069,6 @@ RED.editor = (function() {
},
open: function(tray) {
var trayHeader = tray.find(".editor-tray-header");
var trayBody = tray.find(".editor-tray-body");
var trayFooter = tray.find(".editor-tray-footer");
if (node_def.hasUsers !== false) {
@@ -803,21 +1076,8 @@ RED.editor = (function() {
}
trayFooter.append('<span id="node-config-dialog-scope-container"><span id="node-config-dialog-scope-warning" data-i18n="[title]editor.errors.scopeChange"><i class="fa fa-warning"></i></span><select id="node-config-dialog-scope"></select></span>');
var dialogForm = $('<form id="node-config-dialog-edit-form" class="form-horizontal"></form>').appendTo(trayBody);
dialogForm.html($("script[data-template-name='"+type+"']").html());
dialogForm.find('[data-i18n]').each(function() {
var current = $(this).attr("data-i18n");
if (current.indexOf(":") === -1) {
var prefix = "";
if (current.indexOf("[")===0) {
var parts = current.split("]");
prefix = parts[0]+"]";
current = parts[1];
}
$(this).attr("data-i18n",prefix+ns+":"+current);
}
});
$('<input type="text" style="display: none;" />').prependTo(dialogForm);
var dialogForm = buildEditForm(tray.find('.editor-tray-body'),"node-config-dialog-edit-form",type,ns);
prepareEditDialog(editing_config_node,node_def,"node-config-input");
if (editing_config_node._def.exclusive) {
$("#node-config-dialog-scope").hide();
@@ -941,6 +1201,8 @@ RED.editor = (function() {
input = $("#node-config-input-"+d);
if (input.attr('type') === "checkbox") {
newValue = input.prop('checked');
} else if ("format" in configTypeDef.defaults[d] && configTypeDef.defaults[d].format !== "" && input[0].nodeName === "DIV") {
newValue = input.text();
} else {
newValue = input.val();
}
@@ -1085,6 +1347,14 @@ RED.editor = (function() {
RED.tray.show(trayOptions);
}
function defaultConfigNodeSort(A,B) {
if (A.__label__ < B.__label__) {
return -1;
} else if (A.__label__ > B.__label__) {
return 1;
}
return 0;
}
function updateConfigNodeSelect(name,type,value,prefix) {
// if prefix is null, there is no config select to update
@@ -1112,27 +1382,24 @@ RED.editor = (function() {
RED.nodes.eachConfig(function(config) {
if (config.type == type && (!config.z || config.z === activeWorkspace.id)) {
var label = "";
if (typeof node_def.label == "function") {
label = node_def.label.call(config);
} else {
label = node_def.label;
}
configNodes.push({id:config.id,label:label});
var label = RED.utils.getNodeLabel(config,config.id);
config.__label__ = label;
configNodes.push(config);
}
});
configNodes.sort(function(A,B) {
if (A.label < B.label) {
return -1;
} else if (A.label > B.label) {
return 1;
}
return 0;
});
var configSortFn = defaultConfigNodeSort;
if (typeof node_def.sort == "function") {
configSortFn = node_def.sort;
}
try {
configNodes.sort(configSortFn);
} catch(err) {
console.log("Definition error: "+node_def.type+".sort",err);
}
configNodes.forEach(function(cn) {
select.append('<option value="'+cn.id+'"'+(value==cn.id?" selected":"")+'>'+cn.label+'</option>');
select.append('<option value="'+cn.id+'"'+(value==cn.id?" selected":"")+'>'+RED.text.bidi.enforceTextDirectionWithUCC(cn.__label__)+'</option>');
delete cn.__label__;
});
select.append('<option value="_ADD_"'+(value===""?" selected":"")+'>'+RED._("editor.addNewType", {type:type})+'</option>');
@@ -1173,7 +1440,6 @@ RED.editor = (function() {
changes['name'] = editing_node.name;
editing_node.name = newName;
changed = true;
$("#menu-item-workspace-menu-"+editing_node.id.replace(".","-")).text(newName);
}
var newDescription = subflowEditor.getValue();
@@ -1183,6 +1449,21 @@ RED.editor = (function() {
editing_node.info = newDescription;
changed = true;
}
var inputLabels = $("#node-label-form-inputs").children().find("input");
var outputLabels = $("#node-label-form-outputs").children().find("input");
var newValue = inputLabels.map(function() { return $(this).val();}).toArray().slice(0,editing_node.inputs);
if (JSON.stringify(newValue) !== JSON.stringify(editing_node.inputLabels)) {
changes.inputLabels = editing_node.inputLabels;
editing_node.inputLabels = newValue;
changed = true;
}
newValue = outputLabels.map(function() { return $(this).val();}).toArray().slice(0,editing_node.outputs);
if (JSON.stringify(newValue) !== JSON.stringify(editing_node.outputLabels)) {
changes.outputLabels = editing_node.outputLabels;
editing_node.outputLabels = newValue;
changed = true;
}
RED.palette.refresh();
@@ -1220,7 +1501,10 @@ RED.editor = (function() {
}
}
],
resize: function() {
resize: function(dimensions) {
$(".editor-tray-content").height(dimensions.height - 78);
var form = $(".editor-tray-content form").height(dimensions.height - 78 - 40);
var rows = $("#dialog-form>div:not(.node-text-editor-row)");
var editorRow = $("#dialog-form>div.node-text-editor-row");
var height = $("#dialog-form").height();
@@ -1232,33 +1516,28 @@ RED.editor = (function() {
subflowEditor.resize();
},
open: function(tray) {
var trayFooter = tray.find(".editor-tray-footer");
var trayBody = tray.find('.editor-tray-body');
trayBody.parent().css('overflow','hidden');
var stack = RED.stack.create({
container: trayBody,
singleExpanded: true
});
var nodeProperties = stack.add({
title: RED._("editor.nodeProperties"),
expanded: true
});
var portLabels = stack.add({
title: RED._("editor.portLabels")
});
if (editing_node) {
RED.sidebar.info.refresh(editing_node);
}
var trayBody = tray.find('.editor-tray-body');
var dialogForm = $('<form id="dialog-form" class="form-horizontal"></form>').appendTo(trayBody);
dialogForm.html($("script[data-template-name='subflow-template']").html());
var ns = "node-red";
dialogForm.find('[data-i18n]').each(function() {
var current = $(this).attr("data-i18n");
var keys = current.split(";");
for (var i=0;i<keys.length;i++) {
var key = keys[i];
if (key.indexOf(":") === -1) {
var prefix = "";
if (key.indexOf("[")===0) {
var parts = key.split("]");
prefix = parts[0]+"]";
key = parts[1];
}
keys[i] = prefix+ns+":"+key;
}
}
$(this).attr("data-i18n",keys.join(";"));
});
$('<input type="text" style="display: none;" />').prependTo(dialogForm);
dialogForm.submit(function(e) { e.preventDefault();});
var dialogForm = buildEditForm(nodeProperties.content,"dialog-form","subflow-template");
subflowEditor = RED.editor.createEditor({
id: 'subflow-input-info-editor',
mode: 'ace/mode/markdown',
@@ -1266,6 +1545,7 @@ RED.editor = (function() {
});
$("#subflow-input-name").val(subflow.name);
RED.text.bidi.prepareInput($("#subflow-input-name"));
subflowEditor.getSession().setValue(subflow.info||"",-1);
var userCount = 0;
var subflowType = "subflow:"+editing_node.id;
@@ -1276,7 +1556,9 @@ RED.editor = (function() {
}
});
$("#subflow-dialog-user-count").html(RED._("subflow.subflowInstances", {count:userCount})).show();
dialogForm.i18n();
buildLabelForm(portLabels.content,subflow);
trayBody.i18n();
},
close: function() {
if (RED.view.state() != RED.state.IMPORT_DRAGGING) {
@@ -1293,22 +1575,183 @@ RED.editor = (function() {
RED.tray.show(trayOptions);
}
function editExpression(options) {
var value = options.value;
var onComplete = options.complete;
var type = "_expression"
editStack.push({type:type});
RED.view.state(RED.state.EDITING);
var expressionEditor;
var trayOptions = {
title: getEditStackTitle(),
buttons: [
{
id: "node-dialog-cancel",
text: RED._("common.label.cancel"),
click: function() {
RED.tray.close();
}
},
{
id: "node-dialog-ok",
text: RED._("common.label.done"),
class: "primary",
click: function() {
$("#node-input-expression-help").html("");
onComplete(expressionEditor.getValue());
RED.tray.close();
}
}
],
resize: function(dimensions) {
editTrayWidthCache[type] = dimensions.width;
var rows = $("#dialog-form>div:not(.node-text-editor-row)");
var editorRow = $("#dialog-form>div.node-text-editor-row");
var height = $("#dialog-form").height();
for (var i=0;i<rows.size();i++) {
height -= $(rows[i]).outerHeight(true);
}
height -= (parseInt($("#dialog-form").css("marginTop"))+parseInt($("#dialog-form").css("marginBottom")));
$(".node-text-editor").css("height",height+"px");
expressionEditor.resize();
},
open: function(tray) {
var trayBody = tray.find('.editor-tray-body');
var dialogForm = buildEditForm(tray.find('.editor-tray-body'),'dialog-form','_expression','editor');
var funcSelect = $("#node-input-expression-func");
Object.keys(jsonata.functions).forEach(function(f) {
funcSelect.append($("<option></option>").val(f).text(f));
})
funcSelect.change(function(e) {
var f = $(this).val();
var args = RED._('jsonata:'+f+".args",{defaultValue:''});
var title = "<h5>"+f+"("+args+")</h5>";
var body = marked(RED._('jsonata:'+f+'.desc',{defaultValue:''}));
$("#node-input-expression-help").html(title+"<p>"+body+"</p>");
})
expressionEditor = RED.editor.createEditor({
id: 'node-input-expression',
value: "",
mode:"ace/mode/jsonata",
options: {
enableBasicAutocompletion:true,
enableSnippets:true,
enableLiveAutocompletion: true
}
});
var currentToken = null;
var currentTokenPos = -1;
var currentFunctionMarker = null;
expressionEditor.getSession().setValue(value||"",-1);
expressionEditor.on("changeSelection", function() {
var c = expressionEditor.getCursorPosition();
var token = expressionEditor.getSession().getTokenAt(c.row,c.column);
if (token !== currentToken || (token && /paren/.test(token.type) && c.column !== currentTokenPos)) {
currentToken = token;
var r,p;
var scopedFunction = null;
if (token && token.type === 'keyword') {
r = c.row;
scopedFunction = token;
} else {
var depth = 0;
var next = false;
if (token) {
if (token.type === 'paren.rparen') {
// If this is a block of parens ')))', set
// depth to offset against the cursor position
// within the block
currentTokenPos = c.column;
depth = c.column - (token.start + token.value.length);
}
r = c.row;
p = token.index;
} else {
r = c.row-1;
p = -1;
}
while ( scopedFunction === null && r > -1) {
var rowTokens = expressionEditor.getSession().getTokens(r);
if (p === -1) {
p = rowTokens.length-1;
}
while (p > -1) {
var type = rowTokens[p].type;
if (next) {
if (type === 'keyword') {
scopedFunction = rowTokens[p];
// console.log("HIT",scopedFunction);
break;
}
next = false;
}
if (type === 'paren.lparen') {
depth-=rowTokens[p].value.length;
} else if (type === 'paren.rparen') {
depth+=rowTokens[p].value.length;
}
if (depth < 0) {
next = true;
depth = 0;
}
// console.log(r,p,depth,next,rowTokens[p]);
p--;
}
if (!scopedFunction) {
r--;
}
}
}
expressionEditor.session.removeMarker(currentFunctionMarker);
if (scopedFunction) {
//console.log(token,.map(function(t) { return t.type}));
funcSelect.val(scopedFunction.value).change();
}
}
});
dialogForm.i18n();
$("#node-input-expression-func-insert").click(function(e) {
e.preventDefault();
var pos = expressionEditor.getCursorPosition();
var f = funcSelect.val();
var snippet = jsonata.getFunctionSnippet(f);
expressionEditor.insertSnippet(snippet);
expressionEditor.focus();
})
},
close: function() {
editStack.pop();
},
show: function() {}
}
if (editTrayWidthCache.hasOwnProperty(type)) {
trayOptions.width = editTrayWidthCache[type];
}
RED.tray.show(trayOptions);
}
return {
init: function() {
RED.tray.init();
$(window).on('keydown', function(evt) {
if (evt.keyCode === $.ui.keyCode.ESCAPE && (evt.metaKey || evt.ctrlKey)) {
$("#node-dialog-cancel").click();
$("#node-config-dialog-cancel").click();
} else if (evt.keyCode === $.ui.keyCode.ENTER && (evt.metaKey || evt.ctrlKey)) {
$("#node-dialog-ok").click();
$("#node-config-dialog-ok").click();
}
RED.actions.add("core:confirm-edit-tray", function() {
$("#node-dialog-ok").click();
$("#node-config-dialog-ok").click();
});
RED.actions.add("core:cancel-edit-tray", function() {
$("#node-dialog-cancel").click();
$("#node-config-dialog-cancel").click();
});
},
edit: showEditDialog,
editConfig: showEditConfigNodeDialog,
editSubflow: showEditSubflowDialog,
editExpression: editExpression,
validateNode: validateNode,
updateNodeProperties: updateNodeProperties, // TODO: only exposed for edit-undo
@@ -1336,6 +1779,13 @@ RED.editor = (function() {
if (options.value) {
session.setValue(options.value,-1);
}
if (options.globals) {
setTimeout(function() {
if (!!session.$worker) {
session.$worker.send("setOptions", [{globals: options.globals, esversion:6}]);
}
},100);
}
return editor;
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2013 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,10 +15,101 @@
**/
RED.keyboard = (function() {
var isMac = /Mac/i.test(window.navigator.platform);
var handlers = {};
var partialState;
var keyMap = {
"left":37,
"up":38,
"right":39,
"down":40,
"escape":27,
"enter": 13,
"backspace": 8,
"delete": 46,
"space": 32,
";":186,
"=":187,
",":188,
"-":189,
".":190,
"/":191,
"\\":220,
"'":222,
"?":191 // <- QWERTY specific
}
var metaKeyCodes = {
16:true,
17:true,
18: true,
91:true,
93: true
}
var actionToKeyMap = {}
// FF generates some different keycodes because reasons.
var firefoxKeyCodeMap = {
59:186,
61:187,
173:189
}
function init() {
$.getJSON("red/keymap.json",function(data) {
for (var scope in data) {
if (data.hasOwnProperty(scope)) {
var keys = data[scope];
for (var key in keys) {
if (keys.hasOwnProperty(key)) {
addHandler(scope,key,keys[key]);
}
}
}
}
})
RED.actions.add("core:show-help", showKeyboardHelp);
}
function parseKeySpecifier(key) {
var parts = key.toLowerCase().split("-");
var modifiers = {};
var keycode;
var blank = 0;
for (var i=0;i<parts.length;i++) {
switch(parts[i]) {
case "ctrl":
case "cmd":
modifiers.ctrl = true;
modifiers.meta = true;
break;
case "alt":
modifiers.alt = true;
break;
case "shift":
modifiers.shift = true;
break;
case "":
blank++;
keycode = keyMap["-"];
break;
default:
if (keyMap.hasOwnProperty(parts[i])) {
keycode = keyMap[parts[i]];
} else if (parts[i].length > 1) {
return null;
} else {
keycode = parts[i].toUpperCase().charCodeAt(0);
}
break;
}
}
return [keycode,modifiers];
}
function resolveKeyEvent(evt) {
var slot = handlers;
var slot = partialState||handlers;
if (evt.ctrlKey || evt.metaKey) {
slot = slot.ctrl;
}
@@ -28,9 +119,19 @@ RED.keyboard = (function() {
if (slot && evt.altKey) {
slot = slot.alt;
}
if (slot && slot[evt.keyCode]) {
var handler = slot[evt.keyCode];
if (handler.scope && handler.scope !== "*") {
var keyCode = firefoxKeyCodeMap[evt.keyCode] || evt.keyCode;
if (slot && slot[keyCode]) {
var handler = slot[keyCode];
if (!handler.scope) {
if (partialState) {
partialState = null;
return resolveKeyEvent(evt);
} else {
partialState = handler;
evt.preventDefault();
return null;
}
} else if (handler.scope && handler.scope !== "*") {
var target = evt.target;
while (target.nodeName !== 'BODY' && target.id !== handler.scope) {
target = target.parentElement;
@@ -39,119 +140,206 @@ RED.keyboard = (function() {
handler = null;
}
}
partialState = null;
return handler;
} else if (partialState) {
partialState = null;
return resolveKeyEvent(evt);
}
}
d3.select(window).on("keydown",function() {
if (metaKeyCodes[d3.event.keyCode]) {
return;
}
var handler = resolveKeyEvent(d3.event);
if (handler && handler.ondown) {
handler.ondown();
}
});
d3.select(window).on("keyup",function() {
var handler = resolveKeyEvent(d3.event);
if (handler && handler.onup) {
handler.onup();
if (typeof handler.ondown === "string") {
RED.actions.invoke(handler.ondown);
} else {
handler.ondown();
}
d3.event.preventDefault();
}
});
function addHandler(scope,key,modifiers,ondown,onup) {
function addHandler(scope,key,modifiers,ondown) {
var mod = modifiers;
var cbdown = ondown;
var cbup = onup;
if (typeof modifiers == "function") {
if (typeof modifiers == "function" || typeof modifiers === "string") {
mod = {};
cbdown = modifiers;
cbup = ondown;
}
var keys = [];
var i=0;
if (typeof key === 'string') {
if (typeof cbdown === 'string') {
actionToKeyMap[cbdown] = {scope:scope,key:key};
}
var parts = key.split(" ");
for (i=0;i<parts.length;i++) {
var parsedKey = parseKeySpecifier(parts[i]);
if (parsedKey) {
keys.push(parsedKey);
} else {
console.log("Unrecognised key specifier:",key)
return;
}
}
} else {
keys.push([key,mod])
}
var slot = handlers;
if (mod.ctrl) {
slot.ctrl = slot.ctrl||{};
slot = slot.ctrl;
for (i=0;i<keys.length;i++) {
key = keys[i][0];
mod = keys[i][1];
if (mod.ctrl) {
slot.ctrl = slot.ctrl||{};
slot = slot.ctrl;
}
if (mod.shift) {
slot.shift = slot.shift||{};
slot = slot.shift;
}
if (mod.alt) {
slot.alt = slot.alt||{};
slot = slot.alt;
}
slot[key] = slot[key] || {};
slot = slot[key];
//slot[key] = {scope: scope, ondown:cbdown};
}
if (mod.shift) {
slot.shift = slot.shift||{};
slot = slot.shift;
}
if (mod.alt) {
slot.alt = slot.alt||{};
slot = slot.alt;
}
slot[key] = {scope: scope, ondown:cbdown, onup:cbup};
slot.scope = scope;
slot.ondown = cbdown;
}
function removeHandler(key,modifiers) {
var mod = modifiers || {};
var keys = [];
var i=0;
if (typeof key === 'string') {
delete actionToKeyMap[key];
var parts = key.split(" ");
for (i=0;i<parts.length;i++) {
var parsedKey = parseKeySpecifier(parts[i]);
if (parsedKey) {
keys.push(parsedKey);
} else {
console.log("Unrecognised key specifier:",key)
return;
}
}
} else {
keys.push([key,mod])
}
var slot = handlers;
if (mod.ctrl) {
slot = slot.ctrl;
}
if (slot && mod.shift) {
slot = slot.shift;
}
if (slot && mod.alt) {
slot = slot.alt;
}
if (slot) {
delete slot[key];
for (i=0;i<keys.length;i++) {
key = keys[i][0];
mod = keys[i][1];
if (mod.ctrl) {
slot = slot.ctrl;
}
if (slot && mod.shift) {
slot = slot.shift;
}
if (slot && mod.alt) {
slot = slot.alt;
}
if (!slot[key]) {
return;
}
slot = slot[key];
}
delete slot.scope;
delete slot.ondown;
}
var dialog = null;
var shortcutDialog = null;
var cmdCtrlKey = '<span class="help-key">'+(isMac?'&#8984;':'Ctrl')+'</span>';
function showKeyboardHelp() {
if (!RED.settings.theme("menu.menu-item-keyboard-shortcuts",true)) {
return;
}
if (!dialog) {
dialog = $('<div id="keyboard-help-dialog" class="hide">'+
'<div style="vertical-align: top;display:inline-block; box-sizing: border-box; width:50%; padding: 10px;">'+
'<table class="keyboard-shortcuts">'+
'<tr><td><span class="help-key">Ctrl/&#8984;</span> + <span class="help-key">a</span></td><td>'+RED._("keyboard.selectAll")+'</td></tr>'+
'<tr><td><span class="help-key">Shift</span> + <span class="help-key">Click</span></td><td>'+RED._("keyboard.selectAllConnected")+'</td></tr>'+
'<tr><td><span class="help-key">Ctrl/&#8984;</span> + <span class="help-key">Click</span></td><td>'+RED._("keyboard.addRemoveNode")+'</td></tr>'+
'<tr><td>&nbsp;</td><td></td></tr>'+
'<tr><td><span class="help-key">Ctrl/&#8984;</span> + <span class="help-key">i</span></td><td>'+RED._("keyboard.importNode")+'</td></tr>'+
'<tr><td><span class="help-key">Ctrl/&#8984;</span> + <span class="help-key">e</span></td><td>'+RED._("keyboard.exportNode")+'</td></tr>'+
'<tr><td>&nbsp;</td><td></td></tr>'+
'<tr><td><span class="help-key"> &#x2190; </span> <span class="help-key"> &#x2191; </span> <span class="help-key"> &#x2192; </span> <span class="help-key"> &#x2193; </span></td><td>'+RED._("keyboard.nudgeNode")+'</td></tr>'+
'<tr><td><span class="help-key">Shift</span> + <span class="help-key"> &#x2190; </span></td><td rowspan="4">'+RED._("keyboard.moveNode")+'</td></tr>'+
'<tr><td><span class="help-key">Shift</span> + <span class="help-key"> &#x2191; </span></td></tr>'+
'<tr><td><span class="help-key">Shift</span> + <span class="help-key"> &#x2192; </span></td></tr>'+
'<tr><td><span class="help-key">Shift</span> + <span class="help-key"> &#x2193; </span></td></tr>'+
'</table>'+
'</div>'+
'<div style="vertical-align: top;display:inline-block; box-sizing: border-box; width:50%; padding: 10px;">'+
'<table class="keyboard-shortcuts">'+
'<tr><td><span class="help-key">Ctrl/&#8984;</span> + <span class="help-key">Space</span></td><td>'+RED._("keyboard.toggleSidebar")+'</td></tr>'+
'<tr><td></td><td></td></tr>'+
'<tr><td><span class="help-key">Delete</span></td><td rowspan="2">'+RED._("keyboard.deleteSelected")+'</td></tr>'+
'<tr><td><span class="help-key">Backspace</span></td></tr>'+
'<tr><td></td><td></td></tr>'+
'<tr><td><span class="help-key">Ctrl/&#8984;</span> + <span class="help-key">c</span></td><td>'+RED._("keyboard.copyNode")+'</td></tr>'+
'<tr><td><span class="help-key">Ctrl/&#8984;</span> + <span class="help-key">x</span></td><td>'+RED._("keyboard.cutNode")+'</td></tr>'+
'<tr><td><span class="help-key">Ctrl/&#8984;</span> + <span class="help-key">v</span></td><td>'+RED._("keyboard.pasteNode")+'</td></tr>'+
'<tr><td><span class="help-key">Ctrl/&#8984;</span> + <span class="help-key">z</span></td><td>'+RED._("keyboard.undoChange")+'</td></tr>'+
'</table>'+
if (!shortcutDialog) {
shortcutDialog = $('<div id="keyboard-help-dialog" class="hide">'+
'<div class="keyboard-shortcut-entry keyboard-shortcut-list-header">'+
'<div class="keyboard-shortcut-entry-key">shortcut</div>'+
'<div class="keyboard-shortcut-entry-key">action</div>'+
'<div class="keyboard-shortcut-entry-scope">scope</div>'+
'</div>'+
'<ol id="keyboard-shortcut-list"></ol>'+
'</div>')
.appendTo("body")
.dialog({
.appendTo("body");
var shortcutList = $('#keyboard-shortcut-list').editableList({
addButton: false,
scrollOnAdd: false,
addItem: function(container,i,object) {
var item = $('<div class="keyboard-shortcut-entry">').appendTo(container);
var key = $('<div class="keyboard-shortcut-entry-key">').appendTo(item);
if (object.key) {
key.append(formatKey(object.key));
} else {
item.addClass("keyboard-shortcut-entry-unassigned");
key.html(RED._('keyboard.unassigned'));
}
var text = object.id.replace(/(^.+:([a-z]))|(-([a-z]))/g,function() {
if (arguments[5] === 0) {
return arguments[2].toUpperCase();
} else {
return " "+arguments[4].toUpperCase();
}
});
var label = $('<div>').html(text).appendTo(item);
if (object.scope) {
$('<div class="keyboard-shortcut-entry-scope">').html(object.scope).appendTo(item);
}
},
});
var shortcuts = RED.actions.list();
shortcuts.sort(function(A,B) {
return A.id.localeCompare(B.id);
});
shortcuts.forEach(function(s) {
shortcutList.editableList('addItem',s);
})
shortcutDialog.dialog({
modal: true,
autoOpen: false,
width: "800",
title:"Keyboard shortcuts",
height: "400",
title:RED._("keyboard.title"),
resizable: false
});
}
dialog.dialog("open");
shortcutDialog.dialog("open");
}
function formatKey(key) {
var formattedKey = isMac?key.replace(/ctrl-?/,"&#8984;"):key;
formattedKey = isMac?formattedKey.replace(/alt-?/,"&#8997;"):key;
formattedKey = formattedKey.replace(/shift-?/,"&#8679;")
formattedKey = formattedKey.replace(/left/,"&#x2190;")
formattedKey = formattedKey.replace(/up/,"&#x2191;")
formattedKey = formattedKey.replace(/right/,"&#x2192;")
formattedKey = formattedKey.replace(/down/,"&#x2193;")
return '<span class="help-key-block"><span class="help-key">'+formattedKey.split(" ").join('</span> <span class="help-key">')+'</span></span>';
}
return {
init: init,
add: addHandler,
remove: removeHandler,
showHelp: showKeyboardHelp
getShortcut: function(actionName) {
return actionToKeyMap[actionName];
},
formatKey: formatKey
}
})();

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2013, 2016 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -410,6 +410,9 @@ RED.library = (function() {
return {
init: function() {
RED.actions.add("core:library-export",exportFlow);
RED.events.on("view:selection-changed",function(selection) {
if (!selection.nodes) {
RED.menu.setDisabled("menu-item-export",true);

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2013, 2016 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,11 +51,17 @@ RED.notify = (function() {
n.update = (function() {
var nn = n;
return function(msg) {
return function(msg,timeout) {
nn.innerHTML = msg;
if (timeout !== undefined && timeout > 0) {
window.clearTimeout(nn.timeoutid);
nn.timeoutid = window.setTimeout(nn.close,timeout);
} else {
window.clearTimeout(nn.timeoutid);
}
}
})();
if (!fixed) {
$(n).click((function() {
var nn = n;

View File

@@ -0,0 +1,956 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
RED.palette.editor = (function() {
var disabled = false;
var editorTabs;
var filterInput;
var searchInput;
var nodeList;
var packageList;
var loadedList = [];
var filteredList = [];
var loadedIndex = {};
var typesInUse = {};
var nodeEntries = {};
var eventTimers = {};
var activeFilter = "";
function semVerCompare(A,B) {
var aParts = A.split(".").map(function(m) { return parseInt(m);});
var bParts = B.split(".").map(function(m) { return parseInt(m);});
for (var i=0;i<3;i++) {
var j = aParts[i]-bParts[i];
if (j<0) { return -1 }
if (j>0) { return 1 }
}
return 0;
}
function delayCallback(start,callback) {
var delta = Date.now() - start;
if (delta < 300) {
delta = 300;
} else {
delta = 0;
}
setTimeout(function() {
callback();
},delta);
}
function changeNodeState(id,state,shade,callback) {
shade.show();
var start = Date.now();
$.ajax({
url:"nodes/"+id,
type: "PUT",
data: JSON.stringify({
enabled: state
}),
contentType: "application/json; charset=utf-8"
}).done(function(data,textStatus,xhr) {
delayCallback(start,function() {
shade.hide();
callback();
});
}).fail(function(xhr,textStatus,err) {
delayCallback(start,function() {
shade.hide();
callback(xhr);
});
})
}
function installNodeModule(id,version,shade,callback) {
var requestBody = {
module: id
};
if (callback === undefined) {
callback = shade;
shade = version;
} else {
requestBody.version = version;
}
shade.show();
$.ajax({
url:"nodes",
type: "POST",
data: JSON.stringify(requestBody),
contentType: "application/json; charset=utf-8"
}).done(function(data,textStatus,xhr) {
shade.hide();
callback();
}).fail(function(xhr,textStatus,err) {
shade.hide();
callback(xhr);
});
}
function removeNodeModule(id,callback) {
$.ajax({
url:"nodes/"+id,
type: "DELETE"
}).done(function(data,textStatus,xhr) {
callback();
}).fail(function(xhr,textStatus,err) {
callback(xhr);
})
}
function refreshNodeModuleList() {
for (var id in nodeEntries) {
if (nodeEntries.hasOwnProperty(id)) {
_refreshNodeModule(id);
}
}
}
function refreshNodeModule(module) {
if (!eventTimers.hasOwnProperty(module)) {
eventTimers[module] = setTimeout(function() {
delete eventTimers[module];
_refreshNodeModule(module);
},100);
}
}
function getContrastingBorder(rgbColor){
var parts = /^rgba?\(\s*(\d+),\s*(\d+),\s*(\d+)[,)]/.exec(rgbColor);
if (parts) {
var r = parseInt(parts[1]);
var g = parseInt(parts[2]);
var b = parseInt(parts[3]);
var yiq = ((r*299)+(g*587)+(b*114))/1000;
if (yiq > 160) {
r = Math.floor(r*0.8);
g = Math.floor(g*0.8);
b = Math.floor(b*0.8);
return "rgb("+r+","+g+","+b+")";
}
}
return rgbColor;
}
function formatUpdatedAt(dateString) {
var now = new Date();
var d = new Date(dateString);
var delta = (Date.now() - new Date(dateString).getTime())/1000;
if (delta < 60) {
return RED._('palette.editor.times.seconds');
}
delta = Math.floor(delta/60);
if (delta < 10) {
return RED._('palette.editor.times.minutes');
}
if (delta < 60) {
return RED._('palette.editor.times.minutesV',{count:delta});
}
delta = Math.floor(delta/60);
if (delta < 24) {
return RED._('palette.editor.times.hoursV',{count:delta});
}
delta = Math.floor(delta/24);
if (delta < 7) {
return RED._('palette.editor.times.daysV',{count:delta})
}
var weeks = Math.floor(delta/7);
var days = delta%7;
if (weeks < 4) {
return RED._('palette.editor.times.weeksV',{count:weeks})
}
var months = Math.floor(weeks/4);
weeks = weeks%4;
if (months < 12) {
return RED._('palette.editor.times.monthsV',{count:months})
}
var years = Math.floor(months/12);
months = months%12;
if (months === 0) {
return RED._('palette.editor.times.yearsV',{count:years})
} else {
return RED._('palette.editor.times.year'+(years>1?'s':'')+'MonthsV',{y:years,count:months})
}
}
function _refreshNodeModule(module) {
if (!nodeEntries.hasOwnProperty(module)) {
nodeEntries[module] = {info:RED.nodes.registry.getModule(module)};
var index = [module];
for (var s in nodeEntries[module].info.sets) {
if (nodeEntries[module].info.sets.hasOwnProperty(s)) {
index.push(s);
index = index.concat(nodeEntries[module].info.sets[s].types)
}
}
nodeEntries[module].index = index.join(",").toLowerCase();
nodeList.editableList('addItem', nodeEntries[module]);
//console.log(nodeList.editableList('items'));
} else {
var moduleInfo = nodeEntries[module].info;
var nodeEntry = nodeEntries[module].elements;
if (nodeEntry) {
var activeTypeCount = 0;
var typeCount = 0;
nodeEntries[module].totalUseCount = 0;
nodeEntries[module].setUseCount = {};
for (var setName in moduleInfo.sets) {
if (moduleInfo.sets.hasOwnProperty(setName)) {
var inUseCount = 0;
var set = moduleInfo.sets[setName];
var setElements = nodeEntry.sets[setName];
if (set.enabled) {
activeTypeCount += set.types.length;
}
typeCount += set.types.length;
for (var i=0;i<moduleInfo.sets[setName].types.length;i++) {
var t = moduleInfo.sets[setName].types[i];
inUseCount += (typesInUse[t]||0);
var swatch = setElements.swatches[t];
if (set.enabled) {
var def = RED.nodes.getType(t);
if (def && def.color) {
swatch.css({background:def.color});
swatch.css({border: "1px solid "+getContrastingBorder(swatch.css('backgroundColor'))})
} else {
swatch.css({background:"#eee",border:"1px dashed #999"})
}
} else {
swatch.css({background:"#eee",border:"1px dashed #999"})
}
}
nodeEntries[module].setUseCount[setName] = inUseCount;
nodeEntries[module].totalUseCount += inUseCount;
if (inUseCount > 0) {
setElements.enableButton.html(RED._('palette.editor.inuse'));
setElements.enableButton.addClass('disabled');
} else {
setElements.enableButton.removeClass('disabled');
if (set.enabled) {
setElements.enableButton.html(RED._('palette.editor.disable'));
} else {
setElements.enableButton.html(RED._('palette.editor.enable'));
}
}
setElements.setRow.toggleClass("palette-module-set-disabled",!set.enabled);
}
}
var nodeCount = (activeTypeCount === typeCount)?typeCount:activeTypeCount+" / "+typeCount;
nodeEntry.setCount.html(RED._('palette.editor.nodeCount',{count:typeCount,label:nodeCount}));
if (nodeEntries[module].totalUseCount > 0) {
nodeEntry.enableButton.html(RED._('palette.editor.inuse'));
nodeEntry.enableButton.addClass('disabled');
nodeEntry.removeButton.hide();
} else {
nodeEntry.enableButton.removeClass('disabled');
if (moduleInfo.local) {
nodeEntry.removeButton.show();
}
if (activeTypeCount === 0) {
nodeEntry.enableButton.html(RED._('palette.editor.enableall'));
} else {
nodeEntry.enableButton.html(RED._('palette.editor.disableall'));
}
nodeEntry.container.toggleClass("disabled",(activeTypeCount === 0));
}
}
if (moduleInfo.pending_version) {
nodeEntry.versionSpan.html(moduleInfo.version+' <i class="fa fa-long-arrow-right"></i> '+moduleInfo.pending_version).appendTo(nodeEntry.metaRow)
nodeEntry.updateButton.html(RED._('palette.editor.updated')).addClass('disabled').show();
} else if (loadedIndex.hasOwnProperty(module)) {
if (semVerCompare(loadedIndex[module].version,moduleInfo.version) === 1) {
nodeEntry.updateButton.show();
nodeEntry.updateButton.html(RED._('palette.editor.update',{version:loadedIndex[module].version}));
} else {
nodeEntry.updateButton.hide();
}
} else {
nodeEntry.updateButton.hide();
}
}
}
function showPaletteEditor() {
if (RED.settings.theme('palette.editable') === false) {
return;
}
if (disabled) {
return;
}
initInstallTab();
$("#header-shade").show();
$("#editor-shade").show();
$("#sidebar-shade").show();
$("#sidebar-separator").hide();
editorTabs.activateTab('nodes');
$("#main-container").addClass("palette-expanded");
setTimeout(function() {
editorTabs.resize();
filterInput.focus();
},250);
RED.events.emit("palette-editor:open");
RED.keyboard.add("*","escape",function(){hidePaletteEditor()});
}
function hidePaletteEditor() {
RED.keyboard.remove("escape");
$("#main-container").removeClass("palette-expanded");
$("#header-shade").hide();
$("#editor-shade").hide();
$("#sidebar-shade").hide();
$("#sidebar-separator").show();
$("#palette-editor").find('.expanded').each(function(i,el) {
$(el).find(".palette-module-content").slideUp();
$(el).removeClass('expanded');
});
filterInput.searchBox('value',"");
searchInput.searchBox('value',"");
RED.events.emit("palette-editor:close");
}
function filterChange(val) {
activeFilter = val.toLowerCase();
var visible = nodeList.editableList('filter');
var size = nodeList.editableList('length');
if (val === "") {
filterInput.searchBox('count');
} else {
filterInput.searchBox('count',visible+" / "+size);
}
}
var catalogueCount;
var catalogueLoadStatus = [];
var catalogueLoadStart;
var catalogueLoadErrors = false;
var activeSort = sortModulesAZ;
function handleCatalogResponse(err,catalog,index,v) {
catalogueLoadStatus.push(err||v);
if (!err) {
if (v.modules) {
v.modules.forEach(function(m) {
loadedIndex[m.id] = m;
m.index = [m.id];
if (m.keywords) {
m.index = m.index.concat(m.keywords);
}
if (m.updated_at) {
m.timestamp = new Date(m.updated_at).getTime();
} else {
m.timestamp = 0;
}
m.index = m.index.join(",").toLowerCase();
})
loadedList = loadedList.concat(v.modules);
}
searchInput.searchBox('count',loadedList.length);
} else {
catalogueLoadErrors = true;
}
if (catalogueCount > 1) {
$(".palette-module-shade-status").html(RED._('palette.editor.loading')+"<br>"+catalogueLoadStatus.length+"/"+catalogueCount);
}
if (catalogueLoadStatus.length === catalogueCount) {
if (catalogueLoadErrors) {
RED.notify(RED._('palette.editor.errors.catalogLoadFailed',{url: catalog}),"error",false,8000);
}
var delta = 250-(Date.now() - catalogueLoadStart);
setTimeout(function() {
$("#palette-module-install-shade").hide();
},Math.max(delta,0));
}
}
function initInstallTab() {
if (loadedList.length === 0) {
loadedList = [];
loadedIndex = {};
packageList.editableList('empty');
$(".palette-module-shade-status").html(RED._('palette.editor.loading'));
var catalogues = RED.settings.theme('palette.catalogues')||['https://catalogue.nodered.org/catalogue.json'];
catalogueLoadStatus = [];
catalogueLoadErrors = false;
catalogueCount = catalogues.length;
if (catalogues.length > 1) {
$(".palette-module-shade-status").html(RED._('palette.editor.loading')+"<br>0/"+catalogues.length);
}
$("#palette-module-install-shade").show();
catalogueLoadStart = Date.now();
catalogues.forEach(function(catalog,index) {
$.getJSON(catalog, {_: new Date().getTime()},function(v) {
handleCatalogResponse(null,catalog,index,v);
refreshNodeModuleList();
}).fail(function(jqxhr, textStatus, error) {
handleCatalogResponse(jqxhr,catalog,index);
})
});
}
}
function refreshFilteredItems() {
packageList.editableList('empty');
filteredList.sort(activeSort);
for (var i=0;i<Math.min(10,filteredList.length);i++) {
packageList.editableList('addItem',filteredList[i]);
}
if (filteredList.length === 0) {
packageList.editableList('addItem',{});
}
if (filteredList.length > 10) {
packageList.editableList('addItem',{start:10,more:filteredList.length-10})
}
}
function sortModulesAZ(A,B) {
return A.info.id.localeCompare(B.info.id);
}
function sortModulesRecent(A,B) {
return -1 * (A.info.timestamp-B.info.timestamp);
}
function init() {
if (RED.settings.theme('palette.editable') === false) {
return;
}
RED.events.on("editor:open",function() { disabled = true; });
RED.events.on("editor:close",function() { disabled = false; });
RED.events.on("search:open",function() { disabled = true; });
RED.events.on("search:close",function() { disabled = false; });
RED.events.on("type-search:open",function() { disabled = true; });
RED.events.on("type-search:close",function() { disabled = false; });
RED.actions.add("core:manage-palette",RED.palette.editor.show);
editorTabs = RED.tabs.create({
id:"palette-editor-tabs",
onchange:function(tab) {
$("#palette-editor .palette-editor-tab").hide();
tab.content.show();
if (filterInput) {
filterInput.searchBox('value',"");
}
if (searchInput) {
searchInput.searchBox('value',"");
}
if (tab.id === 'install') {
if (searchInput) {
searchInput.focus();
}
} else {
if (filterInput) {
filterInput.focus();
}
}
},
minimumActiveTabWidth: 110
});
$("#editor-shade").click(function() {
if ($("#main-container").hasClass("palette-expanded")) {
hidePaletteEditor();
}
});
$("#palette-editor-close").on("click", function(e) {
hidePaletteEditor();
})
var modulesTab = $('<div>',{class:"palette-editor-tab"}).appendTo("#palette-editor");
editorTabs.addTab({
id: 'nodes',
label: RED._('palette.editor.tab-nodes'),
content: modulesTab
})
var filterDiv = $('<div>',{class:"palette-search"}).appendTo(modulesTab);
filterInput = $('<input type="text" data-i18n="[placeholder]palette.filter"></input>')
.appendTo(filterDiv)
.searchBox({
delay: 200,
change: function() {
filterChange($(this).val());
}
});
nodeList = $('<ol>',{id:"palette-module-list", style:"position: absolute;top: 35px;bottom: 0;left: 0;right: 0px;"}).appendTo(modulesTab).editableList({
addButton: false,
scrollOnAdd: false,
sort: function(A,B) {
return A.info.name.localeCompare(B.info.name);
},
filter: function(data) {
if (activeFilter === "" ) {
return true;
}
return (activeFilter==="")||(data.index.indexOf(activeFilter) > -1);
},
addItem: function(container,i,object) {
var entry = object.info;
if (entry) {
var headerRow = $('<div>',{class:"palette-module-header"}).appendTo(container);
var titleRow = $('<div class="palette-module-meta palette-module-name"><i class="fa fa-cube"></i></div>').appendTo(headerRow);
$('<span>').html(entry.name).appendTo(titleRow);
var metaRow = $('<div class="palette-module-meta palette-module-version"><i class="fa fa-tag"></i></div>').appendTo(headerRow);
var versionSpan = $('<span>').html(entry.version).appendTo(metaRow);
var buttonRow = $('<div>',{class:"palette-module-meta"}).appendTo(headerRow);
var setButton = $('<a href="#" class="editor-button editor-button-small palette-module-set-button"><i class="fa fa-angle-right palette-module-node-chevron"></i> </a>').appendTo(buttonRow);
var setCount = $('<span>').appendTo(setButton);
var buttonGroup = $('<div>',{class:"palette-module-button-group"}).appendTo(buttonRow);
var updateButton = $('<a href="#" class="editor-button editor-button-small"></a>').html(RED._('palette.editor.update')).appendTo(buttonGroup);
updateButton.click(function(evt) {
evt.preventDefault();
if ($(this).hasClass('disabled')) {
return;
}
$("#palette-module-install-confirm").data('module',entry.name);
$("#palette-module-install-confirm").data('version',loadedIndex[entry.name].version);
$("#palette-module-install-confirm").data('shade',shade);
$("#palette-module-install-confirm-body").html(entry.local?
RED._("palette.editor.confirm.update.body"):
RED._("palette.editor.confirm.cannotUpdate.body")
);
$(".palette-module-install-confirm-button-install").hide();
$(".palette-module-install-confirm-button-remove").hide();
if (entry.local) {
$(".palette-module-install-confirm-button-update").show();
} else {
$(".palette-module-install-confirm-button-update").hide();
}
$("#palette-module-install-confirm")
.dialog('option', 'title',RED._("palette.editor.confirm.update.title"))
.dialog('open');
})
var removeButton = $('<a href="#" class="editor-button editor-button-small"></a>').html(RED._('palette.editor.remove')).appendTo(buttonGroup);
removeButton.click(function(evt) {
evt.preventDefault();
$("#palette-module-install-confirm").data('module',entry.name);
$("#palette-module-install-confirm").data('shade',shade);
$("#palette-module-install-confirm-body").html(RED._("palette.editor.confirm.remove.body"));
$(".palette-module-install-confirm-button-install").hide();
$(".palette-module-install-confirm-button-remove").show();
$(".palette-module-install-confirm-button-update").hide();
$("#palette-module-install-confirm")
.dialog('option', 'title', RED._("palette.editor.confirm.remove.title"))
.dialog('open');
})
if (!entry.local) {
removeButton.hide();
}
var enableButton = $('<a href="#" class="editor-button editor-button-small"></a>').html(RED._('palette.editor.disableall')).appendTo(buttonGroup);
var contentRow = $('<div>',{class:"palette-module-content"}).appendTo(container);
var shade = $('<div class="palette-module-shade hide"><img src="red/images/spin.svg" class="palette-spinner"/></div>').appendTo(container);
object.elements = {
updateButton: updateButton,
removeButton: removeButton,
enableButton: enableButton,
setCount: setCount,
container: container,
shade: shade,
versionSpan: versionSpan,
sets: {}
}
setButton.click(function(evt) {
evt.preventDefault();
if (container.hasClass('expanded')) {
container.removeClass('expanded');
contentRow.slideUp();
} else {
container.addClass('expanded');
contentRow.slideDown();
}
})
var setList = Object.keys(entry.sets)
setList.sort(function(A,B) {
return A.toLowerCase().localeCompare(B.toLowerCase());
});
setList.forEach(function(setName) {
var set = entry.sets[setName];
var setRow = $('<div>',{class:"palette-module-set"}).appendTo(contentRow);
var buttonGroup = $('<div>',{class:"palette-module-set-button-group"}).appendTo(setRow);
var typeSwatches = {};
set.types.forEach(function(t) {
var typeDiv = $('<div>',{class:"palette-module-type"}).appendTo(setRow);
typeSwatches[t] = $('<span>',{class:"palette-module-type-swatch"}).appendTo(typeDiv);
$('<span>',{class:"palette-module-type-node"}).html(t).appendTo(typeDiv);
})
var enableButton = $('<a href="#" class="editor-button editor-button-small"></a>').appendTo(buttonGroup);
enableButton.click(function(evt) {
evt.preventDefault();
if (object.setUseCount[setName] === 0) {
var currentSet = RED.nodes.registry.getNodeSet(set.id);
shade.show();
changeNodeState(set.id,!currentSet.enabled,shade,function(xhr){
console.log(xhr)
});
}
})
object.elements.sets[set.name] = {
setRow: setRow,
enableButton: enableButton,
swatches: typeSwatches
};
});
enableButton.click(function(evt) {
evt.preventDefault();
if (object.totalUseCount === 0) {
changeNodeState(entry.name,(container.hasClass('disabled')),shade,function(xhr){
console.log(xhr)
});
}
})
refreshNodeModule(entry.name);
} else {
$('<div>',{class:"red-ui-search-empty"}).html(RED._('search.empty')).appendTo(container);
}
}
});
var installTab = $('<div>',{class:"palette-editor-tab hide"}).appendTo("#palette-editor");
editorTabs.addTab({
id: 'install',
label: RED._('palette.editor.tab-install'),
content: installTab
})
var toolBar = $('<div>',{class:"palette-editor-toolbar"}).appendTo(installTab);
var searchDiv = $('<div>',{class:"palette-search"}).appendTo(installTab);
searchInput = $('<input type="text" data-i18n="[placeholder]palette.search"></input>')
.appendTo(searchDiv)
.searchBox({
delay: 300,
change: function() {
var searchTerm = $(this).val().toLowerCase();
if (searchTerm.length > 0) {
filteredList = loadedList.filter(function(m) {
return (m.index.indexOf(searchTerm) > -1);
}).map(function(f) { return {info:f}});
refreshFilteredItems();
searchInput.searchBox('count',filteredList.length+" / "+loadedList.length);
} else {
searchInput.searchBox('count',loadedList.length);
packageList.editableList('empty');
}
}
});
$('<span>').html(RED._("palette.editor.sort")+' ').appendTo(toolBar);
var sortGroup = $('<span class="button-group"></span>').appendTo(toolBar);
var sortAZ = $('<a href="#" class="sidebar-header-button-toggle selected" data-i18n="palette.editor.sortAZ"></a>').appendTo(sortGroup);
var sortRecent = $('<a href="#" class="sidebar-header-button-toggle" data-i18n="palette.editor.sortRecent"></a>').appendTo(sortGroup);
sortAZ.click(function(e) {
e.preventDefault();
if ($(this).hasClass("selected")) {
return;
}
$(this).addClass("selected");
sortRecent.removeClass("selected");
activeSort = sortModulesAZ;
refreshFilteredItems();
});
sortRecent.click(function(e) {
e.preventDefault();
if ($(this).hasClass("selected")) {
return;
}
$(this).addClass("selected");
sortAZ.removeClass("selected");
activeSort = sortModulesRecent;
refreshFilteredItems();
});
var refreshSpan = $('<span>').appendTo(toolBar);
var refreshButton = $('<a href="#" class="sidebar-header-button"><i class="fa fa-refresh"></i></a>').appendTo(refreshSpan);
refreshButton.click(function(e) {
e.preventDefault();
loadedList = [];
loadedIndex = {};
initInstallTab();
})
packageList = $('<ol>',{style:"position: absolute;top: 78px;bottom: 0;left: 0;right: 0px;"}).appendTo(installTab).editableList({
addButton: false,
scrollOnAdd: false,
addItem: function(container,i,object) {
if (object.more) {
container.addClass('palette-module-more');
var moreRow = $('<div>',{class:"palette-module-header palette-module"}).appendTo(container);
var moreLink = $('<a href="#"></a>').html(RED._('palette.editor.more',{count:object.more})).appendTo(moreRow);
moreLink.click(function(e) {
e.preventDefault();
packageList.editableList('removeItem',object);
for (var i=object.start;i<Math.min(object.start+10,object.start+object.more);i++) {
packageList.editableList('addItem',filteredList[i]);
}
if (object.more > 10) {
packageList.editableList('addItem',{start:object.start+10, more:object.more-10})
}
})
return;
}
if (object.info) {
var entry = object.info;
var headerRow = $('<div>',{class:"palette-module-header"}).appendTo(container);
var titleRow = $('<div class="palette-module-meta"><i class="fa fa-cube"></i></div>').appendTo(headerRow);
$('<span>',{class:"palette-module-name"}).html(entry.name||entry.id).appendTo(titleRow);
$('<a target="_blank" class="palette-module-link"><i class="fa fa-external-link"></i></a>').attr('href',entry.url).appendTo(titleRow);
var descRow = $('<div class="palette-module-meta"></div>').appendTo(headerRow);
$('<div>',{class:"palette-module-description"}).html(entry.description).appendTo(descRow);
var metaRow = $('<div class="palette-module-meta"></div>').appendTo(headerRow);
$('<span class="palette-module-version"><i class="fa fa-tag"></i> '+entry.version+'</span>').appendTo(metaRow);
$('<span class="palette-module-updated"><i class="fa fa-calendar"></i> '+formatUpdatedAt(entry.updated_at)+'</span>').appendTo(metaRow);
var buttonRow = $('<div>',{class:"palette-module-meta"}).appendTo(headerRow);
var buttonGroup = $('<div>',{class:"palette-module-button-group"}).appendTo(buttonRow);
var shade = $('<div class="palette-module-shade hide"><img src="red/images/spin.svg" class="palette-spinner"/></div>').appendTo(container);
var installButton = $('<a href="#" class="editor-button editor-button-small"></a>').html(RED._('palette.editor.install')).appendTo(buttonGroup);
installButton.click(function(e) {
e.preventDefault();
if (!$(this).hasClass('disabled')) {
$("#palette-module-install-confirm").data('module',entry.id);
$("#palette-module-install-confirm").data('version',entry.version);
$("#palette-module-install-confirm").data('url',entry.url);
$("#palette-module-install-confirm").data('shade',shade);
$("#palette-module-install-confirm-body").html(RED._("palette.editor.confirm.install.body"));
$(".palette-module-install-confirm-button-install").show();
$(".palette-module-install-confirm-button-remove").hide();
$(".palette-module-install-confirm-button-update").hide();
$("#palette-module-install-confirm")
.dialog('option', 'title', RED._("palette.editor.confirm.install.title"))
.dialog('open');
}
})
if (nodeEntries.hasOwnProperty(entry.id)) {
installButton.addClass('disabled');
installButton.html(RED._('palette.editor.installed'));
}
object.elements = {
installButton:installButton
}
} else {
$('<div>',{class:"red-ui-search-empty"}).html(RED._('search.empty')).appendTo(container);
}
}
});
$('<div id="palette-module-install-shade" class="palette-module-shade hide"><div class="palette-module-shade-status"></div><img src="red/images/spin.svg" class="palette-spinner"/></div>').appendTo(installTab);
$('<div id="palette-module-install-confirm" class="hide"><form class="form-horizontal"><div id="palette-module-install-confirm-body" class="node-dialog-confirm-row"></div></form></div>').appendTo(document.body);
$("#palette-module-install-confirm").dialog({
title: RED._('palette.editor.confirm.title'),
modal: true,
autoOpen: false,
width: 550,
height: "auto",
buttons: [
{
text: RED._("common.label.cancel"),
click: function() {
$( this ).dialog( "close" );
}
},
{
text: RED._("palette.editor.confirm.button.review"),
class: "primary palette-module-install-confirm-button-install",
click: function() {
var url = $(this).data('url');
window.open(url);
}
},
{
text: RED._("palette.editor.confirm.button.install"),
class: "primary palette-module-install-confirm-button-install",
click: function() {
var id = $(this).data('module');
var version = $(this).data('version');
var shade = $(this).data('shade');
installNodeModule(id,version,shade,function(xhr) {
if (xhr) {
if (xhr.responseJSON) {
RED.notify(RED._('palette.editor.errors.installFailed',{module: id,message:xhr.responseJSON.message}));
}
}
});
$( this ).dialog( "close" );
}
},
{
text: RED._("palette.editor.confirm.button.remove"),
class: "primary palette-module-install-confirm-button-remove",
click: function() {
var id = $(this).data('module');
var shade = $(this).data('shade');
shade.show();
removeNodeModule(id, function(xhr) {
shade.hide();
if (xhr) {
if (xhr.responseJSON) {
RED.notify(RED._('palette.editor.errors.removeFailed',{module: id,message:xhr.responseJSON.message}));
}
}
})
$( this ).dialog( "close" );
}
},
{
text: RED._("palette.editor.confirm.button.update"),
class: "primary palette-module-install-confirm-button-update",
click: function() {
var id = $(this).data('module');
var version = $(this).data('version');
var shade = $(this).data('shade');
shade.show();
installNodeModule(id,version,shade,function(xhr) {
if (xhr) {
if (xhr.responseJSON) {
RED.notify(RED._('palette.editor.errors.updateFailed',{module: id,message:xhr.responseJSON.message}));
}
}
});
$( this ).dialog( "close" );
}
}
]
})
RED.events.on('registry:module-updated', function(ns) {
refreshNodeModule(ns.module);
});
RED.events.on('registry:node-set-enabled', function(ns) {
refreshNodeModule(ns.module);
});
RED.events.on('registry:node-set-disabled', function(ns) {
refreshNodeModule(ns.module);
});
RED.events.on('registry:node-type-added', function(nodeType) {
if (!/^subflow:/.test(nodeType)) {
var ns = RED.nodes.registry.getNodeSetForType(nodeType);
refreshNodeModule(ns.module);
}
});
RED.events.on('registry:node-type-removed', function(nodeType) {
if (!/^subflow:/.test(nodeType)) {
var ns = RED.nodes.registry.getNodeSetForType(nodeType);
refreshNodeModule(ns.module);
}
});
RED.events.on('registry:node-set-added', function(ns) {
refreshNodeModule(ns.module);
for (var i=0;i<filteredList.length;i++) {
if (filteredList[i].info.id === ns.module) {
var installButton = filteredList[i].elements.installButton;
installButton.addClass('disabled');
installButton.html(RED._('palette.editor.installed'));
break;
}
}
});
RED.events.on('registry:node-set-removed', function(ns) {
var module = RED.nodes.registry.getModule(ns.module);
if (!module) {
var entry = nodeEntries[ns.module];
if (entry) {
nodeList.editableList('removeItem', entry);
delete nodeEntries[ns.module];
for (var i=0;i<filteredList.length;i++) {
if (filteredList[i].info.id === ns.module) {
var installButton = filteredList[i].elements.installButton;
installButton.removeClass('disabled');
installButton.html(RED._('palette.editor.install'));
break;
}
}
}
}
});
RED.events.on('nodes:add', function(n) {
if (!/^subflow:/.test(n.type)) {
typesInUse[n.type] = (typesInUse[n.type]||0)+1;
if (typesInUse[n.type] === 1) {
var ns = RED.nodes.registry.getNodeSetForType(n.type);
refreshNodeModule(ns.module);
}
}
})
RED.events.on('nodes:remove', function(n) {
if (typesInUse.hasOwnProperty(n.type)) {
typesInUse[n.type]--;
if (typesInUse[n.type] === 0) {
delete typesInUse[n.type];
var ns = RED.nodes.registry.getNodeSetForType(n.type);
refreshNodeModule(ns.module);
}
}
})
}
return {
init: init,
show: showPaletteEditor
}
})();

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2013, 2016 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
RED.palette = (function() {
var exclusion = ['config','unknown','deprecated'];
var core = ['subflows', 'input', 'output', 'function', 'social', 'mobile', 'storage', 'analysis', 'advanced'];
var coreCategories = ['subflows', 'input', 'output', 'function', 'social', 'mobile', 'storage', 'analysis', 'advanced'];
var categoryContainers = {};
@@ -91,17 +91,17 @@ RED.palette = (function() {
el.css({height:multiLineNodeHeight+"px"});
var labelElement = el.find(".palette_label");
labelElement.html(lines);
labelElement.html(lines).attr('dir', RED.text.bidi.resolveBaseTextDir(lines));
el.find(".palette_port").css({top:(multiLineNodeHeight/2-5)+"px"});
var popOverContent;
try {
var l = "<p><b>"+label+"</b></p>";
var l = "<p><b>"+RED.text.bidi.enforceTextDirectionWithUCC(label)+"</b></p>";
if (label != type) {
l = "<p><b>"+label+"</b><br/><i>"+type+"</i></p>";
l = "<p><b>"+RED.text.bidi.enforceTextDirectionWithUCC(label)+"</b><br/><i>"+type+"</i></p>";
}
popOverContent = $(l+(info?info:$("script[data-help-name|='"+type+"']").html()||"<p>"+RED._("palette.noInfo")+"</p>").trim())
popOverContent = $(l+(info?info:$("script[data-help-name$='"+type+"']").html()||"<p>"+RED._("palette.noInfo")+"</p>").trim())
.filter(function(n) {
return (this.nodeType == 1 && this.nodeName == "P") || (this.nodeType == 3 && this.textContent.trim().length > 0)
}).slice(0,2);
@@ -149,14 +149,9 @@ RED.palette = (function() {
if (def.icon) {
var icon_url = "arrow-in.png";
try {
icon_url = (typeof def.icon === "function" ? def.icon.call({}) : def.icon);
} catch(err) {
console.log("Definition error: "+nt+".icon",err);
}
var icon_url = RED.utils.getNodeIcon(def);
var iconContainer = $('<div/>',{class:"palette_icon_container"+(def.align=="right"?" palette_icon_container_right":"")}).appendTo(d);
$('<div/>',{class:"palette_icon",style:"background-image: url(icons/"+icon_url+")"}).appendTo(iconContainer);
$('<div/>',{class:"palette_icon",style:"background-image: url("+icon_url+")"}).appendTo(iconContainer);
}
d.style.backgroundColor = def.color;
@@ -174,7 +169,7 @@ RED.palette = (function() {
}
if ($("#palette-base-category-"+rootCategory).length === 0) {
if(core.indexOf(rootCategory) !== -1){
if(coreCategories.indexOf(rootCategory) !== -1){
createCategoryContainer(rootCategory, RED._("node-red:palette.label."+rootCategory, {defaultValue:rootCategory}));
} else {
var ns = def.set.id;
@@ -210,7 +205,7 @@ RED.palette = (function() {
if (nt.indexOf("subflow:") === 0) {
helpText = marked(RED.nodes.subflow(nt.substring(8)).info||"");
} else {
helpText = $("script[data-help-name|='"+d.type+"']").html()||"";
helpText = $("script[data-help-name$='"+d.type+"']").html()||"";
}
var help = '<div class="node-help">'+helpText+"</div>";
RED.sidebar.info.set(help);
@@ -227,18 +222,20 @@ RED.palette = (function() {
appendTo: 'body',
revert: true,
revertDuration: 50,
containment:'#main-container',
start: function() {RED.view.focus();},
stop: function() { d3.select('.link_splice').classed('link_splice',false); if (spliceTimer) { clearTimeout(spliceTimer); spliceTimer = null;}},
drag: function(e,ui) {
// TODO: this is the margin-left of palette node. Hard coding
// it here makes me sad
//console.log(ui.helper.position());
ui.position.left += 17.5;
if (def.inputs > 0 && def.outputs > 0) {
mouseX = ui.position.left+(ui.helper.width()/2) - chartOffset.left + chart.scrollLeft();
mouseY = ui.position.top+(ui.helper.height()/2) - chartOffset.top + chart.scrollTop();
if (!spliceTimer) {
spliceTimer = setTimeout(function() {
var nodes = [];
@@ -361,14 +358,7 @@ RED.palette = (function() {
});
}
function filterChange() {
var val = $("#palette-search-input").val();
if (val === "") {
$("#palette-search-clear").hide();
} else {
$("#palette-search-clear").show();
}
function filterChange(val) {
var re = new RegExp(val.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'),'i');
$("#palette-container .palette_node").each(function(i,el) {
var currentLabel = $(el).find(".palette_label").text();
@@ -393,33 +383,69 @@ RED.palette = (function() {
}
function init() {
$(".palette-spinner").show();
RED.events.on('registry:node-type-added', function(nodeType) {
var def = RED.nodes.getType(nodeType);
addNodeType(nodeType,def);
if (def.onpaletteadd && typeof def.onpaletteadd === "function") {
def.onpaletteadd.call(def);
}
});
RED.events.on('registry:node-type-removed', function(nodeType) {
removeNodeType(nodeType);
});
RED.events.on('registry:node-set-enabled', function(nodeSet) {
for (var j=0;j<nodeSet.types.length;j++) {
showNodeType(nodeSet.types[j]);
var def = RED.nodes.getType(nodeSet.types[j]);
if (def.onpaletteadd && typeof def.onpaletteadd === "function") {
def.onpaletteadd.call(def);
}
}
});
RED.events.on('registry:node-set-disabled', function(nodeSet) {
for (var j=0;j<nodeSet.types.length;j++) {
hideNodeType(nodeSet.types[j]);
var def = RED.nodes.getType(nodeSet.types[j]);
if (def.onpaletteremove && typeof def.onpaletteremove === "function") {
def.onpaletteremove.call(def);
}
}
});
RED.events.on('registry:node-set-removed', function(nodeSet) {
if (nodeSet.added) {
for (var j=0;j<nodeSet.types.length;j++) {
removeNodeType(nodeSet.types[j]);
var def = RED.nodes.getType(nodeSet.types[j]);
if (def.onpaletteremove && typeof def.onpaletteremove === "function") {
def.onpaletteremove.call(def);
}
}
}
});
$("#palette > .palette-spinner").show();
$("#palette-search input").searchBox({
delay: 100,
change: function() {
filterChange($(this).val());
}
})
var categoryList = coreCategories;
if (RED.settings.paletteCategories) {
RED.settings.paletteCategories.forEach(function(category){
createCategoryContainer(category, RED._("palette.label."+category,{defaultValue:category}));
});
} else {
core.forEach(function(category){
createCategoryContainer(category, RED._("palette.label."+category,{defaultValue:category}));
});
categoryList = RED.settings.paletteCategories;
} else if (RED.settings.theme('palette.categories')) {
categoryList = RED.settings.theme('palette.categories');
}
$("#palette-search-clear").on("click",function(e) {
e.preventDefault();
$("#palette-search-input").val("");
filterChange();
$("#palette-search-input").focus();
});
$("#palette-search-input").val("");
$("#palette-search-input").on("keyup",function() {
filterChange();
});
$("#palette-search-input").on("focus",function() {
$("body").one("mousedown",function() {
$("#palette-search-input").blur();
});
if (!Array.isArray(categoryList)) {
categoryList = coreCategories
}
categoryList.forEach(function(category){
createCategoryContainer(category, RED._("palette.label."+category,{defaultValue:category}));
});
$("#palette-collapse-all").on("click", function(e) {

287
editor/js/ui/search.js Normal file
View File

@@ -0,0 +1,287 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
RED.search = (function() {
var disabled = false;
var dialog = null;
var searchInput;
var searchResults;
var selected = -1;
var visible = false;
var index = {};
var keys = [];
var results = [];
function indexNode(n) {
var l = RED.utils.getNodeLabel(n);
if (l) {
l = (""+l).toLowerCase();
index[l] = index[l] || {};
index[l][n.id] = {node:n,label:l}
}
l = l||n.label||n.name||n.id||"";
var properties = ['id','type','name','label','info'];
if (n._def && n._def.defaults) {
properties = properties.concat(Object.keys(n._def.defaults));
}
for (var i=0;i<properties.length;i++) {
if (n.hasOwnProperty(properties[i])) {
var v = n[properties[i]];
if (typeof v === 'string' || typeof v === 'number') {
v = (""+v).toLowerCase();
index[v] = index[v] || {};
index[v][n.id] = {node:n,label:l};
}
}
}
}
function indexWorkspace() {
index = {};
RED.nodes.eachWorkspace(indexNode);
RED.nodes.eachSubflow(indexNode);
RED.nodes.eachConfig(indexNode);
RED.nodes.eachNode(indexNode);
keys = Object.keys(index);
keys.sort();
keys.forEach(function(key) {
index[key] = Object.keys(index[key]).map(function(id) {
return index[key][id];
})
})
}
function search(val) {
searchResults.editableList('empty');
selected = -1;
results = [];
if (val.length > 0) {
val = val.toLowerCase();
var i;
var j;
var list = [];
var nodes = {};
for (i=0;i<keys.length;i++) {
var key = keys[i];
var kpos = keys[i].indexOf(val);
if (kpos > -1) {
for (j=0;j<index[key].length;j++) {
var node = index[key][j];
nodes[node.node.id] = nodes[node.node.id] = node;
nodes[node.node.id].index = Math.min(nodes[node.node.id].index||Infinity,kpos);
}
}
}
list = Object.keys(nodes);
list.sort(function(A,B) {
return nodes[A].index - nodes[B].index;
});
for (i=0;i<list.length;i++) {
results.push(nodes[list[i]]);
}
if (results.length > 0) {
for (i=0;i<Math.min(results.length,25);i++) {
searchResults.editableList('addItem',results[i])
}
} else {
searchResults.editableList('addItem',{});
}
}
}
function ensureSelectedIsVisible() {
var selectedEntry = searchResults.find("li.selected");
if (selectedEntry.length === 1) {
var scrollWindow = searchResults.parent();
var scrollHeight = scrollWindow.height();
var scrollOffset = scrollWindow.scrollTop();
var y = selectedEntry.position().top;
var h = selectedEntry.height();
if (y+h > scrollHeight) {
scrollWindow.animate({scrollTop: '-='+(scrollHeight-(y+h)-10)},50);
} else if (y<0) {
scrollWindow.animate({scrollTop: '+='+(y-10)},50);
}
}
}
function createDialog() {
dialog = $("<div>",{id:"red-ui-search",class:"red-ui-search"}).appendTo("#main-container");
var searchDiv = $("<div>",{class:"red-ui-search-container"}).appendTo(dialog);
searchInput = $('<input type="text" placeholder="search your flows">').appendTo(searchDiv).searchBox({
delay: 200,
change: function() {
search($(this).val());
}
});
searchInput.on('keydown',function(evt) {
var children;
if (results.length > 0) {
if (evt.keyCode === 40) {
// Down
children = searchResults.children();
if (selected < children.length-1) {
if (selected > -1) {
$(children[selected]).removeClass('selected');
}
selected++;
}
$(children[selected]).addClass('selected');
ensureSelectedIsVisible();
evt.preventDefault();
} else if (evt.keyCode === 38) {
// Up
children = searchResults.children();
if (selected > 0) {
if (selected < children.length) {
$(children[selected]).removeClass('selected');
}
selected--;
}
$(children[selected]).addClass('selected');
ensureSelectedIsVisible();
evt.preventDefault();
} else if (evt.keyCode === 13) {
// Enter
if (results.length > 0) {
reveal(results[Math.max(0,selected)].node);
}
}
}
});
var searchResultsDiv = $("<div>",{class:"red-ui-search-results-container"}).appendTo(dialog);
searchResults = $('<ol>',{id:"search-result-list", style:"position: absolute;top: 5px;bottom: 5px;left: 5px;right: 5px;"}).appendTo(searchResultsDiv).editableList({
addButton: false,
addItem: function(container,i,object) {
var node = object.node;
if (node === undefined) {
$('<div>',{class:"red-ui-search-empty"}).html(RED._('search.empty')).appendTo(container);
} else {
var def = node._def;
var div = $('<a>',{href:'#',class:"red-ui-search-result"}).appendTo(container);
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(div);
var colour = def.color;
var icon_url = RED.utils.getNodeIcon(def,node);
if (node.type === 'tab') {
colour = "#C0DEED";
}
nodeDiv.css('backgroundColor',colour);
var iconContainer = $('<div/>',{class:"palette_icon_container"}).appendTo(nodeDiv);
$('<div/>',{class:"palette_icon",style:"background-image: url("+icon_url+")"}).appendTo(iconContainer);
var contentDiv = $('<div>',{class:"red-ui-search-result-description"}).appendTo(div);
if (node.z) {
var workspace = RED.nodes.workspace(node.z);
if (!workspace) {
workspace = RED.nodes.subflow(node.z);
workspace = "subflow:"+workspace.name;
} else {
workspace = "flow:"+workspace.label;
}
$('<div>',{class:"red-ui-search-result-node-flow"}).html(workspace).appendTo(contentDiv);
}
$('<div>',{class:"red-ui-search-result-node-label"}).html(object.label || node.id).appendTo(contentDiv);
$('<div>',{class:"red-ui-search-result-node-type"}).html(node.type).appendTo(contentDiv);
$('<div>',{class:"red-ui-search-result-node-id"}).html(node.id).appendTo(contentDiv);
div.click(function(evt) {
evt.preventDefault();
reveal(node);
});
}
},
scrollOnAdd: false
});
}
function reveal(node) {
hide();
RED.view.reveal(node.id);
}
function show() {
if (disabled) {
return;
}
if (!visible) {
RED.keyboard.add("*","escape",function(){hide()});
$("#header-shade").show();
$("#editor-shade").show();
$("#palette-shade").show();
$("#sidebar-shade").show();
$("#sidebar-separator").hide();
indexWorkspace();
if (dialog === null) {
createDialog();
}
dialog.slideDown(300);
RED.events.emit("search:open");
visible = true;
}
searchInput.focus();
}
function hide() {
if (visible) {
RED.keyboard.remove("escape");
visible = false;
$("#header-shade").hide();
$("#editor-shade").hide();
$("#palette-shade").hide();
$("#sidebar-shade").hide();
$("#sidebar-separator").show();
if (dialog !== null) {
dialog.slideUp(200,function() {
searchInput.searchBox('value','');
});
}
RED.events.emit("search:close");
}
}
function init() {
RED.actions.add("core:search",show);
RED.events.on("editor:open",function() { disabled = true; });
RED.events.on("editor:close",function() { disabled = false; });
RED.events.on("palette-editor:open",function() { disabled = true; });
RED.events.on("palette-editor:close",function() { disabled = false; });
RED.events.on("type-search:open",function() { disabled = true; });
RED.events.on("type-search:close",function() { disabled = false; });
$("#header-shade").on('mousedown',hide);
$("#editor-shade").on('mousedown',hide);
$("#palette-shade").on('mousedown',hide);
$("#sidebar-shade").on('mousedown',hide);
}
return {
init: init,
show: show,
hide: hide
};
})();

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2013, 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -202,12 +202,18 @@ RED.sidebar = (function() {
}
function init () {
RED.keyboard.add("*",/* SPACE */ 32,{ctrl:true},function(){RED.menu.setSelected("menu-item-sidebar",!RED.menu.isSelected("menu-item-sidebar"));d3.event.preventDefault();});
RED.actions.add("core:toggle-sidebar",function(state){
if (state === undefined) {
RED.menu.toggleSelected("menu-item-sidebar");
} else {
toggleSidebar(state);
}
});
showSidebar();
RED.sidebar.info.init();
RED.sidebar.config.init();
// hide info bar at start if screen rather narrow...
if ($(window).width() < 600) { toggleSidebar(); }
if ($(window).width() < 600) { RED.menu.setSelected("menu-item-sidebar",false); }
}
return {

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2013 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,5 +22,6 @@ RED.state = {
EDITING: 5,
EXPORT: 6,
IMPORT: 7,
IMPORT_DRAGGING: 8
IMPORT_DRAGGING: 8,
QUICK_JOINING: 9
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -306,50 +306,13 @@ RED.subflow = (function() {
$("#workspace-subflow-delete").click(function(event) {
event.preventDefault();
var removedNodes = [];
var removedLinks = [];
var startDirty = RED.nodes.dirty();
var historyEvent = removeSubflow(RED.workspaces.active());
historyEvent.t = 'delete';
historyEvent.dirty = startDirty;
var activeSubflow = getSubflow();
RED.history.push(historyEvent);
RED.nodes.eachNode(function(n) {
if (n.type == "subflow:"+activeSubflow.id) {
removedNodes.push(n);
}
if (n.z == activeSubflow.id) {
removedNodes.push(n);
}
});
RED.nodes.eachConfig(function(n) {
if (n.z == activeSubflow.id) {
removedNodes.push(n);
}
});
var removedConfigNodes = [];
for (var i=0;i<removedNodes.length;i++) {
var removedEntities = RED.nodes.remove(removedNodes[i].id);
removedLinks = removedLinks.concat(removedEntities.links);
removedConfigNodes = removedConfigNodes.concat(removedEntities.nodes);
}
// TODO: this whole delete logic should be in RED.nodes.removeSubflow..
removedNodes = removedNodes.concat(removedConfigNodes);
RED.nodes.removeSubflow(activeSubflow);
RED.history.push({
t:'delete',
nodes:removedNodes,
links:removedLinks,
subflow: {
subflow: activeSubflow
},
dirty:startDirty
});
RED.workspaces.remove(activeSubflow);
RED.nodes.dirty(true);
RED.view.redraw();
});
refreshToolbar(activeSubflow);
@@ -362,7 +325,48 @@ RED.subflow = (function() {
$("#chart").css({"margin-top": "0"});
}
function removeSubflow(id) {
var removedNodes = [];
var removedLinks = [];
var activeSubflow = RED.nodes.subflow(id);
RED.nodes.eachNode(function(n) {
if (n.type == "subflow:"+activeSubflow.id) {
removedNodes.push(n);
}
if (n.z == activeSubflow.id) {
removedNodes.push(n);
}
});
RED.nodes.eachConfig(function(n) {
if (n.z == activeSubflow.id) {
removedNodes.push(n);
}
});
var removedConfigNodes = [];
for (var i=0;i<removedNodes.length;i++) {
var removedEntities = RED.nodes.remove(removedNodes[i].id);
removedLinks = removedLinks.concat(removedEntities.links);
removedConfigNodes = removedConfigNodes.concat(removedEntities.nodes);
}
// TODO: this whole delete logic should be in RED.nodes.removeSubflow..
removedNodes = removedNodes.concat(removedConfigNodes);
RED.nodes.removeSubflow(activeSubflow);
RED.workspaces.remove(activeSubflow);
RED.nodes.dirty(true);
RED.view.redraw();
return {
nodes:removedNodes,
links:removedLinks,
subflow: {
subflow: activeSubflow
}
}
}
function init() {
RED.events.on("workspace:change",function(event) {
var activeSubflow = RED.nodes.subflow(event.workspace);
@@ -380,6 +384,8 @@ RED.subflow = (function() {
}
});
RED.actions.add("core:create-subflow",createSubflow);
RED.actions.add("core:convert-to-subflow",convertToSubflow);
}
function createSubflow() {
@@ -617,6 +623,7 @@ RED.subflow = (function() {
init: init,
createSubflow: createSubflow,
convertToSubflow: convertToSubflow,
removeSubflow: removeSubflow,
refresh: refresh,
removeInput: removeSubflowInput,
removeOutput: removeSubflowOutput

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2013, 2016 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -113,7 +113,7 @@ RED.sidebar.config = (function() {
if (showUnusedOnly) {
var hiddenCount = nodes.length;
nodes = nodes.filter(function(n) {
return n.users.length === 0;
return n._def.hasUsers!==false && n.users.length === 0;
})
hiddenCount = hiddenCount - nodes.length;
if (hiddenCount > 0) {
@@ -131,24 +131,19 @@ RED.sidebar.config = (function() {
} else {
var currentType = "";
nodes.forEach(function(node) {
var label = "";
if (typeof node._def.label == "function") {
label = node._def.label.call(node);
} else {
label = node._def.label;
}
label = label || node.id;
var label = RED.utils.getNodeLabel(node,node.id);
if (node.type != currentType) {
$('<li class="config_node_type">'+node.type+'</li>').appendTo(list);
currentType = node.type;
}
var entry = $('<li class="palette_node config_node"></li>').appendTo(list);
var entry = $('<li class="palette_node config_node palette_node_id_'+node.id.replace(/\./g,"-")+'"></li>').appendTo(list);
$('<div class="palette_label"></div>').text(label).appendTo(entry);
var iconContainer = $('<div/>',{class:"palette_icon_container palette_icon_container_right"}).text(node.users.length).appendTo(entry);
if (node.users.length === 0) {
entry.addClass("config_node_unused");
if (node._def.hasUsers !== false) {
var iconContainer = $('<div/>',{class:"palette_icon_container palette_icon_container_right"}).text(node.users.length).appendTo(entry);
if (node.users.length === 0) {
entry.addClass("config_node_unused");
}
}
entry.on('click',function(e) {
RED.sidebar.info.refresh(node);
@@ -230,10 +225,7 @@ RED.sidebar.config = (function() {
visible: false,
onchange: function() { refreshConfigNodeList(); }
});
RED.menu.setAction('menu-item-config-nodes',function() {
RED.sidebar.show('config');
})
RED.actions.add("core:show-config-tab",function() {RED.sidebar.show('config')});
$("#workspace-config-node-collapse-all").on("click", function(e) {
e.preventDefault();
@@ -274,15 +266,45 @@ RED.sidebar.config = (function() {
}
function show(unused) {
if (unused !== undefined) {
if (unused) {
function show(id) {
if (typeof id === 'boolean') {
if (id) {
$('#workspace-config-node-filter-unused').click();
} else {
$('#workspace-config-node-filter-all').click();
}
}
refreshConfigNodeList();
if (typeof id === "string") {
$('#workspace-config-node-filter-all').click();
id = id.replace(/\./g,"-");
setTimeout(function() {
var node = $(".palette_node_id_"+id);
var y = node.position().top;
var h = node.height();
var scrollWindow = $(".sidebar-node-config");
var scrollHeight = scrollWindow.height();
if (y+h > scrollHeight) {
scrollWindow.animate({scrollTop: '-='+(scrollHeight-(y+h)-30)},150);
} else if (y<0) {
scrollWindow.animate({scrollTop: '+='+(y-10)},150);
}
var flash = 21;
var flashFunc = function() {
if ((flash%2)===0) {
node.removeClass('node_highlighted');
} else {
node.addClass('node_highlighted');
}
flash--;
if (flash >= 0) {
setTimeout(flashFunc,100);
}
}
flashFunc();
},100);
}
RED.sidebar.show("config");
}
return {

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2013, 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@ RED.sidebar.info = (function() {
content: content,
enableOnEdit: true
});
RED.actions.add("core:show-info-tab",show);
}
function show() {
@@ -67,13 +67,16 @@ RED.sidebar.info = (function() {
}
function refresh(node) {
var table = '<table class="node-info"><tbody>';
table += '<tr class="blank"><td colspan="2">'+RED._("sidebar.info.node")+'</td></tr>';
tips.stop();
$(content).empty();
var table = $('<table class="node-info"></table>');
var tableBody = $('<tbody>').appendTo(table);
$('<tr class="blank"><td colspan="2">'+RED._("sidebar.info.node")+'</td></tr>').appendTo(tableBody);
if (node.type != "subflow" && node.name) {
table += "<tr><td>"+RED._("common.label.name")+"</td><td>&nbsp;"+node.name+"</td></tr>";
$('<tr><td>'+RED._("common.label.name")+'</td><td>&nbsp;<span class="bidiAware" dir="'+RED.text.bidi.resolveBaseTextDir(node.name)+'">'+node.name+'</span></td></tr>').appendTo(tableBody);
}
table += "<tr><td>"+RED._("sidebar.info.type")+"</td><td>&nbsp;"+node.type+"</td></tr>";
table += "<tr><td>"+RED._("sidebar.info.id")+"</td><td>&nbsp;"+node.id+"</td></tr>";
$("<tr><td>"+RED._("sidebar.info.type")+"</td><td>&nbsp;"+node.type+"</td></tr>").appendTo(tableBody);
$("<tr><td>"+RED._("sidebar.info.id")+"</td><td>&nbsp;"+node.id+"</td></tr>").appendTo(tableBody);
var m = /^subflow(:(.+))?$/.exec(node.type);
var subflowNode;
@@ -84,7 +87,7 @@ RED.sidebar.info = (function() {
subflowNode = node;
}
table += '<tr class="blank"><td colspan="2">'+RED._("sidebar.info.subflow")+'</td></tr>';
$('<tr class="blank"><td colspan="2">'+RED._("sidebar.info.subflow")+'</td></tr>').appendTo(tableBody);
var userCount = 0;
var subflowType = "subflow:"+subflowNode.id;
@@ -93,63 +96,38 @@ RED.sidebar.info = (function() {
userCount++;
}
});
table += "<tr><td>"+RED._("common.label.name")+"</td><td>"+subflowNode.name+"</td></tr>";
table += "<tr><td>"+RED._("sidebar.info.instances")+"</td><td>"+userCount+"</td></tr>";
$('<tr><td>'+RED._("common.label.name")+'</td><td><span class="bidiAware" dir=\"'+RED.text.bidi.resolveBaseTextDir(subflowNode.name)+'">'+subflowNode.name+'</span></td></tr>').appendTo(tableBody);
$("<tr><td>"+RED._("sidebar.info.instances")+"</td><td>"+userCount+"</td></tr>").appendTo(tableBody);
}
if (!m && node.type != "subflow" && node.type != "comment") {
table += '<tr class="blank"><td colspan="2"><a href="#" class="node-info-property-header"><i style="width: 10px; text-align: center;" class="fa fa-caret-'+(propertiesExpanded?"down":"right")+'"></i> '+RED._("sidebar.info.properties")+'</a></td></tr>';
$('<tr class="blank"><td colspan="2"><a href="#" class="node-info-property-header"><i style="width: 10px; text-align: center;" class="fa fa-caret-'+(propertiesExpanded?"down":"right")+'"></i> '+RED._("sidebar.info.properties")+'</a></td></tr>').appendTo(tableBody);
if (node._def) {
for (var n in node._def.defaults) {
if (n != "name" && node._def.defaults.hasOwnProperty(n)) {
var val = node[n]||"";
var val = node[n];
var type = typeof val;
if (type === "string") {
if (val.length === 0) {
val += '<span style="font-style: italic; color: #ccc;">'+RED._("sidebar.info.blank")+'</span>';
} else {
if (val.length > 30) {
val = val.substring(0,30)+" ...";
}
val = val.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");
}
} else if (type === "number") {
val = val.toString();
} else if ($.isArray(val)) {
val = "[<br/>";
for (var i=0;i<Math.min(node[n].length,10);i++) {
var vv = JSON.stringify(node[n][i],jsonFilter," ").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");
val += "&nbsp;"+i+": "+vv+"<br/>";
}
if (node[n].length > 10) {
val += "&nbsp;... "+RED._("sidebar.info.arrayItems",{count:node[n].length})+"<br/>";
}
val += "]";
} else {
val = JSON.stringify(val,jsonFilter," ");
val = val.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");
}
table += '<tr class="node-info-property-row'+(propertiesExpanded?"":" hide")+'"><td>'+n+"</td><td>"+val+"</td></tr>";
var propRow = $('<tr class="node-info-property-row'+(propertiesExpanded?"":" hide")+'"><td>'+n+"</td><td></td></tr>").appendTo(tableBody);
RED.utils.createObjectElement(val).appendTo(propRow.children()[1]);
}
}
}
}
table += "</tbody></table><hr/>";
$(table).appendTo(content);
$("<hr/>").appendTo(content);
if (!subflowNode && node.type != "comment") {
var helpText = $("script[data-help-name|='"+node.type+"']").html()||"";
table += '<div class="node-help">'+helpText+"</div>";
var helpText = $("script[data-help-name$='"+node.type+"']").html()||"";
$('<div class="node-help"><span class="bidiAware" dir=\"'+RED.text.bidi.resolveBaseTextDir(helpText)+'">'+helpText+'</span></div>').appendTo(content);
}
if (subflowNode) {
table += '<div class="node-help">'+marked(subflowNode.info||"")+'</div>';
$('<div class="node-help"><span class="bidiAware" dir=\"'+RED.text.bidi.resolveBaseTextDir(subflowNode.info||"")+'">'+marked(subflowNode.info||"")+'</span></div>').appendTo(content);
} else if (node._def && node._def.info) {
var info = node._def.info;
table += '<div class="node-help">'+marked(typeof info === "function" ? info.call(node) : info)+'</div>';
//table += '<div class="node-help">'+(typeof info === "function" ? info.call(node) : info)+'</div>';
var textInfo = (typeof info === "function" ? info.call(node) : info);
$('<div class="node-help"><span class="bidiAware" dir=\"'+RED.text.bidi.resolveBaseTextDir(textInfo)+'">'+marked(textInfo)+'</span></div>').appendTo(content);
//$('<div class="node-help">'+(typeof info === "function" ? info.call(node) : info)+'</div>';
}
$(content).html(table);
$(".node-info-property-header").click(function(e) {
var icon = $(this).find("i");
if (icon.hasClass("fa-caret-right")) {
@@ -168,14 +146,98 @@ RED.sidebar.info = (function() {
});
}
var tips = (function() {
var started = false;
var enabled = true;
var startDelay = 1000;
var cycleDelay = 15000;
var startTimeout;
var refreshTimeout;
var tipCount = -1;
RED.actions.add("core:toggle-show-tips",function(state) {
if (state === undefined) {
RED.menu.toggleSelected("menu-item-show-tips");
} else {
enabled = state;
if (enabled) {
if (started) {
startTips();
}
} else {
stopTips();
}
}
});
function setTip() {
var r = Math.floor(Math.random() * tipCount);
var tip = RED._("infotips:info.tip"+r);
var m;
while ((m=/({{(.*?)}})/.exec(tip))) {
var shortcut = RED.keyboard.getShortcut(m[2]);
if (shortcut) {
tip = tip.replace(m[1],RED.keyboard.formatKey(shortcut.key));
} else {
return;
}
}
while ((m=/(\[(.*?)\])/.exec(tip))) {
tip = tip.replace(m[1],RED.keyboard.formatKey(m[2]));
}
$('<div class="node-info-tip hide">'+tip+'</div>').appendTo(content).fadeIn(200);
if (startTimeout) {
startTimeout = null;
refreshTimeout = setInterval(cycleTips,cycleDelay);
}
}
function cycleTips() {
$(".node-info-tip").fadeOut(300,function() {
$(this).remove();
setTip();
})
}
function startTips() {
started = true;
if (enabled) {
if (!startTimeout && !refreshTimeout) {
$(content).html("");
if (tipCount === -1) {
do {
tipCount++;
} while(RED._("infotips:info.tip"+tipCount)!=="infotips:info.tip"+tipCount);
}
startTimeout = setTimeout(setTip,startDelay);
}
}
}
function stopTips() {
started = false;
clearInterval(refreshTimeout);
clearTimeout(startTimeout);
refreshTimeout = null;
startTimeout = null;
$(".node-info-tip").remove();
}
return {
start: startTips,
stop: stopTips
}
})();
function clear() {
$(content).html("");
tips.start();
}
function set(html) {
tips.stop();
$(content).html(html);
}
RED.events.on("view:selection-changed",function(selection) {
if (selection.nodes) {
if (selection.nodes.length == 1) {
@@ -199,7 +261,7 @@ RED.sidebar.info = (function() {
return {
init: init,
show: show,
refresh:refresh,
refresh: refresh,
clear: clear,
set: set
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2014 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2016 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -110,6 +110,7 @@ RED.tray = (function() {
$("#header-shade").show();
$("#editor-shade").show();
$("#palette-shade").show();
$(".sidebar-shade").show();
tray.preferredWidth = Math.max(el.width(),500);
@@ -154,6 +155,8 @@ RED.tray = (function() {
// Delay resetting the flag, so we don't close prematurely
openingTray = false;
},200);
body.find(":focusable:first").focus();
},150);
el.css({right:0});
},0);
@@ -186,7 +189,7 @@ RED.tray = (function() {
if (stack.length > 0) {
var tray = stack[stack.length-1];
var trayHeight = tray.tray.height()-tray.header.outerHeight()-tray.footer.outerHeight();
tray.body.height(trayHeight-40);
tray.body.height(trayHeight);
if (tray.width > $("#editor-stack").position().left-8) {
tray.width = $("#editor-stack").position().left-8;
tray.tray.width(tray.width);
@@ -197,7 +200,7 @@ RED.tray = (function() {
// tray.body.parent().width(tray.width);
}
if (tray.options.resize) {
tray.options.resize({width:tray.width});
tray.options.resize({width:tray.width, height:trayHeight});
}
}
}
@@ -259,6 +262,7 @@ RED.tray = (function() {
if (stack.length === 0) {
$("#header-shade").hide();
$("#editor-shade").hide();
$("#palette-shade").hide();
$(".sidebar-shade").hide();
RED.events.emit("editor:close");
RED.view.focus();

295
editor/js/ui/typeSearch.js Normal file
View File

@@ -0,0 +1,295 @@
RED.typeSearch = (function() {
var shade;
var disabled = false;
var dialog = null;
var searchInput;
var searchResults;
var searchResultsDiv;
var selected = -1;
var visible = false;
var activeFilter = "";
var addCallback;
var typesUsed = {};
function search(val) {
activeFilter = val.toLowerCase();
var visible = searchResults.editableList('filter');
setTimeout(function() {
selected = 0;
searchResults.children().removeClass('selected');
searchResults.children(":visible:first").addClass('selected');
},100);
}
function ensureSelectedIsVisible() {
var selectedEntry = searchResults.find("li.selected");
if (selectedEntry.length === 1) {
var scrollWindow = searchResults.parent();
var scrollHeight = scrollWindow.height();
var scrollOffset = scrollWindow.scrollTop();
var y = selectedEntry.position().top;
var h = selectedEntry.height();
if (y+h > scrollHeight) {
scrollWindow.animate({scrollTop: '-='+(scrollHeight-(y+h)-10)},50);
} else if (y<0) {
scrollWindow.animate({scrollTop: '+='+(y-10)},50);
}
}
}
function createDialog() {
//shade = $('<div>',{class:"red-ui-type-search-shade"}).appendTo("#main-container");
dialog = $("<div>",{id:"red-ui-type-search",class:"red-ui-search red-ui-type-search"}).appendTo("#main-container");
var searchDiv = $("<div>",{class:"red-ui-search-container"}).appendTo(dialog);
searchInput = $('<input type="text">').attr("placeholder",RED._("search.addNode")).appendTo(searchDiv).searchBox({
delay: 50,
change: function() {
search($(this).val());
}
});
searchInput.on('keydown',function(evt) {
var children = searchResults.children(":visible");
if (children.length > 0) {
if (evt.keyCode === 40) {
// Down
if (selected < children.length-1) {
if (selected > -1) {
$(children[selected]).removeClass('selected');
}
selected++;
}
$(children[selected]).addClass('selected');
ensureSelectedIsVisible();
evt.preventDefault();
} else if (evt.keyCode === 38) {
// Up
if (selected > 0) {
if (selected < children.length) {
$(children[selected]).removeClass('selected');
}
selected--;
}
$(children[selected]).addClass('selected');
ensureSelectedIsVisible();
evt.preventDefault();
} else if (evt.keyCode === 13) {
// Enter
var index = Math.max(0,selected);
if (index < children.length) {
// TODO: dips into editableList impl details
confirm($(children[index]).find(".red-ui-editableList-item-content").data('data'));
}
}
}
});
searchResultsDiv = $("<div>",{class:"red-ui-search-results-container"}).appendTo(dialog);
searchResults = $('<ol>',{id:"search-result-list", style:"position: absolute;top: 0;bottom: 0;left: 0;right: 0;"}).appendTo(searchResultsDiv).editableList({
addButton: false,
filter: function(data) {
if (activeFilter === "" ) {
return true;
}
if (data.recent || data.common) {
return false;
}
return (activeFilter==="")||(data.index.indexOf(activeFilter) > -1);
},
addItem: function(container,i,object) {
var def = object.def;
object.index = object.type.toLowerCase();
if (object.separator) {
container.addClass("red-ui-search-result-separator")
}
var div = $('<a>',{href:'#',class:"red-ui-search-result"}).appendTo(container);
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(div);
var colour = def.color;
var icon_url = RED.utils.getNodeIcon(def);
nodeDiv.css('backgroundColor',colour);
var iconContainer = $('<div/>',{class:"palette_icon_container"}).appendTo(nodeDiv);
$('<div/>',{class:"palette_icon",style:"background-image: url("+icon_url+")"}).appendTo(iconContainer);
if (def.inputs > 0) {
$('<div/>',{class:"red-ui-search-result-node-port"}).appendTo(nodeDiv);
}
if (def.outputs > 0) {
$('<div/>',{class:"red-ui-search-result-node-port red-ui-search-result-node-output"}).appendTo(nodeDiv);
}
var contentDiv = $('<div>',{class:"red-ui-search-result-description"}).appendTo(div);
var label = object.label;
object.index += "|"+label.toLowerCase();
$('<div>',{class:"red-ui-search-result-node-label"}).html(label).appendTo(contentDiv);
div.click(function(evt) {
evt.preventDefault();
confirm(object);
});
},
scrollOnAdd: false
});
}
function confirm(def) {
hide();
typesUsed[def.type] = Date.now();
addCallback(def.type);
}
function handleMouseActivity(evt) {
if (visible) {
var t = $(evt.target);
while (t.prop('nodeName').toLowerCase() !== 'body') {
if (t.attr('id') === 'red-ui-type-search') {
return;
}
t = t.parent();
}
hide(true);
}
}
function show(opts) {
if (!visible) {
RED.keyboard.add("*","escape",function(){hide()});
if (dialog === null) {
createDialog();
}
visible = true;
setTimeout(function() {
$(document).on('mousedown.type-search',handleMouseActivity);
$(document).on('mouseup.type-search',handleMouseActivity);
$(document).on('click.type-search',handleMouseActivity);
},200);
} else {
dialog.hide();
searchResultsDiv.hide();
}
refreshTypeList();
addCallback = opts.add;
RED.events.emit("type-search:open");
//shade.show();
dialog.css({left:opts.x+"px",top:opts.y+"px"}).show();
searchResultsDiv.slideDown(300);
setTimeout(function() {
searchResultsDiv.find(".red-ui-editableList-container").scrollTop(0);
searchInput.focus();
},100);
}
function hide(fast) {
if (visible) {
RED.keyboard.remove("escape");
visible = false;
if (dialog !== null) {
searchResultsDiv.slideUp(fast?50:200,function() {
dialog.hide();
searchInput.searchBox('value','');
});
//shade.hide();
}
RED.events.emit("type-search:close");
RED.view.focus();
$(document).off('mousedown.type-search');
$(document).off('mouseup.type-search');
$(document).off('click.type-search');
}
}
function getTypeLabel(type, def) {
var label = type;
if (typeof def.paletteLabel !== "undefined") {
try {
label = (typeof def.paletteLabel === "function" ? def.paletteLabel.call(def) : def.paletteLabel)||"";
label += " ("+type+")";
} catch(err) {
console.log("Definition error: "+type+".paletteLabel",err);
}
}
return label;
}
function refreshTypeList() {
var i;
searchResults.editableList('empty');
searchInput.searchBox('value','');
selected = -1;
var common = [
'inject','debug','function','change','switch'
];
var recentlyUsed = Object.keys(typesUsed);
recentlyUsed.sort(function(a,b) {
return typesUsed[b]-typesUsed[a];
});
recentlyUsed = recentlyUsed.filter(function(t) {
return common.indexOf(t) === -1;
});
var items = [];
RED.nodes.registry.getNodeTypes().forEach(function(t) {
var def = RED.nodes.getType(t);
if (def.category !== 'config' && t !== 'unknown') {
items.push({type:t,def: def, label:getTypeLabel(t,def)});
}
});
items.sort(function(a,b) {
var al = a.label.toLowerCase();
var bl = b.label.toLowerCase();
if (al < bl) {
return -1;
} else if (al === bl) {
return 0;
} else {
return 1;
}
})
var commonCount = 0;
var item;
for(i=0;i<common.length;i++) {
item = {
type: common[i],
common: true,
def: RED.nodes.getType(common[i])
};
item.label = getTypeLabel(item.type,item.def);
if (i === common.length-1) {
item.separator = true;
}
searchResults.editableList('addItem', item);
}
for(i=0;i<Math.min(5,recentlyUsed.length);i++) {
item = {
type:recentlyUsed[i],
def: RED.nodes.getType(recentlyUsed[i]),
recent: true
};
item.label = getTypeLabel(item.type,item.def);
if (i === recentlyUsed.length-1) {
item.separator = true;
}
searchResults.editableList('addItem', item);
}
for (i=0;i<items.length;i++) {
searchResults.editableList('addItem', items[i]);
}
setTimeout(function() {
selected = 0;
searchResults.children(":first").addClass('selected');
},100);
}
return {
show: show,
hide: hide
};
})();

410
editor/js/ui/utils.js Normal file
View File

@@ -0,0 +1,410 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
RED.utils = (function() {
function formatString(str) {
return str.replace(/\r?\n/g,"&crarr;").replace(/\t/g,"&rarr;");
}
function sanitize(m) {
return m.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");
}
function buildMessageSummaryValue(value) {
var result;
if (Array.isArray(value)) {
result = $('<span class="debug-message-object-value debug-message-type-meta"></span>').html('array['+value.length+']');
} else if (value === null) {
result = $('<span class="debug-message-object-value debug-message-type-null">null</span>');
} else if (typeof value === 'object') {
if (value.hasOwnProperty('type') && value.type === 'Buffer' && value.hasOwnProperty('data')) {
result = $('<span class="debug-message-object-value debug-message-type-meta"></span>').html('buffer['+value.data.length+']');
} else if (value.hasOwnProperty('type') && value.type === 'array' && value.hasOwnProperty('data')) {
result = $('<span class="debug-message-object-value debug-message-type-meta"></span>').html('array['+value.length+']');
} else {
result = $('<span class="debug-message-object-value debug-message-type-meta">object</span>');
}
} else if (typeof value === 'string') {
var subvalue;
if (value.length > 30) {
subvalue = sanitize(value.substring(0,30))+"&hellip;";
} else {
subvalue = sanitize(value);
}
result = $('<span class="debug-message-object-value debug-message-type-string"></span>').html('"'+formatString(subvalue)+'"');
} else {
result = $('<span class="debug-message-object-value debug-message-type-other"></span>').text(""+value);
}
return result;
}
function makeExpandable(el,onexpand) {
el.addClass("debug-message-expandable");
el.click(function(e) {
var parent = $(this).parent();
if (parent.hasClass('collapsed')) {
if (onexpand && !parent.hasClass('built')) {
onexpand();
parent.addClass('built');
}
parent.removeClass('collapsed');
} else {
parent.addClass('collapsed');
}
e.preventDefault();
});
}
function buildMessageElement(obj,key,typeHint,hideKey) {
var i;
var e;
var entryObj;
var header;
var headerHead;
var value;
var element = $('<span class="debug-message-element"></span>');
if (!key) {
element.addClass("debug-message-top-level");
}
header = $('<span></span>').appendTo(element);
if (key && !hideKey) {
$('<span class="debug-message-object-key"></span>').text(key).appendTo(header);
$('<span>: </span>').appendTo(header);
}
entryObj = $('<span class="debug-message-object-value"></span>').appendTo(header);
var isArray = Array.isArray(obj);
var isArrayObject = false;
if (obj && typeof obj === 'object' && obj.hasOwnProperty('type') && obj.hasOwnProperty('data') && ((obj.__encoded__ && obj.type === 'array') || obj.type === 'Buffer')) {
isArray = true;
isArrayObject = true;
}
if (obj === null || obj === undefined) {
$('<span class="debug-message-type-null">'+obj+'</span>').appendTo(entryObj);
} else if (typeof obj === 'string') {
if (/[\t\n\r]/.test(obj)) {
element.addClass('collapsed');
$('<i class="fa fa-caret-right debug-message-object-handle"></i> ').prependTo(header);
makeExpandable(header, function() {
$('<span class="debug-message-type-meta debug-message-object-type-header"></span>').html(typeHint||'string').appendTo(header);
var row = $('<div class="debug-message-object-entry collapsed"></div>').appendTo(element);
$('<pre class="debug-message-type-string"></pre>').text(obj).appendTo(row);
});
}
e = $('<span class="debug-message-type-string debug-message-object-header"></span>').html('"'+formatString(sanitize(obj))+'"').appendTo(entryObj);
if (/^#[0-9a-f]{6}$/i.test(obj)) {
$('<span class="debug-message-type-string-swatch"></span>').css('backgroundColor',obj).appendTo(e);
}
} else if (typeof obj === 'number') {
e = $('<span class="debug-message-type-number"></span>').text(""+obj).appendTo(entryObj);
if (Number.isInteger(obj) && (obj >= 0)) { // if it's a +ve integer
e.addClass("debug-message-type-number-toggle");
e.click(function(evt) {
var format = $(this).data('format') || "date";
if (format === 'dec') {
$(this).text(""+obj).data('format','date');
} else if ((format === 'date') && (obj.toString().length===13) && (obj<=2147483647000)) {
$(this).text((new Date(obj)).toISOString()).data('format','hex');
} else if ((format === 'date') && (obj.toString().length===10) && (obj<=2147483647)) {
$(this).text((new Date(obj*1000)).toISOString()).data('format','hex');
} else {
$(this).text("0x"+(obj).toString(16)).data('format','dec');
}
evt.preventDefault();
});
}
} else if (isArray) {
element.addClass('collapsed');
var originalLength = obj.length;
if (typeHint) {
var m = /\[(\d+)\]/.exec(typeHint);
if (m) {
originalLength = parseInt(m[1]);
}
}
var data = obj;
var type = 'array';
if (isArrayObject) {
data = obj.data;
if (originalLength === undefined) {
originalLength = data.length;
}
if (data.__encoded__) {
data = data.data;
}
type = obj.type.toLowerCase();
} else if (/buffer/.test(typeHint)) {
type = 'buffer';
}
var fullLength = data.length;
if (originalLength > 0) {
$('<i class="fa fa-caret-right debug-message-object-handle"></i> ').prependTo(header);
var arrayRows = $('<div class="debug-message-array-rows"></div>').appendTo(element);
element.addClass('debug-message-buffer-raw');
makeExpandable(header,function() {
if (!key) {
headerHead = $('<span class="debug-message-type-meta debug-message-object-type-header"></span>').html(typeHint||(type+'['+originalLength+']')).appendTo(header);
}
if (type === 'buffer') {
var stringRow = $('<div class="debug-message-string-rows"></div>').appendTo(element);
var sr = $('<div class="debug-message-object-entry collapsed"></div>').appendTo(stringRow);
var stringEncoding = "";
try {
stringEncoding = String.fromCharCode.apply(null, new Uint16Array(data))
} catch(err) {
console.log(err);
}
$('<pre class="debug-message-type-string"></pre>').text(stringEncoding).appendTo(sr);
var bufferOpts = $('<span class="debug-message-buffer-opts"></span>').appendTo(headerHead);
$('<a href="#"></a>').addClass('selected').html('raw').appendTo(bufferOpts).click(function(e) {
if ($(this).text() === 'raw') {
$(this).text('string');
element.addClass('debug-message-buffer-string').removeClass('debug-message-buffer-raw');
} else {
$(this).text('raw');
element.removeClass('debug-message-buffer-string').addClass('debug-message-buffer-raw');
}
e.preventDefault();
e.stopPropagation();
})
}
var row;
if (fullLength <= 10) {
for (i=0;i<fullLength;i++) {
row = $('<div class="debug-message-object-entry collapsed"></div>').appendTo(arrayRows);
buildMessageElement(data[i],""+i,false).appendTo(row);
}
} else {
for (i=0;i<fullLength;i+=10) {
var minRange = i;
row = $('<div class="debug-message-object-entry collapsed"></div>').appendTo(arrayRows);
header = $('<span></span>').appendTo(row);
$('<i class="fa fa-caret-right debug-message-object-handle"></i> ').appendTo(header);
makeExpandable(header, (function() {
var min = minRange;
var max = Math.min(fullLength-1,(minRange+9));
var parent = row;
return function() {
for (var i=min;i<=max;i++) {
var row = $('<div class="debug-message-object-entry collapsed"></div>').appendTo(parent);
buildMessageElement(data[i],""+i,false).appendTo(row);
}
}
})());
$('<span class="debug-message-object-key"></span>').html("["+minRange+" &hellip; "+Math.min(fullLength-1,(minRange+9))+"]").appendTo(header);
}
if (fullLength < originalLength) {
$('<div class="debug-message-object-entry collapsed"><span class="debug-message-object-key">['+fullLength+' &hellip; '+originalLength+']</span></div>').appendTo(arrayRows);
}
}
});
}
if (key) {
headerHead = $('<span class="debug-message-type-meta f"></span>').html(typeHint||(type+'['+originalLength+']')).appendTo(entryObj);
} else {
headerHead = $('<span class="debug-message-object-header"></span>').appendTo(entryObj);
$('<span>[ </span>').appendTo(headerHead);
var arrayLength = Math.min(originalLength,10);
for (i=0;i<arrayLength;i++) {
buildMessageSummaryValue(data[i]).appendTo(headerHead);
if (i < arrayLength-1) {
$('<span>, </span>').appendTo(headerHead);
}
}
if (originalLength > arrayLength) {
$('<span> &hellip;</span>').appendTo(headerHead);
}
if (arrayLength === 0) {
$('<span class="debug-message-type-meta">empty</span>').appendTo(headerHead);
}
$('<span> ]</span>').appendTo(headerHead);
}
} else if (typeof obj === 'object') {
element.addClass('collapsed');
var keys = Object.keys(obj);
if (key || keys.length > 0) {
$('<i class="fa fa-caret-right debug-message-object-handle"></i> ').prependTo(header);
makeExpandable(header, function() {
if (!key) {
$('<span class="debug-message-type-meta debug-message-object-type-header"></span>').html('object').appendTo(header);
}
for (i=0;i<keys.length;i++) {
var row = $('<div class="debug-message-object-entry collapsed"></div>').appendTo(element);
buildMessageElement(obj[keys[i]],keys[i],false).appendTo(row);
}
if (keys.length === 0) {
$('<div class="debug-message-object-entry debug-message-type-meta collapsed"></div>').text("empty").appendTo(element);
}
});
}
if (key) {
$('<span class="debug-message-type-meta"></span>').html('object').appendTo(entryObj);
} else {
headerHead = $('<span class="debug-message-object-header"></span>').appendTo(entryObj);
$('<span>{ </span>').appendTo(headerHead);
var keysLength = Math.min(keys.length,5);
for (i=0;i<keysLength;i++) {
$('<span class="debug-message-object-key"></span>').text(keys[i]).appendTo(headerHead);
$('<span>: </span>').appendTo(headerHead);
buildMessageSummaryValue(obj[keys[i]]).appendTo(headerHead);
if (i < keysLength-1) {
$('<span>, </span>').appendTo(headerHead);
}
}
if (keys.length > keysLength) {
$('<span> &hellip;</span>').appendTo(headerHead);
}
if (keysLength === 0) {
$('<span class="debug-message-type-meta">empty</span>').appendTo(headerHead);
}
$('<span> }</span>').appendTo(headerHead);
}
} else {
$('<span class="debug-message-type-other"></span>').text(""+obj).appendTo(entryObj);
}
return element;
}
function validatePropertyExpression(str) {
// This must be kept in sync with normalisePropertyExpression
// in red/runtime/util.js
var length = str.length;
if (length === 0) {
return false;
}
var start = 0;
var inString = false;
var inBox = false;
var quoteChar;
var v;
for (var i=0;i<length;i++) {
var c = str[i];
if (!inString) {
if (c === "'" || c === '"') {
if (i != start) {
return false;
}
inString = true;
quoteChar = c;
start = i+1;
} else if (c === '.') {
if (i===0 || i===length-1) {
return false;
}
// Next char is first char of an identifier: a-z 0-9 $ _
if (!/[a-z0-9\$\_]/i.test(str[i+1])) {
return false;
}
start = i+1;
} else if (c === '[') {
if (i === 0) {
return false;
}
if (i===length-1) {
return false;
}
// Next char is either a quote or a number
if (!/["'\d]/.test(str[i+1])) {
return false;
}
start = i+1;
inBox = true;
} else if (c === ']') {
if (!inBox) {
return false;
}
if (start != i) {
v = str.substring(start,i);
if (!/^\d+$/.test(v)) {
return false;
}
}
start = i+1;
inBox = false;
} else if (c === ' ') {
return false;
}
} else {
if (c === quoteChar) {
if (i-start === 0) {
return false;
}
// Next char must be a ]
if (inBox && !/\]/.test(str[i+1])) {
return false;
} else if (!inBox && i+1!==length && !/[\[\.]/.test(str[i+1])) {
return false;
}
start = i+1;
inString = false;
}
}
}
if (inBox || inString) {
return false;
}
return true;
}
function getNodeIcon(def,node) {
if (def.category === 'config') {
return "icons/node-red/cog.png"
} else if (node && node.type === 'tab') {
return "icons/node-red/subflow.png"
} else if (node && node.type === 'unknown') {
return "icons/node-red/alert.png"
}
var icon_url;
if (typeof def.icon === "function") {
try {
icon_url = def.icon.call(node);
} catch(err) {
console.log("Definition error: "+def.type+".icon",err);
icon_url = "arrow-in.png";
}
} else {
icon_url = def.icon;
}
return "icons/"+def.set.module+"/"+icon_url;
}
function getNodeLabel(node,defaultLabel) {
defaultLabel = defaultLabel||"";
var l = node._def.label;
try {
l = (typeof l === "function" ? l.call(node) : l)||defaultLabel;
} catch(err) {
console.log("Definition error: "+node.type+".label",err);
l = defaultLabel;
}
return RED.text.bidi.enforceTextDirectionWithUCC(l);
}
return {
createObjectElement: buildMessageElement,
validatePropertyExpression: validatePropertyExpression,
getNodeIcon: getNodeIcon,
getNodeLabel: getNodeLabel
}
})();

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015, 2016 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@ RED.workspaces = (function() {
var activeWorkspace = 0;
var workspaceIndex = 0;
function addWorkspace(ws) {
function addWorkspace(ws,skipHistoryEntry) {
if (ws) {
workspace_tabs.addTab(ws);
workspace_tabs.resize();
@@ -34,9 +34,13 @@ RED.workspaces = (function() {
RED.nodes.addWorkspace(ws);
workspace_tabs.addTab(ws);
workspace_tabs.activateTab(tabId);
RED.history.push({t:'add',workspaces:[ws],dirty:RED.nodes.dirty()});
RED.nodes.dirty(true);
if (!skipHistoryEntry) {
RED.history.push({t:'add',workspaces:[ws],dirty:RED.nodes.dirty()});
RED.nodes.dirty(true);
}
}
RED.view.focus();
return ws;
}
function deleteWorkspace(ws) {
if (workspace_tabs.count() == 1) {
@@ -90,11 +94,11 @@ RED.workspaces = (function() {
node: workspace,
dirty: RED.nodes.dirty()
}
workspace.changed = true;
RED.history.push(historyEvent);
workspace_tabs.renameTab(workspace.id,label);
RED.nodes.dirty(true);
RED.sidebar.config.refresh();
$("#menu-item-workspace-menu-"+workspace.id.replace(".","-")).text(label);
}
RED.tray.close();
}
@@ -110,6 +114,7 @@ RED.workspaces = (function() {
$('<input type="text" style="display: none;" />').prependTo(dialogForm);
dialogForm.submit(function(e) { e.preventDefault();});
$("#node-input-name").val(workspace.label);
RED.text.bidi.prepareInput($("#node-input-name"))
dialogForm.i18n();
},
close: function() {
@@ -133,7 +138,12 @@ RED.workspaces = (function() {
activeWorkspace = tab.id;
event.workspace = activeWorkspace;
RED.events.emit("workspace:change",event);
window.location.hash = 'flow/'+tab.id;
RED.sidebar.config.refresh();
RED.view.focus();
},
onclick: function(tab) {
RED.view.focus();
},
ondblclick: function(tab) {
if (tab.type != "subflow") {
@@ -143,33 +153,31 @@ RED.workspaces = (function() {
}
},
onadd: function(tab) {
RED.menu.addItem("menu-item-workspace",{
id:"menu-item-workspace-menu-"+tab.id.replace(".","-"),
label:tab.label,
onselect:function() {
workspace_tabs.activateTab(tab.id);
}
});
RED.menu.setDisabled("menu-item-workspace-delete",workspace_tabs.count() == 1);
},
onremove: function(tab) {
RED.menu.setDisabled("menu-item-workspace-delete",workspace_tabs.count() == 1);
RED.menu.removeItem("menu-item-workspace-menu-"+tab.id.replace(".","-"));
},
onreorder: function(oldOrder, newOrder) {
RED.history.push({t:'reorder',order:oldOrder,dirty:RED.nodes.dirty()});
RED.nodes.dirty(true);
setWorkspaceOrder(newOrder);
},
minimumActiveTabWidth: 150
minimumActiveTabWidth: 150,
scrollable: true,
addButton: function() {
addWorkspace();
}
});
}
function init() {
createWorkspaceTabs();
$('#btn-workspace-add-tab').on("click",function(e) {addWorkspace(); e.preventDefault()});
RED.events.on("sidebar:resize",workspace_tabs.resize);
RED.actions.add("core:show-next-tab",workspace_tabs.nextTab);
RED.actions.add("core:show-previous-tab",workspace_tabs.previousTab);
RED.menu.setAction('menu-item-workspace-delete',function() {
deleteWorkspace(RED.nodes.workspace(activeWorkspace));
});
@@ -177,6 +185,14 @@ RED.workspaces = (function() {
$(window).resize(function() {
workspace_tabs.resize();
});
RED.actions.add("core:add-flow",addWorkspace);
RED.actions.add("core:edit-flow",editWorkspace);
RED.actions.add("core:remove-flow",removeWorkspace);
}
function editWorkspace(id) {
showRenameWorkspaceDialog(id||activeWorkspace);
}
function removeWorkspace(ws) {
@@ -201,9 +217,7 @@ RED.workspaces = (function() {
add: addWorkspace,
remove: removeWorkspace,
order: setWorkspaceOrder,
edit: function(id) {
showRenameWorkspaceDialog(id||activeWorkspace);
},
edit: editWorkspace,
contains: function(id) {
return workspace_tabs.contains(id);
},
@@ -218,6 +232,8 @@ RED.workspaces = (function() {
var sf = RED.nodes.subflow(id);
if (sf) {
addWorkspace({type:"subflow",id:id,icon:"red/images/subflow_tab.png",label:sf.name, closeable: true});
} else {
return;
}
}
workspace_tabs.activateTab(id);
@@ -225,7 +241,6 @@ RED.workspaces = (function() {
refresh: function() {
RED.nodes.eachWorkspace(function(ws) {
workspace_tabs.renameTab(ws.id,ws.label);
$("#menu-item-workspace-menu-"+ws.id.replace(".","-")).text(ws.label);
})
RED.nodes.eachSubflow(function(sf) {

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2014, 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2013 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,22 @@
* limitations under the License.
**/
RED.validators = {
number: function(){return function(v) { return v!=='' && !isNaN(v);}},
regex: function(re){return function(v) { return re.test(v);}}
number: function(blankAllowed){return function(v) { return (blankAllowed&&(v===''||v===undefined)) || (v!=='' && !isNaN(v));}},
regex: function(re){return function(v) { return re.test(v);}},
typedInput: function(ptypeName,isConfig) { return function(v) {
var ptype = $("#node-"+(isConfig?"config-":"")+"input-"+ptypeName).val() || this[ptypeName];
if (ptype === 'json') {
try {
JSON.parse(v);
return true;
} catch(err) {
return false;
}
} else if (ptype === 'msg' || ptype === 'flow' || ptype === 'global' ) {
return RED.utils.validatePropertyExpression(v);
} else if (ptype === 'num') {
return /^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/.test(v);
}
return true;
}}
};

8
editor/sass/ace.scss Normal file
View File

@@ -0,0 +1,8 @@
.ace_gutter {
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.ace_scroller {
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ $form-placeholder-color: #bbbbbb;
$form-text-color: #444;
$form-input-focus-color: rgba(85,150,230,0.8);
$form-input-border-color: #ccc;
$form-input-border-selected-color: #aaa;
$node-selected-color: #ff7f0e;
@@ -42,18 +43,22 @@ $palette-header-background: #f3f3f3;
$workspace-button-background: #fff;
$workspace-button-background-hover: #ddd;
$workspace-button-background-active: #efefef;
$workspace-button-color: #999;
$workspace-button-color: #888;
$workspace-button-color-disabled: #ccc;
$workspace-button-color-focus: #999;
$workspace-button-color-hover: #666;
$workspace-button-color-active: #666;
$workspace-button-color-selected: #AAA;
$workspace-button-toggle-color: #999;
$workspace-button-toggle-color-selected: #888;
$workspace-button-toggle-color-disabled: #ddd;
$workspace-button-color-focus-outline: rgba(85,150,230,0.2);
$typedInput-button-background: #efefef;
$typedInput-button-background-hover: #ddd;
$typedInput-button-background-active: #e3e3e3;
$typedInput-button-background-active: #ddd;
$editor-button-color-primary: #eee;
$editor-button-background-primary: #AD1625;
@@ -61,4 +66,4 @@ $editor-button-background-primary-hover: #6E0A1E;
$editor-button-color: #999;
$editor-button-background: #fff;
$shade-color: rgba(220,220,220,0.5);
$shade-color: rgba(200,200,200,0.5);

193
editor/sass/debug.scss Normal file
View File

@@ -0,0 +1,193 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
.debug-window {
padding:0;
margin:0;
background: #fff;
line-height: 20px;
}
.debug-window .debug-message-payload {
font-size: 14px;
}
.debug-content {
position: absolute;
top: 43px;
bottom: 0px;
left:0px;
right: 0px;
overflow-y: scroll;
}
.debug-filter-box {
position:absolute;
top: 42px;
left: 0px;
right: 0px;
background: #f9f9f9;
padding: 10px;
border-bottom: 1px solid #ddd;
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
}
.debug-filter-row {
text-align: right;
}
.debug-message {
border-bottom: 1px solid #eee;
border-left: 8px solid #eee;
border-right: 8px solid #eee;
padding: 2px;
}
.debug-message-meta {
background: #fff;
font-size: 10px;
color: #777;
}
.debug-message-date {
padding: 1px 5px 1px 1px;
}
.debug-message-topic {
display: block;
color: #a66;
}
.debug-message-name {
padding: 1px 5px;
color: #777;
}
.debug-message-payload {
display: block;
padding: 2px;
background: #fff;
}
.debug-message-level-log {
border-left-color: #eee;
border-right-color: #eee;
}
.debug-message-level-30 {
border-left-color: #ffdf9d;
border-right-color: #ffdf9d;
}
.debug-message-level-20 {
border-left-color: #f99;
border-right-color: #f99;
}
.debug-message-object-entry {
padding-left: 15px;
padding-bottom: 3px;
padding-top: 3px;
}
.debug-message-element {
color: #333;
font-family: Menlo, monospace;
font-size: 12px !important;
line-height: 1.3em;
}
.debug-message-object-key {
color: #792e90;
}
.debug-message-object-value {
}
.debug-message-object-handle {
color: #666;
font-size: 1em;
width: 1em;
text-align: center;
transition: transform 0.1s ease-in-out;
transform: rotate(90deg);
}
.debug-message-element:not(.debug-message-top-level)>.debug-message-expandable>.debug-message-object-handle {
margin-left: -1em;
}
.debug-message-object-entry>.debug-message-expandable>.debug-message-object-handle {
margin-left: -1em;
}
.debug-message-object-entry.collapsed>span>.debug-message-object-handle {
transform: rotate(0deg);
}
.debug-message-element.collapsed>span>.debug-message-object-handle {
transform: rotate(0deg);
}
.debug-message-object-entry.collapsed > .debug-message-object-entry {
display:none;
}
.debug-message-element.collapsed .debug-message-object-entry {
display:none;
}
.debug-message-element:not(.collapsed)>.debug-message-expandable>.debug-message-object-value>.debug-message-object-header {
display:none;
}
.debug-message-element.collapsed .debug-message-buffer-opts {
display: none;
}
.debug-message-element.collapsed .debug-message-object-type-header {
display:none;
}
.debug-message-object-entry pre {
font-family: Menlo, monospace;
font-size: 12px;
line-height: 1.4em;
margin: 0 0 0 -1em;
}
.debug-message-type-other { color: #2033d6; }
.debug-message-type-string { color: #b72828; }
.debug-message-type-null { color: #666; font-style: italic;}
.debug-message-type-meta { color: #666; font-style: italic;}
.debug-message-type-number { color: #2033d6; };
.debug-message-type-number-toggle { cursor: pointer;}
.debug-message-expandable {
cursor: pointer;
}
.debug-message-expandable:hover {
background: #fefefe;
}
.debug-message-expandable:hover .debug-message-object-handle {
color: #b72828 !important;
}
.debug-message-buffer-opts a {
font-size: 9px;
color: #bbb;
border: 1px solid #bbb;
border-radius: 2px;
padding: 2px 5px;
margin-left: 5px;
}
.debug-message-buffer-opts a:hover {
text-decoration: none;
color: #999;
border: 1px solid #999;
background: #f3f3f3;
}
.debug-message-buffer-raw > .debug-message-string-rows {
display: none;
}
.debug-message-buffer-string > .debug-message-array-rows {
display: none;
}
.debug-message-type-string-swatch {
display: inline-block;
width: 1.1em;
height: 0.9em;
vertical-align: middle;
border-radius: 3px;
margin: 0 4px;
}

516
editor/sass/diff.scss Normal file
View File

@@ -0,0 +1,516 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
#node-dialog-view-diff {
height: 600px;
.red-ui-editableList-container {
border-radius:1px;
padding:0;
background: #f9f9f9;
}
#node-dialog-view-diff-diff {
position: absolute;
top:80px;
bottom:10px;
left:10px;
right:10px;
li {
background: #f9f9f9;
padding: 0px;
border: none;
min-height: 0;
}
}
.red-ui-editableList-item-content {
padding: 5px;
// padding-bottom: 5px;
}
}
#node-dialog-view-diff-headers {
position: absolute;
left:17px;
right:32px;
top: 55px;
height: 25px;
.node-diff-node-entry-cell:not(:first-child) {
background: #f9f9f9;
text-align: center;
border-top: 1px solid $secondary-border-color;
border-color:$secondary-border-color;
}
.node-diff-node-entry-cell:last-child {
border-right: 1px solid $secondary-border-color;
}
}
.node-diff-toolbar {
position:absolute;
top:0;
left:0;
right:0;
height: 43px;
box-sizing: border-box;
color: #666;
text-align: right;
padding: 8px 10px;
background: #f3f3f3;
border-bottom: 1px solid $secondary-border-color;
white-space: nowrap;
}
.node-diff-tab {
background: #fff;
border: 1px solid #ddd;
border-radius: 1px;
overflow: hidden;
&.collapsed {
.node-diff-tab-title .node-diff-chevron {
transform: rotate(-90deg);
}
.node-diff-node-entry {
display: none;
}
}
}
.node-diff-tab-stats {
font-size: 0.9em;
}
.node-diff-chevron {
display: inline-block;
width: 15px;
text-align: center;
margin-left: 3px;
transition: transform 0.1s ease-in-out;
}
.node-diff-node-entry {
margin-left: 20px;
font-size: 0.9em;
&:first-child {
border-top: 1px solid #eee;
}
&:not(:last-child) {
border-bottom: 1px solid #eee;
}
&.collapsed {
.node-diff-chevron {
transform: rotate(-90deg);
}
.node-diff-node-entry-properties {
display: none;
}
}
&:not(.collapsed) {
.node-diff-node-entry-cell:not(:first-child) {
//display: none;
}
.node-diff-node-entry-cell:first-child {
//width: 100%
}
}
table {
border-collapse: collapse;
table-layout:fixed;
// Fix for table-layout: fixed on safari:
max-width: none;
width: auto;
min-width: 100%;
}
td, th {
border: 1px solid $secondary-border-color;
padding: 0 0 0 3px;
text-align: left;
overflow-x: auto;
}
tr {
vertical-align: top;
&:first-child td {
white-space:nowrap;
overflow:hidden;
}
}
td:first-child {
width: 140px;
}
td:not(:first-child) {
width: calc( 100% - 140px);
}
td {
.node-diff-status {
margin-left: 0;
}
}
tr:not(.node-diff-property-header) {
.node-diff-status {
width: 12px;
margin-left: 0;
margin-top: 0;
margin-bottom: 0;
margin-right: 5px;
}
}
}
.node-diff-three-way {
.node-diff-node-entry-cell {
width: calc((100% - 220px) / 2);
&:first-child {
width: 220px;
}
}
td:not(:first-child) {
width: calc( (100% - 140px) / 2);
}
.node-diff-node-entry {
.node-diff-node-entry-cell {
width: calc((100% + 20px - 220px) / 2);
&:first-child {
width: 200px;
}
}
}
}
.node-diff-column {
display:inline-block;
height:100%;
width:50%;
box-sizing: border-box;
white-space:nowrap;
overflow: hidden;
&:first-child {
border-right: 1px solid $secondary-border-color
}
}
.node-diff-tab-title {
cursor: pointer;
padding: 0;
// background: #f6f6f6;
}
.node-diff-tab-title-meta {
vertical-align: middle;
display: inline-block;
padding-top: 2px;
}
.node-diff-node-entry-header {
cursor: pointer;
}
.node-diff-node-entry-node {
vertical-align: middle;
display: inline-block;
margin: 5px;
width: 18px;
height: 15px;
background: #ddd;
border-radius: 2px;
border: 1px solid #999;
background-position: 5% 50%;
background-repeat: no-repeat;
background-size: contain;
position: relative;
.palette_icon {
background-position: 49% 50%;
width: 15px;
}
.palette_icon_container {
width: 18px;
}
}
.node-diff-tab-empty {
.node-diff-chevron i {
display: none;
}
.node-diff-tab-title {
cursor: default;
}
}
.node-diff-node-deleted {
//background: #fadddd;
cursor: default !important;
.node-diff-status {
color: #f80000;
}
.node-diff-node-entry-node {
opacity: 0.5;
}
.node-diff-node-description {
opacity: 0.5;
text-decoration: line-through;
}
}
.node-diff-node-added {
//background: #eefaee;
cursor: default !important;
.node-diff-status {
color: #009900;
}
}
.node-diff-node-moved {
//background: #eefaee;
.node-diff-status {
color: #3f81b3;
}
}
.node-diff-node-changed {
//background: #fff2ca;
.node-diff-status {
color: #f89406;
}
}
.node-diff-node-unchanged {
//background: #fff2ca;
.node-diff-status {
color: #bbb;
}
}
.node-diff-node-conflict {
.node-diff-status {
color: #9b45ce;
}
}
.node-diff-node-entry-title {
display: inline-block;
.node-diff-status {
margin-left: 15px;
}
}
.node-diff-node-entry-properties {
margin: 5px ;
color: #666;
}
.node-diff-status {
display: inline-block;
height: 20px;
margin-left: 5px;
vertical-align: top;
margin-top: 6px;
margin-bottom: 6px;
text-align: center;
}
.node-diff-node-description {
color: $form-text-color;
margin-right: 5px;
padding-top: 5px;
display: inline-block;
&:after {
content: "";
display: table;
clear: both;
}
}
.node-diff-node-meta {
float: right;
//font-size: 0.9em;
color: #999;
margin-top: 7px;
margin-right: 10px;
}
.node-diff-count { color: #999}
.node-diff-added { color: #009900}
.node-diff-deleted { color: #f80000}
.node-diff-changed { color: #f89406}
.node-diff-conflicted { color: purple}
.node-diff-node-entry-cell {
display: inline-block;
vertical-align: top;
box-sizing: border-box;
width: calc( (100% - 20px) / 2);
height: 32px;
border-left: 1px solid #eee;
padding-top: 2px;
white-space: nowrap;
overflow: hidden;
position: relative;
}
.node-diff-empty {
background: #f3f3f3;
background: repeating-linear-gradient(
20deg,
#fff, #fff 5px,
#f6f6f6 5px,
#f6f6f6 10px
);
}
.node-diff-node-entry-cell:first-child {
border-left: none;
}
.node-diff-property-cell-label {
margin-left: 20px;
vertical-align: top;
box-sizing: border-box;
padding-left: 8px;
width: 120px;
}
.node-diff-property-wires {
display: inline-block;
.node-diff-node-entry-node {
width: 18px;
height: 15px;
}
.palette_icon_container {
width: 18px;
}
.palette_icon {
width: 15px;
}
ul,li,ol {
background: none !important;
}
ul {
vertical-align: middle;
display: inline-block;
margin-left: 5px;
}
li {
list-style-type: none !important;
}
ol {
font-size: 0.9em;
margin: 0;
& > span {
vertical-align: middle;
display: inline-block;
width: 30px;
text-align: center;
}
& > li:not(:last-child) {
border-bottom: 1px solid #999;
}
}
}
.node-diff-node-props .node-diff-node-entry-cell:first-child {
padding: 6px 0px;
span:not(.node-diff-chevron) {
margin-left: 5px;
}
}
.node-diff-property-cell {
// vertical-align: top;
// display:inline-block;
//
// box-sizing: border-box;
// padding: 1px 5px;
//min-height: 30px;
&.node-diff-node-changed {
background: #fff2e1 !important;
}
&.node-diff-node-conflict {
background: #ffdad4 !important;
}
}
.node-diff-selectbox {
position: absolute;
top:0;
right:0;
bottom:0;
width: 35px;
text-align: center;
border-left: 1px solid #eee;
margin:0;
input {
margin-top: 8px;
}
&:hover {
background: #f3f3f3;
}
}
.node-diff-node-entry-conflict.node-diff-select-remote {
.node-diff-node-remote {
background: #e7ffe3;
label {
border-left-color: #b8daad;
}
}
.node-diff-node-local {
background: #ffe1e1;
label {
border-left-color: #e4bcbc;
}
}
}
.node-diff-node-entry-conflict.node-diff-select-local {
.node-diff-node-local {
background: #e7ffe3;
label {
border-left-color: #b8daad;
}
}
.node-diff-node-remote {
background: #ffe1e1;
label {
border-left-color: #e4bcbc;
}
}
}
#node-dialog-confirm-deploy {
.node-dialog-confirm-row {
text-align: left; padding-top: 10px;
}
ul {
font-size: 0.9em;
width: 400px;
margin: 10px auto;
text-align: left;
}
.node-dialog-confirm-conflict-row {
img {
vertical-align:middle;
height: 30px;
margin-right: 10px;
}
i {
vertical-align:middle;
text-align: center;
font-size: 30px;
width: 30px;
margin-right: 10px;
}
div {
vertical-align: middle;
width: calc(100% - 60px);
display:inline-block;
}
}
}
#node-diff-toolbar-resolved-conflicts .node-diff-status {
margin:0;
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
width: 100%;
height: 100%;
display: none;
z-index:100;
}
#dropTarget div {
display: table-cell;
@@ -34,4 +35,3 @@
#dropTarget div i {
font-size: 80px;
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015, 2016 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,7 +46,12 @@
overflow: auto;
}
.editor-tray-body {
margin: 20px;
form {
margin: 20px;
}
}
.editor-tray-content {
overflow: auto;
}
.editor-tray-header {
@include disable-selection;
@@ -65,6 +70,13 @@
.editor-tray-footer {
@include component-footer;
height: 35px;
button {
@include editor-button;
padding: 3px 7px;
font-size: 11px;
}
}
.editor-tray-toolbar {
@@ -72,48 +84,9 @@
padding: 6px;
button {
@include workspace-button;
font-size: 14px;
padding: 6px 14px;
margin-right: 8px;
color: $editor-button-color;
background: $editor-button-background;
&.primary {
border-color: $editor-button-background-primary;
color: $editor-button-color-primary;
background: $editor-button-background-primary;
&.disabled, &.ui-state-disabled {
background: none;
color: $editor-button-color;
border-color: $form-input-border-color;
}
&:not(.disabled):not(.ui-button-disabled):hover {
border-color: $editor-button-background-primary-hover;
background: $editor-button-background-primary-hover;
color: $editor-button-color-primary !important;
}
}
&:not(.disabled):hover {
//color: $editor-button-color;
}
&.disabled {
background: none;
}
&.disabled:focus {
outline: none;
}
&.leftButton {
float: left;
margin-top: 1px;
}
&:not(.leftButton):not(:last-child) {
margin-right: 16px;
}
&.ui-state-disabled {
opacity: 1;
@include editor-button;
&.toggle {
@include workspace-button-toggle;
}
}
}
@@ -167,19 +140,18 @@
background: $background-color;
color: $workspace-button-color;
}
#editor-shade, #header-shade {
position: absolute;
top:0;
bottom:0;
left:0;
right:0;
background: $shade-color;
#palette-shade, #editor-shade, #header-shade, #sidebar-shade {
@include shade;
z-index: 2;
}
#sidebar-shade {
left: -8px;
top: -1px;
bottom: -1px;
}
.dialog-form,#dialog-form, #dialog-config-form {
margin: 0;
height: 100%;
}
@@ -196,7 +168,7 @@
display: inline-block;
width: 100px;
}
.form-row input {
.form-row input, .form-row div[contenteditable="true"] {
width:70%;
}
@@ -230,7 +202,12 @@
font-size: 13px;
border-radius: 4px;
padding: 0 10px;
&.toggle {
@include workspace-button-toggle;
}
}
.editor-button-small {
height: 20px;
line-height: 18px;
@@ -255,7 +232,7 @@
margin: 1px 0 0 0;
padding: 0;
height: 22px;
width: 150px;
width: 200px;
}
#node-config-dialog-user-count {

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -157,6 +157,8 @@
stroke: $node-selected-color !important;
}
.node_highlighted {
border-color: #dd1616 !important;
border-style: dashed !important;
stroke: #dd1616;
stroke-width: 2;
stroke-dasharray: 10, 4;
@@ -168,6 +170,11 @@
stroke-dasharray:8, 3;
}
.node_quickadd * {
stroke-dasharray: 12,3;
}
.node_status_label {
@include disable-selection;
stroke-width: 0;
@@ -181,6 +188,13 @@
stroke: $port-selected-color;
fill: $port-selected-color;
}
.port_quick_link {
stroke: $port-selected-color;
fill: $port-selected-color;
}
.subflowport {
stroke-dasharray: 5,5;
fill: #eee;
@@ -258,3 +272,25 @@ g.link_unknown path.link_line {
stroke-width: 2;
stroke-dasharray: 10, 4;
}
@keyframes port_tooltip_fadeIn { from { opacity:0; } to { opacity:1; } }
.port_tooltip {
opacity:0;
animation: 0.1s ease-in 0s 1 normal forwards port_tooltip_fadeIn;
pointer-events: none;
path {
fill: white;
stroke: #999;
stroke-width: 1;
}
}
.port_tooltip_label {
stroke-width: 0;
fill: #666;
font-size: 12px;
pointer-events: none;
-webkit-touch-callout: none;
@include disable-selection;
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
button,
input,
select,
div[contenteditable="true"],
textarea {
margin: 0;
font-size: 100%;
@@ -33,12 +34,14 @@ textarea {
}
button,
div[contenteditable="true"],
input {
*overflow: visible;
line-height: normal;
}
button::-moz-focus-inner,
div[contenteditable="true"]::-moz-focus-inner,
input::-moz-focus-inner {
padding: 0;
border: 0;
@@ -110,6 +113,7 @@ legend small {
label,
input,
div[contenteditable="true"],
button,
select,
textarea {
@@ -119,6 +123,7 @@ textarea {
}
input,
div[contenteditable="true"],
button,
select,
textarea {
@@ -146,6 +151,7 @@ input[type="url"],
input[type="search"],
input[type="tel"],
input[type="color"],
div[contenteditable="true"],
.uneditable-input {
box-sizing: border-box;
display: inline-block;
@@ -161,6 +167,7 @@ input[type="color"],
input,
textarea,
div[contenteditable="true"],
.uneditable-input {
width: 206px;
}
@@ -184,6 +191,7 @@ input[type="url"],
input[type="search"],
input[type="tel"],
input[type="color"],
div[contenteditable="true"],
.uneditable-input {
background-color: #ffffff;
border: 1px solid $form-input-border-color;
@@ -207,6 +215,7 @@ input[type="url"]:focus,
input[type="search"]:focus,
input[type="tel"]:focus,
input[type="color"]:focus,
div[contenteditable="true"]:focus,
.uneditable-input:focus {
border-color: $form-input-focus-color;
outline: 0;
@@ -294,11 +303,13 @@ textarea:-moz-placeholder {
}
input:-ms-input-placeholder,
div[contenteditable="true"]:-ms-input-placeholder,
textarea:-ms-input-placeholder {
color: $form-placeholder-color;
}
input::-webkit-input-placeholder,
div[contenteditable="true"]::-webkit-input-placeholder,
textarea::-webkit-input-placeholder {
color: $form-placeholder-color;
}
@@ -384,6 +395,7 @@ textarea[class*="span"],
input,
textarea,
div[contenteditable="true"],
.uneditable-input {
margin-left: 0;
}
@@ -515,12 +527,14 @@ input[type="checkbox"][readonly] {
.control-group.warning .checkbox,
.control-group.warning .radio,
.control-group.warning input,
.control-group.warning div[contenteditable="true"],
.control-group.warning select,
.control-group.warning textarea {
color: #c09853;
}
.control-group.warning input,
.control-group.warning div[contenteditable="true"],
.control-group.warning select,
.control-group.warning textarea {
border-color: #c09853;
@@ -530,6 +544,7 @@ input[type="checkbox"][readonly] {
}
.control-group.warning input:focus,
.control-group.warning div[contenteditable="true"]:focus,
.control-group.warning select:focus,
.control-group.warning textarea:focus {
border-color: #a47e3c;
@@ -554,12 +569,14 @@ input[type="checkbox"][readonly] {
.control-group.error .checkbox,
.control-group.error .radio,
.control-group.error input,
.control-group.error div[contenteditable="true"],
.control-group.error select,
.control-group.error textarea {
color: #b94a48;
}
.control-group.error input,
.control-group.error div[contenteditable="true"],
.control-group.error select,
.control-group.error textarea {
border-color: #b94a48;
@@ -569,6 +586,7 @@ input[type="checkbox"][readonly] {
}
.control-group.error input:focus,
.control-group.error div[contenteditable="true"]:focus,
.control-group.error select:focus,
.control-group.error textarea:focus {
border-color: #953b39;
@@ -593,12 +611,14 @@ input[type="checkbox"][readonly] {
.control-group.success .checkbox,
.control-group.success .radio,
.control-group.success input,
.control-group.success div[contenteditable="true"],
.control-group.success select,
.control-group.success textarea {
color: #468847;
}
.control-group.success input,
.control-group.success div[contenteditable="true"],
.control-group.success select,
.control-group.success textarea {
border-color: #468847;
@@ -608,6 +628,7 @@ input[type="checkbox"][readonly] {
}
.control-group.success input:focus,
.control-group.success div[contenteditable="true"]:focus,
.control-group.success select:focus,
.control-group.success textarea:focus {
border-color: #356635;
@@ -632,12 +653,14 @@ input[type="checkbox"][readonly] {
.control-group.info .checkbox,
.control-group.info .radio,
.control-group.info input,
.control-group.info div[contenteditable="true"],
.control-group.info select,
.control-group.info textarea {
color: #3a87ad;
}
.control-group.info input,
.control-group.info div[contenteditable="true"],
.control-group.info select,
.control-group.info textarea {
border-color: #3a87ad;
@@ -647,6 +670,7 @@ input[type="checkbox"][readonly] {
}
.control-group.info input:focus,
.control-group.info div[contenteditable="true"]:focus,
.control-group.info select:focus,
.control-group.info textarea:focus {
border-color: #2d6987;
@@ -663,6 +687,7 @@ input[type="checkbox"][readonly] {
}
input:focus:invalid,
div[contenteditable="true"]:focus:invalid,
textarea:focus:invalid,
select:focus:invalid {
color: #b94a48;
@@ -670,6 +695,7 @@ select:focus:invalid {
}
input:focus:invalid:focus,
div[contenteditable="true"]:focus:invalid:focus,
textarea:focus:invalid:focus,
select:focus:invalid:focus {
border-color: #e9322d;
@@ -727,6 +753,8 @@ select:focus:invalid:focus {
.input-append input,
.input-prepend input,
.input-append div[contenteditable="true"],
.input-prepend div[contenteditable="true"],
.input-append select,
.input-prepend select,
.input-append .uneditable-input,
@@ -740,6 +768,8 @@ select:focus:invalid:focus {
.input-append input,
.input-prepend input,
.input-append div[contenteditable="true"],
.input-prepend div[contenteditable="true"],
.input-append select,
.input-prepend select,
.input-append .uneditable-input,
@@ -755,6 +785,8 @@ select:focus:invalid:focus {
.input-append input:focus,
.input-prepend input:focus,
.input-append div[contenteditable="true"]:focus,
.input-prepend div[contenteditable="true"]:focus,
.input-append select:focus,
.input-prepend select:focus,
.input-append .uneditable-input:focus,
@@ -809,6 +841,7 @@ select:focus:invalid:focus {
}
.input-append input,
.input-append div[contenteditable="true"],
.input-append select,
.input-append .uneditable-input {
-webkit-border-radius: 4px 0 0 4px;
@@ -839,6 +872,7 @@ select:focus:invalid:focus {
}
.input-prepend.input-append input,
.input-prepend.input-append div[contenteditable="true"],
.input-prepend.input-append select,
.input-prepend.input-append .uneditable-input {
-webkit-border-radius: 0;
@@ -923,6 +957,9 @@ input.search-query {
.form-search input,
.form-inline input,
.form-horizontal input,
.form-search div[contenteditable="true"],
.form-inline div[contenteditable="true"],
.form-horizontal div[contenteditable="true"],
.form-search textarea,
.form-inline textarea,
.form-horizontal textarea,
@@ -1045,3 +1082,8 @@ legend + .control-group {
.form-horizontal .form-actions {
padding-left: 180px;
}
.form-row div[contenteditable="true"] {
white-space: nowrap;
overflow: hidden;
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -111,6 +111,7 @@ span.logo {
}
#header .button-group > a {
display: inline-block;
position: relative;
float: left;
line-height: 22px;
font-size: 14px;
@@ -133,6 +134,20 @@ span.logo {
}
}
.deploy-button-spinner {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
text-align: center;
img {
opacity: 0.8;
height: 100%;
}
}
#btn-deploy {
padding: 4px 12px;
@@ -142,7 +157,7 @@ span.logo {
background: $deployDisabledButton;
color: #999 !important;
img {
.deploy-button-content>img {
opacity: 0.3;
}
@@ -158,7 +173,7 @@ span.logo {
}
}
img {
.deploy-button-content>img {
margin-right: 8px;
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015, 2016 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,11 +18,11 @@
font-size: 14px !important;
font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif !important;
}
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button {
.ui-widget input, .ui-widget div[contenteditable="true"], .ui-widget select, .ui-widget textarea, .ui-widget button {
font-size: 14px !important;
font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif !important;
}
.ui-widget input {
.ui-widget input, .ui-widget div[contenteditable="true"] {
box-shadow: none;
}
@@ -92,13 +92,18 @@
&.primary {
border-color: $editor-button-background-primary;
color: $editor-button-color-primary;
color: $editor-button-color-primary !important;
background: $editor-button-background-primary;
&:not(.disabled):hover {
border-color: $editor-button-background-primary-hover;
background: $editor-button-background-primary-hover;
color: $editor-button-color-primary !important;
}
&.disabled {
border-color: $form-input-border-color;
color: $workspace-button-color-disabled !important;
background: $editor-button-background;
}
}
&.disabled {
background: none;

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,19 +16,42 @@
#keyboard-help-dialog {
font-size: 0.9em;
padding-top: 10px;
}
.keyboard-shortcuts {
padding: 10px;
.keyboard-shortcut-entry.keyboard-shortcut-list-header {
padding:0 30px 0 5px;
div {
color: #666 !important;
}
}
.keyboard-shortcuts td {
padding: 7px 5px;
margin-bottom: 10px;
white-space: pre;
#keyboard-shortcut-list {
position: absolute;
top:30px;
left:10px;
right:10px;
bottom:10px;
}
.keyboard-shortcuts td:first-child {
text-align: right;
padding-right: 10px;
.keyboard-shortcut-entry {
padding: 0px 20px 0 10px;
div {
display: inline-block;
}
}
.keyboard-shortcut-entry-key {
width:150px;
}
.keyboard-shortcut-entry-scope {
float: right;
color: #999;
}
.keyboard-shortcut-entry-unassigned {
color: #999;
.keyboard-shortcut-entry-key {
font-style: italic;
}
}
.help-key {
border: 1px solid #ddd;
padding: 4px;
@@ -37,4 +60,6 @@
font-family: Courier, monospace;
box-shadow: #999 1px 1px 1px;
}
.help-key-block {
white-space: nowrap;
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,14 @@
user-select: none;
}
@mixin enable-selection {
-webkit-user-select: auto;
-khtml-user-select: auto;
-moz-user-select: auto;
-ms-user-select: auto;
user-select: auto;
}
@mixin component-border {
border: 1px solid $primary-border-color;
box-sizing: border-box;
@@ -32,56 +40,120 @@
@include disable-selection;
box-sizing: border-box;
display: inline-block;
color: $workspace-button-color;
color: $workspace-button-color !important;
background: $workspace-button-background;
border: 1px solid $form-input-border-color;
text-align: center;
margin:0;
text-decoration: none;
cursor:pointer;
&.disabled {
cursor: default;
color: $workspace-button-color-disabled;
color: $workspace-button-color-disabled !important;
}
&:hover, &:focus {
text-decoration: none;
}
&:not(.disabled):hover {
text-decoration: none;
color: $workspace-button-color-hover;
color: $workspace-button-color-hover !important;
background: $workspace-button-background-hover;
}
&:not(.disabled):focus {
color: $workspace-button-color-focus;
text-decoration: none;
color: $workspace-button-color-focus !important;
}
&:not(.disabled):active {
color: $workspace-button-color-active;
color: $workspace-button-color-active !important;
background: $workspace-button-background-active;
text-decoration: none;
}
&.selected:not(.disabled) {
color: $workspace-button-color-selected;
color: $workspace-button-color-selected !important;
background: $workspace-button-background-active;
cursor: default;
}
.button-group &:not(:first-child) {
border-left: none;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.button-group &:not(:last-child) {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
&:focus {
outline: 1px solid $workspace-button-color-focus-outline;
}
}
@mixin workspace-button-toggle {
@include workspace-button;
color: $workspace-button-color-selected;
background: $workspace-button-background-active;
&.selected:not(.disabled) {
color: $workspace-button-color;
background: $workspace-button-background;
}
.button-group:not(:last-child) {
margin-right: 10px;
}
@mixin workspace-button-toggle {
@include workspace-button;
color: $workspace-button-toggle-color !important;
background:$workspace-button-background-active;
margin-bottom: 1px;
&.selected:not(.disabled) {
color: $workspace-button-toggle-color-selected !important;
background: $workspace-button-background;
border-bottom-width: 2px;
border-bottom-color: $form-input-border-selected-color;
margin-bottom: 0;
cursor: default;
}
&.disabled {
color: $workspace-button-toggle-color-disabled !important;
}
}
@mixin editor-button {
@include workspace-button;
font-size: 14px;
padding: 6px 14px;
margin-right: 8px;
color: $editor-button-color !important;
background: $editor-button-background;
&.primary {
border-color: $editor-button-background-primary;
color: $editor-button-color-primary !important;
background: $editor-button-background-primary;
&.disabled, &.ui-state-disabled {
background: none;
color: $editor-button-color !important;
border-color: $form-input-border-color;
}
&:not(.disabled):not(.ui-button-disabled):hover {
border-color: $editor-button-background-primary-hover;
background: $editor-button-background-primary-hover;
color: $editor-button-color-primary !important;
}
}
&:not(.disabled):hover {
//color: $editor-button-color;
}
&.disabled {
background: none;
}
&.disabled:focus {
outline: none;
}
&.leftButton {
float: left;
margin-top: 1px;
}
&:not(.leftButton):not(:last-child) {
margin-right: 16px;
}
&.ui-state-disabled {
opacity: 1;
}
}
@mixin component-footer {
border-top: 1px solid $primary-border-color;
background: #f3f3f3;
@@ -93,6 +165,12 @@
height: 25px;
line-height: 23px;
padding: 0 10px;
.button-group:not(:last-child) {
margin-right: 5px;
}
}
@mixin component-footer-button {
@@ -106,9 +184,28 @@
padding: 0 5px;
}
}
@mixin component-footer-button-toggle {
@include workspace-button-toggle;
font-size: 11px;
line-height: 17px;
height: 18px;
&.text-button {
width: auto;
padding: 0 5px;
}
}
@mixin component-shadow {
border: 1px solid $secondary-border-color;
box-shadow: 1px 1px 4px rgba(0,0,0,0.2);
}
@mixin shade {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: $shade-color;
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -0,0 +1,223 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
#palette-editor {
text-align: left;
display: none;
position: absolute;
top: 0px;
right: 0;
bottom: 25px;
left:0;
padding: 0;
box-sizing:border-box;
background: #fff;
.red-ui-editableList-container {
border: none;
border-radius: 0;
padding: 0px;
li {
// border: none;
// border-top: 1px solid $primary-border-color;
padding: 0px;
.disabled {
background: #f3f3f3;
.palette-module-name {
font-style: italic;
color: #aaa;
}
.palette-module-version {
color: #aaa;
}
}
.red-ui-editableList-item-content {
padding: 12px 8px;
}
&:last-child {
// border-bottom: 1px solid $primary-border-color;
}
}
}
.palette-editor-tab {
position:absolute;
top:115px;
left:0;
right:0;
bottom:0
}
.palette-editor-toolbar {
background: #f3f3f3;
box-sizing: border-box;
padding: 8px 10px;
border-bottom: 1px solid $primary-border-color;
text-align: right;
}
.palette-module-button-group {
position: absolute;
right: 0;
bottom: 0;
a {
margin-left: 5px;
}
}
.palette-module-shade {
@include shade;
text-align: center;
padding-top: 20px;
}
#palette-module-install-shade {
padding-top: 80px;
}
.palette-module-shade-status {
color: #666;
}
.palette-module-meta {
color: #666;
position: relative;
&.disabled {
color: #ccc;
}
.fa {
width: 15px;
text-align: center;
margin-right: 5px;
}
}
.palette-module-name {
white-space: nowrap;
@include enable-selection;
}
.palette-module-version, .palette-module-updated, .palette-module-link {
font-style:italic;
font-size: 0.8em;
@include enable-selection;
}
.palette-module-updated {
margin-left: 10px;
}
.palette-module-link {
margin-left: 5px;
}
.palette-module-description {
margin-left: 20px;
font-size: 0.9em;
color: #999;
}
.palette-module-link {
}
.palette-module-set-button-group {
}
.palette-module-count {
border-radius: 4px;
background: #eee;
padding: 2px 8px;
font-size: 12px;
}
.palette-module-content {
display: none;
padding: 10px 3px;
}
i.fa.palette-module-node-chevron {
width: 8px;
margin-right: 0;
transform: rotate(0deg);
transition: transform 0.2s ease-in-out;
}
.expanded {
i.fa.palette-module-node-chevron {
transform: rotate(90deg);
}
.palette-module-set-button {
background:#f3f3f3 !important;
}
}
.palette-module-set {
border:1px solid $secondary-border-color;
border-radius: 0;
padding: 5px;
position: relative;
&:not(:last-child) {
border-bottom: none;
}
&:first-child {
border-top-right-radius: 2px;
border-top-left-radius: 2px;
}
&:last-child {
border-bottom-right-radius: 2px;
border-bottom-left-radius: 2px;
}
}
.palette-module-type {
color: #666;
padding-left: 5px;
font-size: 0.9em;
@include enable-selection;
}
.palette-module-type-swatch {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 3px;
vertical-align: middle;
margin-right: 5px;
background: #fff;
border: 1px solid #fff;
}
.palette-module-set-button-group {
position: absolute;
right: 4px;
top: 4px;
}
.palette-module-set-disabled {
background: #eee;
.palette-module-type {
color: #999;
}
}
.palette-module-more {
padding: 0 !important;
margin-top: 10px;
margin-bottom: 10px;
background: $tab-background-inactive;
a {
display: block;
text-align: center;
padding: 12px 8px;
color: #AD1625;
&:hover {
text-decoration: none;
background: $tab-background-hover;
}
}
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,10 +25,25 @@
text-align: center;
@include disable-selection;
@include component-border;
transition: width 0.2s ease-in-out;
}
.palette-expanded {
& #palette {
width: 380px;
box-shadow: 1px 0 6px rgba(0,0,0,0.1);
}
& #workspace { left: 379px !important; }
& #palette-collapse-all { display: none; }
& #palette-expand-all { display: none; }
& #palette-container { display: none !important; }
& #palette-search { display: none !important; }
& #palette-edit { background: $workspace-button-background-active }
& #palette-editor { display: block !important }
}
.palette-scroll {
display: none;
position: absolute;
top: 35px;
right: 0;
@@ -38,15 +53,11 @@
overflow-y: auto;
box-sizing:border-box;
}
.palette-spinner {
padding-top: 40px;
#palette > .palette-spinner {
padding-top: 80px;
}
#palette-search {
position: absolute;
display: none;
top: 0;
left:0;
right:0;
.palette-search {
position: relative;
overflow: hidden;
background: #ffffff;
text-align: center;
@@ -55,48 +66,7 @@
border-bottom: 1px solid $primary-border-color;
box-sizing:border-box;
}
#palette-search i {
font-size: 10px;
color: #666;
}
#palette-search i.fa-search {
position: absolute;
pointer-events: none;
left: 12px;
top: 12px;
}
#palette-search i.fa-times {
position: absolute;
right: 7px;
top: 12px;
}
#palette-search-clear {
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 20px;
display: none;
}
#palette-search input {
border-radius: 0;
border: none;
width: 100%;
box-shadow: none;
-webkit-box-shadow: none;
padding: 3px 17px 3px 22px;
margin: 0px;
height: 30px;
box-sizing:border-box;
}
#palette-search input:focus {
border: none;
box-shadow: none;
-webkit-box-shadow: none;
}
#palette-footer {
@include component-footer;
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

192
editor/sass/search.scss Normal file
View File

@@ -0,0 +1,192 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
.red-ui-search {
z-index:1000;
display: none;
position: absolute;
width: 500px;
background: white;
left: 50%;
margin-left: -250px;
top: 0px;
border: 1px solid $primary-border-color;
box-shadow: 0 0 10px rgba(0,0,0,0.4);
ol {
}
}
.red-ui-type-search-shade {
@include shade;
z-index: 20;
position: fixed;
background: rgba(255,255,255,0.05);
}
.red-ui-type-search {
box-shadow: 0 1px 6px -3px black;
background: none;
width: 300px;
margin-left: 0px;
//height: 75px;
border: none;
.red-ui-search-container {
border-top-left-radius: 5px;
border-top-right-radius: 5px;
border: 1px dashed #aaa;
border-bottom: none;
padding: 0;
}
.red-ui-search-results-container {
display: none;
height: 150px;
.red-ui-editableList-container {
border: 1px dashed #aaa;
border-top: 1px solid #ccc;
}
}
.red-ui-search-result {
padding: 2px 2px 2px 5px;
font-size: 13px;
border-left-width: 3px;
border-right-width: 3px;
}
.red-ui-search-result-separator {
border-bottom: 3px solid #ddd;
}
.red-ui-search-result-node {
position: relative;
width: 18px;
height: 15px;
margin-top: 1px;
}
.red-ui-search-result-node-port {
position: absolute;
border-radius: 2px;
border: 1px solid #999;
width: 6px;
height: 7px;
top:4px;
left:-4px;
background: #eee;
box-sizing: border-box;
}
.red-ui-search-result-node-output{
left: 16px;
}
.palette_icon_container {
width: 18px;
}
.palette_icon {
width: 15px;
}
.red-ui-search-result-description {
margin-left:28px;
}
.red-ui-search-result-node-label {
color: #999;
}
}
.red-ui-search-container {
padding: 3px;
border-bottom: 1px solid $secondary-border-color;
}
.red-ui-search-results-container {
position:relative;
height: 300px;
padding: 5px;
background: #f9f9f9;
.red-ui-editableList-container {
background: white;
padding: 0;
background: #f9f9f9;
li {
padding: 0;
&.selected {
background: #efefef;
.red-ui-search-result {
border-left-color:#999;
border-right-color:#999;
}
}
}
}
}
.red-ui-search-result {
padding: 8px 2px 8px 5px;
display: block;
cursor: pointer;
color: $form-text-color;
border-left: 3px solid #fff;
border-right: 3px solid #fff;
&:hover {
text-decoration: none;
color: $form-text-color;
background: #efefef;
border-left-color:#efefef;
border-right-color:#efefef;
}
&:after {
content: "";
display: table;
clear: both;
}
}
.red-ui-search-result-node {
display: inline-block;
width: 30px;
float:left;
height: 25px;
background: #ddd;
border-radius: 5px;
border: 1px solid #999;
background-position: 5% 50%;
background-repeat: no-repeat;
background-size: contain;
position: relative;
.palette_icon_container {
border-right: none;
}
}
.red-ui-search-result-description {
margin-left: 40px;
margin-right: 5px;
}
.red-ui-search-result-node-label {
color: #222;
}
.red-ui-search-result-node-type {
font-style: italic;
font-size: 0.9em;
}
.red-ui-search-result-node-flow {
float:right;
font-size: 0.8em;
}
.red-ui-search-result-node-id {
display:none;
font-size: 0.8em;
}
.red-ui-search-empty {
padding: 10px;
text-align: center;
font-style: italic;
color: $form-placeholder-color;
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -71,6 +71,7 @@
padding: 8px 10px;
background: #f3f3f3;
border-bottom: 1px solid $secondary-border-color;
white-space: nowrap;
}
#sidebar-footer {
@@ -80,6 +81,9 @@
.sidebar-footer-button {
@include component-footer-button;
}
.sidebar-footer-button-toggle {
@include component-footer-button-toggle;
}
.sidebar-header-button {
@include workspace-button;
font-size: 13px;
@@ -97,10 +101,5 @@
}
.sidebar-shade {
position: absolute;
top:0;
bottom:0;
left:0;
right:0;
background: $shade-color;
@include shade;
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2013, 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
@import "jquery";
@import "bootstrap";
@import "ace";
@import "dropdownMenu";
@@ -34,20 +35,26 @@
@import "editor";
@import "library";
@import "search";
@import "tabs";
@import "tab-config";
@import "tab-info";
@import "popover";
@import "flow";
@import "palette-editor";
@import "diff";
@import "typedInput";
@import "editableList";
@import "ui/common/editableList";
@import "ui/common/searchBox";
@import "ui/common/typedInput";
@import "dragdrop";
@import "keyboard";
@import "debug";
body {
font-size: 14px;
@@ -82,11 +89,13 @@ code, pre {
}
code {
padding: 0px 4px;
padding: 0px 3px 2px 3px;
margin: 1px;
color: #AD1625;
white-space: nowrap;
background-color: #f7f7f9;
border: 1px solid #e1e1e8;
border-radius: 2px;
}
pre {
@@ -112,3 +121,7 @@ pre code {
background-color: transparent;
border: 0;
}
.hide {
display: none;
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015, 2016 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@ table.node-info tr.blank td {
padding-left: 0px;
}
table.node-info td:first-child{
color: #000;
color: #666;
vertical-align: top;
width: 90px;
padding: 3px;
@@ -81,3 +81,18 @@ div.node-info {
margin: 8px auto;
}
}
.node-info-tip {
position: absolute;
top: 40%;
left:0;
right:0;
padding: 20px;
font-size: 16px;
text-align: center;
line-height: 1.9em;
color : #bbb;
background-color: #fff;
@include disable-selection;
cursor: default;
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,47 +14,174 @@
* limitations under the License.
**/
ul.red-ui-tabs {
list-style-type: none;
padding:0;
margin: 0;
display: block;
height: 35px;
box-sizing:border-box;
white-space: nowrap;
border-bottom: 1px solid $primary-border-color;
background: #fff;
@include disable-selection;
}
ul.red-ui-tabs li {
box-sizing: border-box;
display: inline-block;
border-left: 1px solid $primary-border-color;
border-top: 1px solid $primary-border-color;
border-right: 1px solid $primary-border-color;
border-bottom: 1px solid $primary-border-color;
background: $tab-background-inactive;
margin: 3px 3px 0 3px;
height: 32px;
line-height: 29px;
max-width: 200px;
width: 14%;
overflow: hidden;
white-space: nowrap;
}
ul.red-ui-tabs li a.red-ui-tab-label {
display: block;
font-size: 14px;
padding-left: 12px;
width: 100%;
height: 100%;
color: #666;
}
ul.red-ui-tabs li {
.red-ui-tabs {
position: relative;
background: #fff;
overflow: hidden;
height: 35px;
box-sizing: border-box;
.red-ui-tabs-scroll-container {
height: 60px;
overflow-x: scroll;
overflow-y: hidden;
&::-webkit-scrollbar {
display: none;
}
}
& ul {
//background: #9999ff;
list-style-type: none;
padding:0;
margin: 0;
display: block;
height: 35px;
box-sizing:border-box;
border-bottom: 1px solid $primary-border-color;
white-space: nowrap;
@include disable-selection;
li {
box-sizing: border-box;
display: inline-block;
border-left: 1px solid $primary-border-color;
border-top: 1px solid $primary-border-color;
border-right: 1px solid $primary-border-color;
border-bottom: 1px solid $primary-border-color;
background: $tab-background-inactive;
margin: 3px 3px 0 3px;
height: 32px;
line-height: 29px;
max-width: 200px;
width: 14%;
overflow: hidden;
white-space: nowrap;
position: relative;
a.red-ui-tab-label {
display: block;
font-size: 14px;
padding-left: 12px;
width: 100%;
height: 100%;
color: #666;
}
a:hover {
text-decoration: none;
}
a:focus {
text-decoration: none;
}
&:not(.active) a:hover+a.red-ui-tab-close {
background: $tab-background-hover;
}
&.active {
background: $tab-background-active;
font-weight: bold;
border-bottom: 1px solid #fff;
z-index: 2;
a {
color: #333;
}
a.red-ui-tab-close {
color: #aaa;
background: $tab-background-active;
&:hover {
background: $workspace-button-background-hover !important;
color: $workspace-button-color-hover;
}
}
.red-ui-tab-icon {
opacity: 0.2;
}
}
&:not(.active) a:hover {
color: $workspace-button-color-hover;
background: $tab-background-hover;
}
}
}
&.red-ui-tabs-scrollable {
padding-left: 21px;
padding-right: 21px;
}
&.red-ui-tabs-add {
padding-right: 35px;
}
&.red-ui-tabs-add.red-ui-tabs-scrollable {
padding-right: 59px;
}
}
.red-ui-tab-button {
position: absolute;
box-sizing: border-box;
top: 0;
right: 0;
height: 35px;
background: #fff;
border-bottom: 1px solid $primary-border-color;
z-index: 2;
a {
@include workspace-button;
line-height: 32px;
height: 32px;
width: 32px;
margin-top: 3px;
margin-right:3px;
margin-left:3px;
border: 1px solid $primary-border-color;
z-index: 2;
}
}
.red-ui-tab-scroll {
width: 21px;
top: 0;
a {
height: 35px;
width: 21px;
display: block;
color: $link-color;
font-size: 22px;
text-align: center;
margin:0;
border-left: none;
border-right: none;
border-top: none;
}
}
.red-ui-tab-scroll-left {
left:0;
a {
border-right: 1px solid $primary-border-color;
// box-shadow: 8px 0px 5px -2px rgba(0,0,0,0.1);
}
}
.red-ui-tab-scroll-right {
right: 0px;
a {
border-left: 1px solid $primary-border-color;
// box-shadow: -8px 0px 5px -2px rgba(0,0,0,0.1);
}
}
.red-ui-tabs.red-ui-tabs-add .red-ui-tab-scroll-right {
right: 38px;
}
.red-ui-tab-icon {
margin-left: -8px;
margin-right: 3px;
margin-top: -2px;
opacity: 0.1;
width: 20px;
height: 20px;
vertical-align: middle;
}
.red-ui-tabs-badges {
position: absolute;
top:2px;
@@ -96,51 +223,3 @@ ul.red-ui-tabs li {
opacity: 1;
}
}
ul.red-ui-tabs li:not(.active) a:hover+a.red-ui-tab-close {
background: $tab-background-hover;
}
ul.red-ui-tabs li.active a.red-ui-tab-close {
color: #aaa;
background: $tab-background-active;
&:hover {
background: $workspace-button-background-hover !important;
color: $workspace-button-color-hover;
}
}
ul.red-ui-tabs li a:hover {
text-decoration: none;
}
ul.red-ui-tabs li:not(.active) a:hover {
color: $workspace-button-color-hover;
background: $tab-background-hover;
}
ul.red-ui-tabs li a:focus {
text-decoration: none;
}
ul.red-ui-tabs li.active {
background: $tab-background-active;
font-weight: bold;
border-bottom: 1px solid #fff;
z-index: 2;
}
ul.red-ui-tabs li.active a {
color: #333;
}
.red-ui-tab-icon {
margin-left: -8px;
margin-right: 3px;
margin-top: -2px;
opacity: 0.1;
width: 20px;
height: 20px;
vertical-align: middle;
}
ul.red-ui-tabs li.active .red-ui-tab-icon {
opacity: 0.2;
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2016 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -0,0 +1,70 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
.red-ui-searchBox-container {
position: relative;
i {
font-size: 10px;
color: #666;
}
i.fa-search {
position: absolute;
pointer-events: none;
left: 8px;
top: 9px;
}
i.fa-times {
position: absolute;
right: 5px;
top: 9px;
}
input {
border-radius: 0;
border: none;
width: 100%;
box-shadow: none;
-webkit-box-shadow: none;
padding: 3px 17px 3px 22px;
margin: 0px;
height: 30px;
box-sizing:border-box;
&:focus {
border: none;
box-shadow: none;
-webkit-box-shadow: none;
}
}
a {
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 20px;
display: none;
}
.red-ui-searchBox-resultCount {
position: absolute;
right: 18px;
top: 4px;
background: #eee;
color: #666;
padding: 1px 8px;
font-size: 9px;
border-radius: 4px;
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,7 +49,10 @@
border-color: $form-input-focus-color !important;
}
a {
button {
text-align: left;
border: none;
position: absolute;
box-sizing: border-box;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
@@ -66,6 +69,9 @@
margin-right:4px;
margin-top: 1px;
vertical-align: middle;
&.fa-ellipsis-h {
top: -1px;
}
}
&.disabled {
cursor: default;
@@ -82,44 +88,65 @@
&:not(.disabled):hover {
text-decoration: none;
background: $typedInput-button-background-hover;
span {
background: $typedInput-button-background-hover;
}
}
&:focus {
text-decoration: none;
outline: none;
box-shadow: inset 0 0 0 1px $form-input-focus-color;
}
&:not(.disabled):active {
background: $typedInput-button-background-active;
text-decoration: none;
}
&.red-ui-typedInput-full-width {
width: 100%;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
}
a.red-ui-typedInput-option-trigger {
button.red-ui-typedInput-option-expand {
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
right: 0;
}
button.red-ui-typedInput-option-trigger {
border-top-left-radius: 0px;
border-bottom-left-radius: 0px;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
padding: 0 5px 0 0;
padding: 0 0 0 0;
position:absolute;
left:0;
top:0;
bottom:0;
right:0;
width: calc( 100% );
i {
position:absolute;
right: 4px;
top: 7px;
}
span {
.red-ui-typedInput-option-label {
background:#fff;
position:absolute;
left:0;
right:23px;
top: 0;
padding: 0 5px 0 5px;
}
.red-ui-typedInput-option-caret {
top: 0;
position: absolute;
right: 0;
width: 17px;
}
&:focus {
box-shadow: none;
}
&:focus .red-ui-typedInput-option-caret {
box-shadow: inset 0 0 0 1px $form-input-focus-color;
}
}
}
.red-ui-typedInput-options {
@@ -139,12 +166,12 @@
}
&:focus {
text-decoration: none;
background: $typedInput-button-background-active;
outline: none;
}
&:active {
background: $typedInput-button-background-active;
text-decoration: none;
background: $typedInput-button-background-active;
}
}
}

View File

@@ -0,0 +1,23 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
@import "colors";
@import "mixins";
@import "forms";
@import "jquery";
@import "typedInput";
@import "editableList";

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,39 +40,21 @@
right: 322px;
overflow: hidden;
@include component-border;
transition: left 0.2s ease-in-out;
}
.workspace-footer-button {
@include component-footer-button;
}
#workspace-tabs {
margin-right: 35px;
}
#workspace-add-tab {
position: absolute;
box-sizing: border-box;
top: 0;
right: 0;
height: 35px;
width: 35px;
background: #fff;
border-bottom: 1px solid $primary-border-color;
}
#btn-workspace-add-tab {
@include workspace-button;
line-height: 32px;
height: 32px;
width: 32px;
margin-top: 3px;
margin-right:3px;
border: 1px solid $primary-border-color;
}
#workspace-footer {
@include component-footer;
}
#workspace-tabs:not(.workspace-focussed) {
opacity:0.8;
li.red-ui-tab.active a {
color:#666;
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -6,7 +6,7 @@
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<!--
Copyright 2013, 2015 IBM Corp.
Copyright JS Foundation and other contributors, http://js.foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -43,22 +43,8 @@
<div id="header-shade" class="hide"></div>
</div>
<div id="main-container" class="sidebar-closed hide">
<div id="palette">
<img src="red/images/spin.svg" class="palette-spinner hide"/>
<div id="palette-search">
<i class="fa fa-search"></i><input id="palette-search-input" type="text" data-i18n="[placeholder]palette.filter"><a href="#" id="palette-search-clear"><i class="fa fa-times"></i></a></input>
</div>
<div id="palette-container" class="palette-scroll"></div>
<div id="palette-footer">
<a class="palette-button" id="palette-collapse-all" href="#"><i class="fa fa-angle-double-up"></i></a>
<a class="palette-button" id="palette-expand-all" href="#"><i class="fa fa-angle-double-down"></i></a>
</div>
</div><!-- /palette -->
<div id="workspace">
<ul id="workspace-tabs"></ul>
<div id="workspace-add-tab"><a id="btn-workspace-add-tab" href="#"><i class="fa fa-plus"></i></a></div>
<div id="chart" tabindex="1"></div>
<div id="workspace-toolbar"></div>
<div id="workspace-footer">
@@ -66,13 +52,30 @@
<a class="workspace-footer-button" id="btn-zoom-zero" href="#"><i class="fa fa-circle-o"></i></a>
<a class="workspace-footer-button" id="btn-zoom-in" href="#"><i class="fa fa-plus"></i></a>
</div>
<div id="editor-shade" class="hide"></div>
</div>
<div id="editor-shade" class="hide"></div>
<div id="editor-stack"></div>
<div id="palette">
<img src="red/images/spin.svg" class="palette-spinner hide"/>
<div id="palette-search" class="palette-search hide">
<input type="text" data-i18n="[placeholder]palette.filter"></input>
</div>
<div id="palette-editor">
<div class="editor-tray-header"><div class="editor-tray-titlebar"><ul class="editor-tray-breadcrumbs"><li data-i18n="palette.editor.title"></li></ul></div><div class="editor-tray-toolbar"><button id="palette-editor-close" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only primary" role="button" aria-disabled="false" data-i18n="common.label.done"></button></div></div>
<ul id="palette-editor-tabs"></ul>
</div>
<div id="palette-container" class="palette-scroll hide"></div>
<div id="palette-footer">
<a class="palette-button" id="palette-collapse-all" href="#"><i class="fa fa-angle-double-up"></i></a>
<a class="palette-button" id="palette-expand-all" href="#"><i class="fa fa-angle-double-down"></i></a>
</div>
<div id="palette-shade" class="hide"></div>
</div><!-- /palette -->
<div id="sidebar">
<ul id="sidebar-tabs"></ul>
<div id="sidebar-content"></div>
<div id="sidebar-footer"></div>
<div id="sidebar-shade" class="hide"></div>
</div>
<div id="sidebar-separator"></div>
@@ -84,11 +87,25 @@
<div id="node-dialog-confirm-deploy" class="hide">
<form class="form-horizontal">
<div id="node-dialog-confirm-deploy-config" style="text-align: left; padding-top: 30px;" data-i18n="[prepend]deploy.confirm.improperlyConfigured;[append]deploy.confirm.confirm">
<ul style="font-size: 0.9em; width: 400px; margin: 10px auto; text-align: left;" id="node-dialog-confirm-deploy-invalid-list"></ul>
<div id="node-dialog-confirm-deploy-config" class="node-dialog-confirm-row" data-i18n="[prepend]deploy.confirm.improperlyConfigured;[append]deploy.confirm.confirm">
<ul id="node-dialog-confirm-deploy-invalid-list"></ul>
</div>
<div id="node-dialog-confirm-deploy-unknown" style="text-align: left; padding-top: 10px;" data-i18n="[prepend]deploy.confirm.unknown;[append]deploy.confirm.confirm">
<ul style="font-size: 0.9em; width: 400px; margin: 10px auto; text-align: left;" id="node-dialog-confirm-deploy-unknown-list"></ul>
<div id="node-dialog-confirm-deploy-unknown" class="node-dialog-confirm-row" data-i18n="[prepend]deploy.confirm.unknown;[append]deploy.confirm.confirm">
<ul id="node-dialog-confirm-deploy-unknown-list"></ul>
</div>
<div id="node-dialog-confirm-deploy-conflict" class="node-dialog-confirm-row">
<div style="margin-left: 40px; margin-bottom: 10px;">
<span data-i18n="deploy.confirm.conflict"></span>
</div>
<div id="node-dialog-confirm-deploy-conflict-checking" class="node-dialog-confirm-conflict-row">
<img src="red/images/spin.svg"/><div data-i18n="deploy.confirm.conflictChecking"></div>
</div>
<div id="node-dialog-confirm-deploy-conflict-auto-merge" class="node-dialog-confirm-conflict-row">
<i style="color: #3a3;" class="fa fa-check"></i><div data-i18n="deploy.confirm.conflictAutoMerge"></div>
</div>
<div id="node-dialog-confirm-deploy-conflict-manual-merge" class="node-dialog-confirm-conflict-row">
<i style="color: #999;" class="fa fa-exclamation"></i><div data-i18n="deploy.confirm.conflictManualMerge"></div>
</div>
</div>
</form>
</div>
@@ -151,10 +168,25 @@
<div class="form-row form-tips" id="subflow-dialog-user-count"></div>
</script>
<script type="text/x-red" data-template-name="_expression">
<div class="form-row node-text-editor-row">
<div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-expression"></div>
</div>
<div class="form-row">
<label for="node-input-expression-func" data-i18n="expressionEditor.functions"></label>
<select id="node-input-expression-func"></select>
<button id="node-input-expression-func-insert" class="editor-button" data-i18n="expressionEditor.insert"></button>
<div style="min-height: 200px;" id="node-input-expression-help"></div>
</div>
</script>
<script src="vendor/vendor.js"></script>
<script src="vendor/jsonata/jsonata.min.js"></script>
<script src="vendor/ace/ace.js"></script>
<script src="vendor/ace/ext-language_tools.js"></script>
<script src="{{ asset.red }}"></script>
<script src="{{ asset.main }}"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
ace.define("ace/mode/properties_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e=/\\u[0-9a-fA-F]{4}|\\/;this.$rules={start:[{token:"comment",regex:/[!#].*$/},{token:"keyword",regex:/[=:]$/},{token:"keyword",regex:/[=:]/,next:"value"},{token:"constant.language.escape",regex:e},{defaultToken:"variable"}],value:[{regex:/\\$/,token:"string",next:"value"},{regex:/$/,token:"string",next:"start"},{token:"constant.language.escape",regex:e},{defaultToken:"string"}]}};r.inherits(s,i),t.PropertiesHighlightRules=s}),ace.define("ace/mode/properties",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/properties_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./properties_highlight_rules").PropertiesHighlightRules,o=function(){this.HighlightRules=s};r.inherits(o,i),function(){this.$id="ace/mode/properties"}.call(o.prototype),t.Mode=o})
define("ace/mode/properties_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e=/\\u[0-9a-fA-F]{4}|\\/;this.$rules={start:[{token:"comment",regex:/[!#].*$/},{token:"keyword",regex:/[=:]$/},{token:"keyword",regex:/[=:]/,next:"value"},{token:"constant.language.escape",regex:e},{defaultToken:"variable"}],value:[{regex:/\\$/,token:"string",next:"value"},{regex:/$/,token:"string",next:"start"},{token:"constant.language.escape",regex:e},{defaultToken:"string"}]}};r.inherits(s,i),t.PropertiesHighlightRules=s}),define("ace/mode/properties",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/properties_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./properties_highlight_rules").PropertiesHighlightRules,o=function(){this.HighlightRules=s};r.inherits(o,i),function(){this.$id="ace/mode/properties"}.call(o.prototype),t.Mode=o})

View File

@@ -1 +1 @@
ace.define("ace/mode/sql_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e="select|insert|update|delete|from|where|and|or|group|by|order|limit|offset|having|as|case|when|else|end|type|left|right|join|on|outer|desc|asc|union|create|table|primary|key|if|foreign|not|references|default|null|inner|cross|natural|database|drop|grant",t="true|false",n="avg|count|first|last|max|min|sum|ucase|lcase|mid|len|round|rank|now|format|coalesce|ifnull|isnull|nvl",r="int|numeric|decimal|date|varchar|char|bigint|float|double|bit|binary|text|set|timestamp|money|real|number|integer",i=this.createKeywordMapper({"support.function":n,keyword:e,"constant.language":t,"storage.type":r},"identifier",!0);this.$rules={start:[{token:"comment",regex:"--.*$"},{token:"comment",start:"/\\*",end:"\\*/"},{token:"string",regex:'".*?"'},{token:"string",regex:"'.*?'"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:i,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+|\\-|\\/|\\/\\/|%|<@>|@>|<@|&|\\^|~|<|>|<=|=>|==|!=|<>|="},{token:"paren.lparen",regex:"[\\(]"},{token:"paren.rparen",regex:"[\\)]"},{token:"text",regex:"\\s+"}]},this.normalizeRules()};r.inherits(s,i),t.SqlHighlightRules=s}),ace.define("ace/mode/sql",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/sql_highlight_rules","ace/range"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./sql_highlight_rules").SqlHighlightRules,o=e("../range").Range,u=function(){this.HighlightRules=s};r.inherits(u,i),function(){this.lineCommentStart="--",this.$id="ace/mode/sql"}.call(u.prototype),t.Mode=u})
define("ace/mode/sql_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e="select|insert|update|delete|from|where|and|or|group|by|order|limit|offset|having|as|case|when|else|end|type|left|right|join|on|outer|desc|asc|union|create|table|primary|key|if|foreign|not|references|default|null|inner|cross|natural|database|drop|grant",t="true|false",n="avg|count|first|last|max|min|sum|ucase|lcase|mid|len|round|rank|now|format|coalesce|ifnull|isnull|nvl",r="int|numeric|decimal|date|varchar|char|bigint|float|double|bit|binary|text|set|timestamp|money|real|number|integer",i=this.createKeywordMapper({"support.function":n,keyword:e,"constant.language":t,"storage.type":r},"identifier",!0);this.$rules={start:[{token:"comment",regex:"--.*$"},{token:"comment",start:"/\\*",end:"\\*/"},{token:"string",regex:'".*?"'},{token:"string",regex:"'.*?'"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:i,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+|\\-|\\/|\\/\\/|%|<@>|@>|<@|&|\\^|~|<|>|<=|=>|==|!=|<>|="},{token:"paren.lparen",regex:"[\\(]"},{token:"paren.rparen",regex:"[\\)]"},{token:"text",regex:"\\s+"}]},this.normalizeRules()};r.inherits(s,i),t.SqlHighlightRules=s}),define("ace/mode/sql",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/sql_highlight_rules","ace/range"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./sql_highlight_rules").SqlHighlightRules,o=e("../range").Range,u=function(){this.HighlightRules=s};r.inherits(u,i),function(){this.lineCommentStart="--",this.$id="ace/mode/sql"}.call(u.prototype),t.Mode=u})

1
editor/vendor/ace/mode-swift.js vendored Executable file

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
ace.define("ace/mode/yaml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"list.markup",regex:/^(?:-{3}|\.{3})\s*(?=#|$)/},{token:"list.markup",regex:/^\s*[\-?](?:$|\s)/},{token:"constant",regex:"!![\\w//]+"},{token:"constant.language",regex:"[&\\*][a-zA-Z0-9-_]+"},{token:["meta.tag","keyword"],regex:/^(\s*\w.*?)(\:(?:\s+|$))/},{token:["meta.tag","keyword"],regex:/(\w+?)(\s*\:(?:\s+|$))/},{token:"keyword.operator",regex:"<<\\w*:\\w*"},{token:"keyword.operator",regex:"-\\s*(?=[{])"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"[|>][-+\\d\\s]*$",next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:/(\b|[+\-\.])[\d_]+(?:(?:\.[\d_]*)?(?:[eE][+\-]?[\d_]+)?)/},{token:"constant.numeric",regex:/[+\-]?\.inf\b|NaN\b|0x[\dA-Fa-f_]+|0b[10_]+/},{token:"constant.language.boolean",regex:"(?:true|false|TRUE|FALSE|True|False|yes|no)\\b"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"}],qqstring:[{token:"string",regex:"(?=(?:(?:\\\\.)|(?:[^:]))*?:)",next:"start"},{token:"string",regex:".+"}]}};r.inherits(s,i),t.YamlHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){"use strict";var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){return e.match(/^\s*/)[0]}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/folding/coffee",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=t.FoldMode=function(){};r.inherits(o,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=this.indentationBlock(e,n);if(r)return r;var i=/\S/,o=e.getLine(n),u=o.search(i);if(u==-1||o[u]!="#")return;var a=o.length,f=e.getLength(),l=n,c=n;while(++n<f){o=e.getLine(n);var h=o.search(i);if(h==-1)continue;if(o[h]!="#")break;c=n}if(c>l){var p=e.getLine(c).length;return new s(l,a,c,p)}},this.getFoldWidget=function(e,t,n){var r=e.getLine(n),i=r.search(/\S/),s=e.getLine(n+1),o=e.getLine(n-1),u=o.search(/\S/),a=s.search(/\S/);if(i==-1)return e.foldWidgets[n-1]=u!=-1&&u<a?"start":"","";if(u==-1){if(i==a&&r[i]=="#"&&s[i]=="#")return e.foldWidgets[n-1]="",e.foldWidgets[n+1]="","start"}else if(u==i&&r[i]=="#"&&o[i]=="#"&&e.getLine(n-2).search(/\S/)==-1)return e.foldWidgets[n-1]="start",e.foldWidgets[n+1]="","";return u!=-1&&u<i?e.foldWidgets[n-1]="start":e.foldWidgets[n-1]="",i<a?"start":""}}.call(o.prototype)}),ace.define("ace/mode/yaml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/yaml_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/coffee"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./yaml_highlight_rules").YamlHighlightRules,o=e("./matching_brace_outdent").MatchingBraceOutdent,u=e("./folding/coffee").FoldMode,a=function(){this.HighlightRules=s,this.$outdent=new o,this.foldingRules=new u};r.inherits(a,i),function(){this.lineCommentStart="#",this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t);if(e=="start"){var i=t.match(/^.*[\{\(\[]\s*$/);i&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.$id="ace/mode/yaml"}.call(a.prototype),t.Mode=a})
define("ace/mode/yaml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"list.markup",regex:/^(?:-{3}|\.{3})\s*(?=#|$)/},{token:"list.markup",regex:/^\s*[\-?](?:$|\s)/},{token:"constant",regex:"!![\\w//]+"},{token:"constant.language",regex:"[&\\*][a-zA-Z0-9-_]+"},{token:["meta.tag","keyword"],regex:/^(\s*\w.*?)(:(?:\s+|$))/},{token:["meta.tag","keyword"],regex:/(\w+?)(\s*:(?:\s+|$))/},{token:"keyword.operator",regex:"<<\\w*:\\w*"},{token:"keyword.operator",regex:"-\\s*(?=[{])"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"[|>][-+\\d\\s]*$",next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:/(\b|[+\-\.])[\d_]+(?:(?:\.[\d_]*)?(?:[eE][+\-]?[\d_]+)?)/},{token:"constant.numeric",regex:/[+\-]?\.inf\b|NaN\b|0x[\dA-Fa-f_]+|0b[10_]+/},{token:"constant.language.boolean",regex:"(?:true|false|TRUE|FALSE|True|False|yes|no)\\b"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"}],qqstring:[{token:"string",regex:"(?=(?:(?:\\\\.)|(?:[^:]))*?:)",next:"start"},{token:"string",regex:".+"}]}};r.inherits(s,i),t.YamlHighlightRules=s}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){"use strict";var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){return e.match(/^\s*/)[0]}}).call(i.prototype),t.MatchingBraceOutdent=i}),define("ace/mode/folding/coffee",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=t.FoldMode=function(){};r.inherits(o,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=this.indentationBlock(e,n);if(r)return r;var i=/\S/,o=e.getLine(n),u=o.search(i);if(u==-1||o[u]!="#")return;var a=o.length,f=e.getLength(),l=n,c=n;while(++n<f){o=e.getLine(n);var h=o.search(i);if(h==-1)continue;if(o[h]!="#")break;c=n}if(c>l){var p=e.getLine(c).length;return new s(l,a,c,p)}},this.getFoldWidget=function(e,t,n){var r=e.getLine(n),i=r.search(/\S/),s=e.getLine(n+1),o=e.getLine(n-1),u=o.search(/\S/),a=s.search(/\S/);if(i==-1)return e.foldWidgets[n-1]=u!=-1&&u<a?"start":"","";if(u==-1){if(i==a&&r[i]=="#"&&s[i]=="#")return e.foldWidgets[n-1]="",e.foldWidgets[n+1]="","start"}else if(u==i&&r[i]=="#"&&o[i]=="#"&&e.getLine(n-2).search(/\S/)==-1)return e.foldWidgets[n-1]="start",e.foldWidgets[n+1]="","";return u!=-1&&u<i?e.foldWidgets[n-1]="start":e.foldWidgets[n-1]="",i<a?"start":""}}.call(o.prototype)}),define("ace/mode/yaml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/yaml_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/coffee"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./yaml_highlight_rules").YamlHighlightRules,o=e("./matching_brace_outdent").MatchingBraceOutdent,u=e("./folding/coffee").FoldMode,a=function(){this.HighlightRules=s,this.$outdent=new o,this.foldingRules=new u};r.inherits(a,i),function(){this.lineCommentStart="#",this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t);if(e=="start"){var i=t.match(/^.*[\{\(\[]\s*$/);i&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.$id="ace/mode/yaml"}.call(a.prototype),t.Mode=a})

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
ace.define("ace/snippets/handlebars",["require","exports","module"],function(e,t,n){"use strict";t.snippetText=undefined,t.scope="handlebars"})
define("ace/snippets/handlebars",["require","exports","module"],function(e,t,n){"use strict";t.snippetText=undefined,t.scope="handlebars"})

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More