scms 1.7.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +0 -0
  3. data/assets/blank-app-template/application.xml +57 -0
  4. data/assets/blank-app-template/cert.p12 +0 -0
  5. data/assets/blank-app-template/config.yml +32 -0
  6. data/assets/blank-app-template/debug.cmd +6 -0
  7. data/assets/blank-app-template/package.cmd +16 -0
  8. data/assets/blank-app-template/public/ico/favicon.ico +0 -0
  9. data/assets/blank-app-template/public/ico/logo-128.png +0 -0
  10. data/assets/blank-app-template/public/ico/logo-16.png +0 -0
  11. data/assets/blank-app-template/public/ico/logo-32.png +0 -0
  12. data/assets/blank-app-template/public/ico/logo-48.png +0 -0
  13. data/assets/blank-app-template/public/images/glyphicons-halflings-white.png +0 -0
  14. data/assets/blank-app-template/public/images/glyphicons-halflings.png +0 -0
  15. data/assets/blank-app-template/public/robots.txt +4 -0
  16. data/assets/blank-app-template/public/scripts/air/AIRAliases.js +240 -0
  17. data/assets/blank-app-template/public/scripts/air/AIRIntrospector.js +1949 -0
  18. data/assets/blank-app-template/public/scripts/air/AIRMenuBuilder.js +1322 -0
  19. data/assets/blank-app-template/public/scripts/air/applicationupdater.swf +0 -0
  20. data/assets/blank-app-template/public/scripts/air/applicationupdater_ui.swf +0 -0
  21. data/assets/blank-app-template/public/scripts/air/servicemonitor.swf +0 -0
  22. data/assets/blank-app-template/public/scripts/libs/bootstrap.js +2027 -0
  23. data/assets/blank-app-template/public/scripts/libs/jquery-1.8.2.min.js +2 -0
  24. data/assets/blank-app-template/public/scripts/libs/jquery.fn.custom.js +67 -0
  25. data/assets/blank-app-template/public/scripts/libs/knockout-2.1.0-min.js +86 -0
  26. data/assets/blank-app-template/public/scripts/presenters/dashboard-presenter.js +3 -0
  27. data/assets/blank-app-template/public/scripts/presenters/global-presenter.js +8 -0
  28. data/assets/blank-app-template/public/scripts/shared/data-persistance.js +22 -0
  29. data/assets/blank-app-template/public/scripts/shared/utils.js +107 -0
  30. data/assets/blank-app-template/public/stylesheets/bootstrap-responsive.css +1058 -0
  31. data/assets/blank-app-template/public/stylesheets/bootstrap.css +5774 -0
  32. data/assets/blank-app-template/public/stylesheets/style.css +0 -0
  33. data/assets/blank-app-template/s3config.template.yml +9 -0
  34. data/assets/blank-app-template/templates/menu.xml +5 -0
  35. data/assets/blank-app-template/templates/skin.erb.html +84 -0
  36. data/assets/blank-app-template/tools/msxsl.exe +0 -0
  37. data/assets/blank-app-template/tools/update-descriptor.xsl +18 -0
  38. data/assets/blank-app-template/tools/version.xsl +10 -0
  39. data/assets/blank-app-template/views/about.html +15 -0
  40. data/assets/blank-app-template/views/dashboard.html +7 -0
  41. data/assets/blank-template/config.yml +30 -0
  42. data/assets/blank-template/public/images/glyphicons-halflings-white.png +0 -0
  43. data/assets/blank-template/public/images/glyphicons-halflings.png +0 -0
  44. data/assets/blank-template/public/robots.txt +4 -0
  45. data/assets/blank-template/public/scripts/air-monkey-hook.js +63 -0
  46. data/assets/blank-template/public/scripts/bootstrap.js +2027 -0
  47. data/assets/blank-template/public/scripts/jquery-1.8.2.min.js +2 -0
  48. data/assets/blank-template/public/scripts/script.js +0 -0
  49. data/assets/blank-template/public/stylesheets/bootstrap-responsive.css +1058 -0
  50. data/assets/blank-template/public/stylesheets/bootstrap.css +5774 -0
  51. data/assets/blank-template/public/stylesheets/style.css +0 -0
  52. data/assets/blank-template/s3config.template.yml +10 -0
  53. data/assets/blank-template/templates/menu.xml +5 -0
  54. data/assets/blank-template/templates/skin.erb.html +108 -0
  55. data/assets/blank-template/views/about-intro.html +1 -0
  56. data/assets/blank-template/views/about-main.html +2 -0
  57. data/assets/blank-template/views/home-intro.html +3 -0
  58. data/assets/blank-template/views/home-main.html +15 -0
  59. data/assets/mime.types +68 -0
  60. data/bin/scms +127 -0
  61. data/lib/scms.rb +426 -0
  62. data/lib/scms/s3deploy.rb +45 -0
  63. data/lib/scms/scms_utils.rb +73 -0
  64. data/lib/scms/version.rb +3 -0
  65. data/scms.gemspec +24 -0
  66. data/scripts/build.bat +4 -0
  67. data/staticcms.sublime-project +8 -0
  68. data/staticcms.sublime-workspace +417 -0
  69. metadata +180 -0
@@ -0,0 +1,1322 @@
1
+ /* AIRMenuBuilder.js - Revision: 1.5 */
2
+
3
+ /*
4
+ ADOBE SYSTEMS INCORPORATED
5
+ Copyright 2007-2008 Adobe Systems Incorporated. All Rights Reserved.
6
+
7
+ NOTICE: Adobe permits you to modify and distribute this file only in accordance with
8
+ the terms of Adobe AIR SDK license agreement. You may have received this file from a
9
+ source other than Adobe. Nonetheless, you may modify or
10
+ distribute this file only in accordance with such agreement.
11
+ */
12
+
13
+ (function AIRMenuBuilder () {
14
+
15
+ function constructor ( ) {
16
+ window ['air'] = window ['air'] || {};
17
+ window.air['ui'] = window.air['ui'] || {};
18
+ window.air.ui['Menu'] = new Menu();
19
+ registry = new FieldsRegistry();
20
+ currentOS = runtime.flash.system.Capabilities.os;
21
+ }
22
+
23
+ var currentOS = null;
24
+ var registry = null;
25
+
26
+ var File = runtime.flash.filesystem.File;
27
+ var FileStream = runtime.flash.filesystem.FileStream;
28
+ var FileMode = runtime.flash.filesystem.FileMode;
29
+ var NativeMenu = runtime.flash.display.NativeMenu;
30
+ var NativeMenuItem = runtime.flash.display.NativeMenuItem;
31
+ var SELECT = runtime.flash.events.Event.SELECT;
32
+ var KEYBOARD = runtime.flash.ui.Keyboard;
33
+ var COMPLETE = runtime.flash.events.Event.COMPLETE;
34
+ var IO_ERROR = runtime.flash.events.IOErrorEvent.IO_ERROR;
35
+ var NativeApplication = runtime.flash.desktop.NativeApplication;
36
+ var NativeWindow = runtime.flash.display.NativeWindow;
37
+ var Loader = runtime.flash.display.Loader;
38
+ var URLRequest = runtime.flash.net.URLRequest;
39
+ var BitmapData = runtime.flash.display.BitmapData;
40
+
41
+ /**
42
+ * CLASS FieldsRegistry
43
+ * @class
44
+ * @private
45
+ */
46
+ function FieldsRegistry () {
47
+
48
+ this.proof = function (name, value) {
49
+ if (!validateName(name)) { return null };
50
+ switch (name) {
51
+ case FieldsRegistry.ENABLED:
52
+ case FieldsRegistry.ALT_KEY:
53
+ case FieldsRegistry.SHIFT_KEY:
54
+ case FieldsRegistry.CMD_KEY:
55
+ case FieldsRegistry.CTRL_KEY:
56
+ case FieldsRegistry.TOGGLED:
57
+ case FieldsRegistry.DEFAULT_KEY:
58
+ return (typeof value == 'boolean')?
59
+ value: (typeof value == 'string')?
60
+ (value.toLowerCase() == 'false')? false :
61
+ true : getDefault (name);
62
+ case FieldsRegistry.KEY_EQUIVALENT:
63
+ var d;
64
+ return (typeof value == 'string')?
65
+ (value.length == 1)? value :
66
+ getDefault (name) : getDefault (name);
67
+ case FieldsRegistry.LABEL:
68
+ return (typeof value == 'string')?
69
+ (value.length != 0)? value:
70
+ getDefault (name) : getDefault (name);
71
+ case FieldsRegistry.MNEMONIC_INDEX:
72
+ var n;
73
+ return (typeof value == 'number')?
74
+ value: (typeof value == 'string')?
75
+ (!isNaN ( n = parseInt(value) ))? n :
76
+ getDefault (name) : getDefault (name);
77
+ case FieldsRegistry.TYPE:
78
+ return (typeof value == 'string') ?
79
+ (validateType(value))? value :
80
+ getDefault (name) : getDefault (name);
81
+ case FieldsRegistry.ON_SELECT:
82
+ var f;
83
+ return (typeof value == 'function')?
84
+ value : (typeof value == 'string')?
85
+ (typeof (f = window[value]) == 'function')?
86
+ f : getDefault (name) : getDefault (name);
87
+ }
88
+ }
89
+
90
+ this.iterateFields = function (callback, scope) {
91
+ var f, n, fr = FieldsRegistry;
92
+ for (f in fr) {
93
+ n = fr [f] !== fr.prototype? fr [f] : null;
94
+ if (n && !validateType(n)) {
95
+ callback.call ( scope || window, n )
96
+ };
97
+ }
98
+ }
99
+
100
+ var validateType = function (type) {
101
+ return type == FieldsRegistry.REGULAR ||
102
+ type == FieldsRegistry.SEPARATOR ||
103
+ type == FieldsRegistry.CHECK;
104
+ }
105
+
106
+ var validateName = function (fieldName) {
107
+ for (var f in FieldsRegistry) {
108
+ if (FieldsRegistry[f] == fieldName) { return true };
109
+ }
110
+ return false;
111
+ }
112
+
113
+
114
+ var getDefault = function (fieldName) {
115
+ switch (fieldName) {
116
+ case FieldsRegistry.ALT_KEY:
117
+ case FieldsRegistry.SHIFT_KEY:
118
+ case FieldsRegistry.TOGGLED:
119
+ return false;
120
+ case FieldsRegistry.ENABLED:
121
+ case FieldsRegistry.DEFAULT_KEY:
122
+ return true;
123
+ case FieldsRegistry.KEY_EQUIVALENT:
124
+ case FieldsRegistry.ON_SELECT:
125
+ return null;
126
+ case FieldsRegistry.LABEL:
127
+ return ' ';
128
+ case FieldsRegistry.MNEMONIC_INDEX:
129
+ return -1;
130
+ case FieldsRegistry.TYPE:
131
+ return FieldsRegistry.REGULAR;
132
+ case FieldsRegistry.CMD_KEY:
133
+ case FieldsRegistry.CTRL_KEY:
134
+ default:
135
+ return null;
136
+ }
137
+ }
138
+
139
+ }
140
+ FieldsRegistry.ALT_KEY = 'altKey';
141
+ FieldsRegistry.CMD_KEY = 'cmdKey';
142
+ FieldsRegistry.CTRL_KEY = 'ctrlKey';
143
+ FieldsRegistry.ENABLED = 'enabled';
144
+ FieldsRegistry.KEY_EQUIVALENT = 'keyEquivalent';
145
+ FieldsRegistry.LABEL = 'label';
146
+ FieldsRegistry.MNEMONIC_INDEX = 'mnemonicIndex';
147
+ FieldsRegistry.SHIFT_KEY = 'shiftKey';
148
+ FieldsRegistry.TOGGLED = 'toggled';
149
+ FieldsRegistry.TYPE = 'type';
150
+ FieldsRegistry.ON_SELECT = 'onSelect';
151
+ FieldsRegistry.DEFAULT_KEY = 'defaultKeyEquivalentModifiers';
152
+ FieldsRegistry.SEPARATOR = 'separator';
153
+ FieldsRegistry.CHECK = 'check';
154
+ FieldsRegistry.REGULAR = 'regular';
155
+
156
+ /**
157
+ * CLASS Menu
158
+ * Description
159
+ * Loads a user menu defined as XML or JSON, and sets it as one of the
160
+ * supported menu types.
161
+ * @class
162
+ * @author ciacob
163
+ */
164
+ function Menu() {
165
+
166
+ var buildMenu = function (source, type) {
167
+ var b = new Builder();
168
+ b.loadData (source, type);
169
+ return b.build();
170
+ }
171
+
172
+ var attachMenu = function (menu, type, target, icons) {
173
+ var s = new Shell();
174
+ s.link(menu, type, target, icons);
175
+ }
176
+
177
+ /**
178
+ * Load a menu defined in XML format.
179
+ * @param source
180
+ * An object containing XML menu(s) to be loaded for various OS-es.
181
+ * @return
182
+ * A NativeMenu object built from the given XML source.
183
+ */
184
+ this.createFromXML = function ( source ) {
185
+ return buildMenu ( source, Builder.XML );
186
+ }
187
+
188
+ /**
189
+ * Same as air.ui.Menu.fromXML, except it handles JSON data.
190
+ */
191
+ this.createFromJSON = function ( source ) {
192
+ return buildMenu ( source, Builder.JSON );
193
+ }
194
+
195
+ /**
196
+ * - on Windows: sets the given nativeMenu object as the NativeWindow's
197
+ * menu;
198
+ * - on Mac: inserts the items of the given nativeMenu object between
199
+ * the 'Edit' and 'Window' default menus;
200
+ * @param nativeMenu
201
+ * A NativeMenu returned by one of the air.ui.Menu.from...
202
+ * functions.
203
+ * @param overwrite
204
+ * A boolean that will change the behavior on Mac. If true, the
205
+ * default menus will be replaced entirely by the given nativeMenu
206
+ */
207
+ this.setAsMenu = function ( nativeMenu, overwrite ) {
208
+ if (!arguments.length) {
209
+ throw (new Error(
210
+ "No argument given for the 'setAsMenu()' method."
211
+ ));
212
+ }
213
+ var style = overwrite? Shell.MENU | Shell.OVERWRITE : Shell.MENU;
214
+ attachMenu (nativeMenu, style);
215
+ }
216
+
217
+ /**
218
+ * Displays the given menu as a contextual menu when the user right
219
+ * clicks a certain DOM element.
220
+ * @param nativeMenu
221
+ * A NativeMenu returned by one of the air.ui.Menu.from...
222
+ * functions.
223
+ * @param domElement
224
+ * The DOM Element to link with the given nativeMenu. The
225
+ * contextual menu will only show when the user right clicks over
226
+ * domElement. This attribute is optional. If missing, the context
227
+ * menu will display on every right-click over the application.
228
+ */
229
+ this.setAsContextMenu = function ( nativeMenu, domElement ) {
230
+ if (!arguments.length) {
231
+ throw (new Error(
232
+ "No argument given for the 'setAsContextMenu()' method."
233
+ ));
234
+ }
235
+ if (arguments.length < 2) { domElement = Shell.UNSPECIFIED };
236
+ attachMenu (nativeMenu, Shell.CONTEXT, domElement);
237
+ }
238
+
239
+ /**
240
+ * Sets the given nativeMenu as the
241
+ * ''NativeApplication.nativeApplication.icon.menu'' property.
242
+ * @param nativeMenu
243
+ * A NativeMenu returned by one of the air.ui.Menu.from...
244
+ * functions.
245
+ * @param icons
246
+ * An array holding icon file paths or bitmap data objects.
247
+ * If specified, these will be used as the application's
248
+ * tray/dock icons.
249
+ * @throws
250
+ * If no bitmap data was set for the ''icon'' object and no default
251
+ * icons are specified in the application descriptor.
252
+ */
253
+ this.setAsIconMenu = function ( nativeMenu, icons ) {
254
+ if (!arguments.length) {
255
+ throw (new Error(
256
+ "No argument given for the 'setAsIconMenu()' method."
257
+ ));
258
+ }
259
+ attachMenu (nativeMenu, Shell.ICON, null, icons);
260
+ }
261
+
262
+ }
263
+
264
+ /**
265
+ * CLASS DataSource
266
+ * @public
267
+ * @abstract
268
+ */
269
+ function DataSource() {
270
+ var _this = this;
271
+
272
+ var legalExtensions = ['xml', 'js'];
273
+
274
+ var rSeed = null;
275
+
276
+ var DATA_OBJECT = 1;
277
+ var INLINE_STRING = 2;
278
+ var FILE_PATH = 3;
279
+ var FILE_OBJECT = 4;
280
+ var ILLEGAL_TYPE = 5;
281
+
282
+ function getFileContent (file) {
283
+ var ret = '';
284
+ var fileStream = new FileStream();
285
+ fileStream.open(file, FileMode.READ);
286
+ try {
287
+ ret = fileStream.readUTFBytes(file.size);
288
+ } catch(e) {
289
+ throw(
290
+ new Error(["Error\n", "ID: ", e.errorID, "\n", "Message: ",
291
+ e.message, "\n"].join(''))
292
+ );
293
+ }
294
+ fileStream.close();
295
+ return ret;
296
+ }
297
+
298
+ function checkExtension (url, whiteList) {
299
+ var match = url.match(/\.([^\.]*)$/);
300
+ var extension = match? match[1] : null;
301
+ for(var i=0; i<whiteList.length; i++) {
302
+ if (whiteList[i] == extension) {
303
+ return true;
304
+ }
305
+ }
306
+ return false;
307
+ }
308
+
309
+ function sniffSource(src) {
310
+ if (typeof src == "object") {
311
+ if (src.constructor === (new File()).constructor) {
312
+ return FILE_OBJECT;
313
+ }
314
+ if (src.nodeType && src.nodeType == src.DOCUMENT_NODE) {
315
+ return DATA_OBJECT;
316
+ }
317
+ }
318
+ if (typeof src == "string") {
319
+ if (checkExtension(src, legalExtensions)) {
320
+ return FILE_PATH;
321
+ }
322
+ return INLINE_STRING;
323
+ }
324
+ return ILLEGAL_TYPE;
325
+ }
326
+
327
+ this.document = null;
328
+
329
+ this.type = null;
330
+
331
+ this.$DataSource = function(rawSource) {
332
+ if(rawSource) {
333
+ var srcType = sniffSource(rawSource);
334
+ if (srcType == ILLEGAL_TYPE) {
335
+ throw (new Error(['Could not instantiate DataSource class:',
336
+ 'An illegal data was provided. Legal types are:',
337
+ '- JavaScript Object',
338
+ '- Inline JSON or XML String',
339
+ '- *.XML or *.JS app root-relative file path',
340
+ '- flash.filesystem.File object, pointing to the above'
341
+ ].join('\n')));
342
+ }
343
+ var parsableCnt = _this.getParsableContent(rawSource, srcType);
344
+ if (srcType != DATA_OBJECT) {
345
+ this.parseContent(parsableCnt);
346
+ } else {
347
+ this.document = parsableCnt;
348
+ }
349
+ } else {
350
+ throw (new Error(['Could not instantiate DataSource class:',
351
+ 'Data provided is null.'].join(' ')));
352
+ }
353
+ }
354
+
355
+ this.getParsableContent = function (rawSource, sourceType) {
356
+ var url = null;
357
+ switch (sourceType) {
358
+ case DATA_OBJECT:
359
+ case INLINE_STRING:
360
+ return rawSource;
361
+ case FILE_OBJECT:
362
+ url = rawSource.url;
363
+ case FILE_PATH:
364
+ if (!url) { url = rawSource };
365
+ var localFile = Shell.resolve(url);
366
+ if (!localFile.exists) {
367
+ throw (new Error([
368
+ 'Could not instantiate DataSource class.',
369
+ 'Could not resolve this path:', url
370
+ ].join('\n')));
371
+ return null;
372
+ }
373
+ var cnt = getFileContent(localFile);
374
+ return cnt;
375
+ }
376
+ }
377
+
378
+ this.generateUID = function() {
379
+ if (!rSeed) {
380
+ var r = Math.floor(Math.random() * 1e5);
381
+ rSeed = r;
382
+ return ['id', r].join('');
383
+ }
384
+ var add = Math.floor(Math.random() * 10) + 1;
385
+ rSeed += add;
386
+ return ['id', rSeed].join('');
387
+ }
388
+
389
+ this.getSummary = function (node) {
390
+ var ret = {};
391
+ var func = function (fieldName) {
392
+ ret[fieldName] = this.getProperty (node, fieldName);
393
+ }
394
+ registry.iterateFields (func, this);
395
+ return ret;
396
+ }
397
+
398
+ this.parseContent = function (content) {
399
+ // subclass must overwrite;
400
+ }
401
+
402
+ this.getRoot = function() {
403
+ // subclass must overwrite;
404
+ }
405
+
406
+ this.getChildren = function(node) {
407
+ // subclass must overwrite;
408
+ }
409
+
410
+ this.getNextSibling = function(node) {
411
+ // subclass must overwrite;
412
+ }
413
+
414
+ this.getParent = function(node) {
415
+ // subclass must overwrite;
416
+ }
417
+
418
+ this.hasChildren = function(node) {
419
+ // subclass must overwrite;
420
+ }
421
+
422
+ this.addChildAt = function(node, newChild, index) {
423
+ // subclass must overwrite;
424
+ }
425
+
426
+ this.removeChildAt = function(node, index) {
427
+ // subclass must overwrite;
428
+ }
429
+
430
+ this.createNode = function(node, index) {
431
+ // subclass must overwrite;
432
+ }
433
+
434
+ this.getProperty = function(node, propName) {
435
+ // subclass must overwrite;
436
+ }
437
+
438
+ this.setProperty = function(node, propName, propValue) {
439
+ // subclass must overwrite;
440
+ }
441
+ }
442
+
443
+ /**
444
+ * CLASS XMLDataSource inherits DataSource
445
+ * @private
446
+ * @class
447
+ */
448
+ function XMLDataSource() {
449
+
450
+ this.__proto__ = new DataSource();
451
+
452
+ this.$XMLDataSource = function (rawSource) {
453
+ this.__proto__.$DataSource.call (this.__proto__, rawSource);
454
+ that.type = Builder.XML;
455
+ }
456
+
457
+ var that = this.__proto__;
458
+
459
+ that.parseContent = function (content) {
460
+ if (content) {
461
+ var p = new DOMParser();
462
+ var doc = p.parseFromString(content, "text/xml");
463
+ var err = 'parsererror';
464
+ var r = doc.documentElement;
465
+ var isError = (r.nodeName == err) ||
466
+ (doc.getElementsByTagName(err).length > 0);
467
+ if (isError) {
468
+ var errText = doc.getElementsByTagName(err)[0].innerText;
469
+ var msg = errText.split(':');
470
+ msg.length -= 1;
471
+ msg = msg.join(':\n');
472
+ throw (new Error ([
473
+ 'Could not parse data: malformed XML file.', msg
474
+ ].join('\n')));
475
+ }
476
+ that.document = doc;
477
+ }
478
+ }
479
+
480
+ that.getRoot = function() {
481
+ return that.document.documentElement;
482
+ }
483
+
484
+ that.getChildren = function (node) {
485
+ var ret = [];
486
+ if(node) {
487
+ if(node.hasChildNodes && node.hasChildNodes()){
488
+ var children = node.childNodes;
489
+ for(var i=0; i<children.length; i++) {
490
+ var child = children.item(i);
491
+ if(child.nodeType == child.ELEMENT_NODE) {
492
+ if (that.getProperty (child, 'id') == null) {
493
+ that.setProperty (child, 'id',
494
+ that.generateUID());
495
+ }
496
+ ret.push(child);
497
+ }
498
+ }
499
+ }
500
+ }
501
+ return ret;
502
+ }
503
+
504
+ that.getNextSibling = function (node) {
505
+ if(node) {
506
+ var checkIfLegalType = function(el) {
507
+ return (el.nodeType == el.ELEMENT_NODE);
508
+ }
509
+ var isLegalType = checkIfLegalType(node);
510
+ if(isLegalType) {
511
+ var testNode = node;
512
+ while(testNode = testNode.nextSibling) {
513
+ var isNextLegal = checkIfLegalType(testNode);
514
+ if(isNextLegal) { return testNode };
515
+ }
516
+ }
517
+ }
518
+ return null;
519
+ }
520
+
521
+ that.getParent = function (node) {
522
+ if(node) {
523
+ var isLegalType = (node.nodeType == node.ELEMENT_NODE);
524
+ if(isLegalType) {
525
+ if (node === that.getRoot()) { return null };
526
+ // make it headless, to accommodate the JSON
527
+ if (node.parentNode === that.getRoot()) { return null };
528
+ return node.parentNode;
529
+ }
530
+ }
531
+ return null;
532
+ }
533
+
534
+ that.hasChildren = function (node) {
535
+ if (node && (node.nodeType == node.ELEMENT_NODE)) {
536
+ if(!node.hasChildNodes()) { return false };
537
+ var childElements = node.getElementsByTagName('*');
538
+ if (childElements.length) { return true };
539
+ }
540
+ return null;
541
+ }
542
+
543
+ that.addChildAt = function (node, newChild, index) {
544
+ if (node && newChild && (typeof index != "undefined")) {
545
+ var nodeIsLegal = node.nodeType &&
546
+ (node.nodeType == node.ELEMENT_NODE);
547
+ var newIsLegal = newChild.nodeType &&
548
+ (newChild.nodeType == newChild.ELEMENT_NODE);
549
+ var indexIsLegal = !isNaN(parseInt(index));
550
+ if (nodeIsLegal && newIsLegal && indexIsLegal) {
551
+ var children = that.getChildren(node);
552
+ index = Math.min(Math.max(0, index), children.length);
553
+ var refNode = children [index+1] || null;
554
+ var success = false;
555
+ try {
556
+ node.insertBefore (newChild, refNode);
557
+ success = true;
558
+ } catch (e) {
559
+ throw ( new Error([
560
+ 'Could not add new child. A DOM error has occured:',
561
+ e.message
562
+ ].join('\n')) );
563
+ }
564
+ return success;
565
+ }
566
+ }
567
+ return null;
568
+ }
569
+
570
+ that.removeChildAt = function (node, index) {
571
+ if (node && (typeof index!= "undefined")) {
572
+ var nodeIsLegal = node.nodeType &&
573
+ (node.nodeType == node.ELEMENT_NODE);
574
+ var indexIsLegal = !isNaN(parseInt(index));
575
+ if (nodeIsLegal && indexIsLegal) {
576
+ var children = that.getChildren(node);
577
+ index = Math.min(Math.max(0, index), children.length-1);
578
+ try {
579
+ return node.removeChild (children[index]);
580
+ } catch (e) {
581
+ throw ( new Error([
582
+ 'Could not remove child. A DOM error has occured:',
583
+ e.message
584
+ ].join('\n')) );
585
+ }
586
+ }
587
+ }
588
+ return null;
589
+ }
590
+
591
+ that.createNode = function (properties) {
592
+ var node = that.document.createElement('menuItem');
593
+ for (var p in properties) {
594
+ that.setProperty (node, p, properties[p])
595
+ }
596
+ if (that.getProperty (node, 'id') == null) {
597
+ that.setProperty (node, 'id', that.generateUID());
598
+ }
599
+ return node;
600
+ }
601
+
602
+
603
+
604
+ that.getProperty = function (node, propName) {
605
+ if (node) {
606
+ var nodeIsLegal = node.nodeType &&
607
+ (node.nodeType == node.ELEMENT_NODE);
608
+ if (nodeIsLegal) {
609
+ return registry.proof(propName, node.getAttribute(propName));
610
+ }
611
+ }
612
+ return null;
613
+ }
614
+
615
+ that.setProperty = function (node, propName, propValue) {
616
+ if (node) {
617
+ var nodeIsLegal = node.nodeType &&
618
+ (node.nodeType == node.ELEMENT_NODE);
619
+ if (nodeIsLegal) {
620
+ var val = registry.proof(propName, propValue);
621
+ node.setAttribute(propName, val);
622
+ }
623
+ }
624
+ }
625
+
626
+ this.$XMLDataSource.apply (this, arguments);
627
+ }
628
+
629
+ /**
630
+ * CLASS JSONDataSource inherits DataSource
631
+ * @private
632
+ * @class
633
+ */
634
+ function JSONDataSource() {
635
+
636
+ this.__proto__ = new DataSource();
637
+
638
+ this.$JSONDataSource = function (rawSource) {
639
+ this.__proto__.$DataSource.call (this.__proto__, rawSource);
640
+ that.type = Builder.XML;
641
+ }
642
+
643
+ var that = this.__proto__;
644
+
645
+ that.parseContent = function (content) {
646
+ var doc = null;
647
+ if(content) {
648
+ try {
649
+ doc = eval(content);
650
+ this.document = doc;
651
+ } catch (e) {
652
+ var specificErr = null;
653
+ if (e instanceof ReferenceError) {
654
+ specificErr = [
655
+ 'Unknown reference given.',
656
+ 'Common mistakes include specifying non-global',
657
+ 'function names for the onSelect field.'].join('\n');
658
+ } else if (e instanceof SyntaxError) {
659
+ specificErr = "Your JSON string is malformed";
660
+ }
661
+ var err = [
662
+ e.message,
663
+ ['on line:', e.line].join(' ')
664
+ ];
665
+ if(specificErr) {
666
+ err.reverse();
667
+ err.push(specificErr);
668
+ err.reverse();
669
+ }
670
+ throw (new Error(err.join('\n')));
671
+ }
672
+ }
673
+ }
674
+
675
+ that.getRoot = function() {
676
+ return that.document;
677
+ }
678
+
679
+ that.getChildren = function (node) {
680
+ var ret = [];
681
+ if (node) {
682
+ var iterable = (node === that.getRoot())? node:
683
+ (node ['items'])? node ['items']: null;
684
+ if (iterable) {
685
+ var par = (node === that.getRoot())? null: node;
686
+ for (var i=0; i<iterable.length; i++) {
687
+ var child = iterable[i];
688
+ if (that.getProperty (child, 'id') == null) {
689
+ that.setProperty (child, 'id', that.generateUID())};
690
+ ret[i] = child;
691
+ child['parent'] = par;
692
+ if (i > 0) {
693
+ var prev = iterable[i-1];
694
+ prev['nextSibling'] = child;
695
+ }
696
+ }
697
+ }
698
+ }
699
+ return ret;
700
+ }
701
+
702
+ that.getNextSibling = function (node) {
703
+ if (node) {
704
+ if(node !== that.getRoot()) {
705
+ if (node['nextSibling']) { return node['nextSibling'] };
706
+ }
707
+ }
708
+ return null;
709
+ }
710
+
711
+ that.getParent = function (node) {
712
+ if (node) {
713
+ if(node !== that.getRoot()) {
714
+ if (node['parent']) { return node['parent'] };
715
+ }
716
+ }
717
+ return null;
718
+ }
719
+
720
+ that.hasChildren = function (node) {
721
+ if (node) {
722
+ var iterable = (node === that.getRoot())? node:
723
+ (node ['items'])? node ['items']: null;
724
+ if (iterable) {
725
+ return iterable.length && iterable.length > 0;
726
+ }
727
+ return false;
728
+ }
729
+ return false;
730
+ }
731
+
732
+ that.addChildAt = function (node, newChild, index) {
733
+ if (node && newChild) {
734
+ var children = that.getChildren (node) || (function() {
735
+ node['items'] = [];
736
+ return node['items'];
737
+ })();
738
+ index = Math.min(Math.max(0, index), children.length);
739
+ children.splice (index, 0, newChild);
740
+ if (index > 0) {
741
+ children [index-1]['nextSibling'] = children [index]
742
+ };
743
+ if (index < children.length-1) {
744
+ children[index]['nextSibling'] = children [index]+1
745
+ };
746
+ node['items'] = children;
747
+ }
748
+ }
749
+
750
+ that.removeChildAt = function (node, index) {
751
+ if (node) {
752
+ var children = that.getChildren (node) || (function() {
753
+ node['items'] = [];
754
+ return node['items'];
755
+ })();
756
+ index = Math.min(Math.max(0, index), children.length);
757
+ var removed = children [index];
758
+ children.splice (index, 1);
759
+ if(index > 0 && index < children.length) {
760
+ children [index-1]['nextSibling'] = children [index];
761
+ }
762
+ node['items'] = children;
763
+ return removed;
764
+ }
765
+ return null;
766
+ }
767
+
768
+ that.createNode = function (properties) {
769
+ var node = {};
770
+ for (var p in properties) {
771
+ that.setProperty (node, p, properties[p])
772
+ };
773
+ if (that.getProperty (node, 'id') == null) {
774
+ that.setProperty (node, 'id', that.generateUID());
775
+ }
776
+ return node;
777
+ }
778
+
779
+ that.getProperty = function (node, propName) {
780
+ if (node) { return registry.proof(propName, node[propName]) };
781
+ return null;
782
+ }
783
+
784
+ that.setProperty = function (node, propName, propValue) {
785
+ if (node) {
786
+ node[propName] = registry.proof(propName, propValue);
787
+ }
788
+ }
789
+
790
+ this.$JSONDataSource.apply (this, arguments);
791
+ }
792
+
793
+ /**
794
+ * CLASS Builder
795
+ * @private
796
+ * @class
797
+ */
798
+ function Builder() {
799
+
800
+ var ds, root = null;
801
+
802
+ function createDataSource (source, type) {
803
+ var ret = null;
804
+ if (type == Builder.XML) { ret = new XMLDataSource ( source ) };
805
+ if (type == Builder.JSON) { ret = new JSONDataSource( source )};
806
+ return ret;
807
+ }
808
+
809
+ function buildMenu() {
810
+ var w = new Walker(ds, buildItem);
811
+ w.walk ();
812
+ }
813
+
814
+ function buildItem (item) {
815
+
816
+ // Get & parse info about the item to be built:
817
+ var summary = ds.getSummary (item);
818
+ var isFirstLevel = (!ds.getParent(item));
819
+ var isItemDisabled = (!summary[FieldsRegistry.ENABLED]);
820
+ var hasChildren = ds.hasChildren(item);
821
+ var isItemSeparator = (summary [FieldsRegistry.TYPE] ==
822
+ FieldsRegistry.SEPARATOR);
823
+ var isItemAToggle = (summary [FieldsRegistry.TYPE] ==
824
+ FieldsRegistry.CHECK);
825
+
826
+ // Build the NativeMenuItem to represent this item:
827
+ var ret = parseLabelForMnemonic (summary [FieldsRegistry.LABEL]);
828
+ var nmi = new NativeMenuItem ( ret[0], isItemSeparator );
829
+
830
+
831
+ // Attach features for this item:
832
+ var parsedMnemonicIndex = ret[1];
833
+ if (parsedMnemonicIndex >= 0) {
834
+ summary [FieldsRegistry.MNEMONIC_INDEX] = parsedMnemonicIndex;
835
+ };
836
+ var mnemonicIndex = summary [FieldsRegistry.MNEMONIC_INDEX];
837
+ if (mnemonicIndex != -1) { nmi.mnemonicIndex = mnemonicIndex };
838
+ if (isItemAToggle) {
839
+ var toggler = function (event) {
840
+ var val = !ds.getProperty (item,
841
+ FieldsRegistry.TOGGLED);
842
+ ds.setProperty (item, FieldsRegistry.TOGGLED, val);
843
+ nmi.checked = val;
844
+ }
845
+ nmi.addEventListener (SELECT, toggler);
846
+ nmi.checked = summary [FieldsRegistry.TOGGLED];
847
+ }
848
+ if (summary [FieldsRegistry.ON_SELECT]) {
849
+ var f = function (event) {
850
+ var target = event.target;
851
+ summary [FieldsRegistry.ON_SELECT].call (
852
+ window, event, summary
853
+ );
854
+ }
855
+ nmi.addEventListener (SELECT, f);
856
+ }
857
+ attachKeyEquivalentHandler (nmi, summary);
858
+ if ( isItemDisabled ) { nmi.enabled = false };
859
+
860
+ // Attach our item within the menu structure:
861
+ item['_widget_'] = nmi;
862
+ if (hasChildren) { nmi.submenu = new NativeMenu() };
863
+ var data = nmi.data || (nmi.data = {});
864
+ data['item'] = item;
865
+ var parMnu = null;
866
+ var parItem = ds.getParent(item);
867
+ if (parItem) {
868
+ var parWidget = parItem['_widget_'];
869
+ parMnu = parWidget.submenu;
870
+ if (!parMnu) { return };
871
+ } else {
872
+ parMnu = root || ( root = new NativeMenu() );
873
+ }
874
+ parMnu.addItem(nmi);
875
+ }
876
+
877
+ function qReplace (tStr, searchStr , replaceStr) {
878
+ var index;
879
+ while ((index = tStr.indexOf (searchStr)) >= 0) {
880
+ var arr = tStr.split('');
881
+ arr.splice (index, searchStr.length,
882
+ replaceStr);
883
+ tStr = arr.join('');
884
+ }
885
+ return tStr;
886
+ }
887
+
888
+ function parseLabelForMnemonic (label) {
889
+ var l = label;
890
+ if (l) {
891
+ l = qReplace(l, '__', '[UNDERSCORE]');
892
+ l = qReplace(l, '_', '[MNEMONIC]');
893
+ l = qReplace(l, '[UNDERSCORE]', '_');
894
+ var mi = l.indexOf ('[MNEMONIC]');
895
+ l = qReplace(l, '[MNEMONIC]', '');
896
+ if (mi >= 0) { return [l, mi] };
897
+ }
898
+ return [l, -1];
899
+ }
900
+
901
+ function attachKeyEquivalentHandler (nativeItem, summary) {
902
+ if (summary[FieldsRegistry.DEFAULT_KEY]) {
903
+ // Linux implementation needs this check:
904
+ var def = nativeItem.keyEquivalentModifiers &&
905
+ nativeItem.keyEquivalentModifiers[0]?
906
+ nativeItem.keyEquivalentModifiers[0] : null;
907
+ if (def && typeof def != "undefined") {
908
+ if (summary[FieldsRegistry.CTRL_KEY] === false) {
909
+ if (def == KEYBOARD.CONTROL) { def = null };
910
+ }
911
+ if (summary[FieldsRegistry.CMD_KEY] === false) {
912
+ if (def == KEYBOARD.COMMAND) { def = null };
913
+ }
914
+ }
915
+ }
916
+ var key;
917
+ if (key = summary[FieldsRegistry.KEY_EQUIVALENT]) {
918
+ var mods = [];
919
+ if (def) { mods.push(def) };
920
+ if (summary[FieldsRegistry.CTRL_KEY]) {
921
+ mods.push (KEYBOARD.CONTROL);
922
+ }
923
+ if (summary[FieldsRegistry.CMD_KEY]) {
924
+ mods.push (KEYBOARD.COMMAND);
925
+ }
926
+ if (summary[FieldsRegistry.ALT_KEY]) {
927
+ mods.push (KEYBOARD.ALTERNATE);
928
+ }
929
+ key = (summary[FieldsRegistry.SHIFT_KEY])?
930
+ key.toUpperCase() : key.toLowerCase();
931
+ nativeItem.keyEquivalent = key;
932
+ nativeItem.keyEquivalentModifiers = mods;
933
+ }
934
+ }
935
+
936
+ this.loadData = function (source, type) {
937
+ if (source) { ds = createDataSource (source, type) }
938
+ else { throw new Error([
939
+ "Cannot create menu. ",
940
+ "Provided data source is null"
941
+ ].join('')) }
942
+ }
943
+
944
+ this.build = function() {
945
+ if(ds) {buildMenu()};
946
+ return root;
947
+ }
948
+ }
949
+ Builder.XML = 0x10;
950
+ Builder.JSON = 0x20;
951
+
952
+ /**
953
+ * CLASS NIConnector
954
+ * @private
955
+ * @class
956
+ */
957
+ function NIConnector () {
958
+
959
+ var that = this;
960
+
961
+ var LAST = 0x1;
962
+ var BEFORE_LAST = 0x2;
963
+
964
+ var ni;
965
+ var nativeMenu;
966
+ var overwrite;
967
+ var allSet;
968
+ var isMac;
969
+
970
+ function $NIConnector (oNi, oNewNativeMenu, bOverwriteExisting) {
971
+ if (oNi && oNewNativeMenu) {
972
+ allSet = true;
973
+ ni = oNi;
974
+ nativeMenu = oNewNativeMenu;
975
+ overwrite = bOverwriteExisting;
976
+ isMac = currentOS.indexOf('Mac') >= 0;
977
+ if (typeof NIConnector.defaultMenu == "undefined") {
978
+ var app = NativeApplication.nativeApplication;
979
+ NIConnector.defaultMenu = app.menu;
980
+ }
981
+ }
982
+ }
983
+
984
+
985
+ function isDefaultApplicationMenu () {
986
+ var app = NativeApplication.nativeApplication;
987
+ return (app.menu == NIConnector.defaultMenu);
988
+ }
989
+
990
+ function purge () {
991
+ while (ni.menu.numItems) { ni.menu.removeItemAt (0) }
992
+ }
993
+
994
+ function add ( style ) {
995
+ if (!ni.menu) {
996
+ replace();
997
+ return;
998
+ }
999
+ var addFunction = (style == LAST)?
1000
+ ni.menu.addItem : function (item) {
1001
+ ni.menu.addItemAt (item, ni.menu.numItems-1);
1002
+ }
1003
+ var item;
1004
+ while (nativeMenu.numItems && (item = nativeMenu.removeItemAt(0))) {
1005
+ if(isMac && !item.submenu) { continue };
1006
+ addFunction.call (that, item);
1007
+ }
1008
+ }
1009
+
1010
+ function replace () {
1011
+ ni.menu = nativeMenu;
1012
+ }
1013
+
1014
+ this.doConnect = function () {
1015
+ if (allSet) {
1016
+ if (overwrite) {
1017
+ if (isMac) {
1018
+ purge ();
1019
+ add (LAST);
1020
+ }
1021
+ else { replace() };
1022
+ }
1023
+ else {
1024
+ if (isMac) {
1025
+ if (isDefaultApplicationMenu()) { add (BEFORE_LAST) }
1026
+ else { add (LAST) };
1027
+ } else { add (LAST) };
1028
+ }
1029
+ }
1030
+ }
1031
+
1032
+ $NIConnector.apply (this, arguments);
1033
+ }
1034
+ NIConnector.defaultMenu;
1035
+
1036
+
1037
+ /**
1038
+ * CLASS Shell
1039
+ * @private
1040
+ * @class
1041
+ */
1042
+ function Shell() {
1043
+
1044
+ function $Shell(){}
1045
+
1046
+ var that = this;
1047
+
1048
+ var CONTEXT_MENU = 'contextmenu';
1049
+ var app = NativeApplication.nativeApplication;
1050
+
1051
+ var uidSeed = 0;
1052
+ var DEFAULT_ID = "DEFAULT_ID";
1053
+
1054
+ var isMac = currentOS.indexOf('Mac') >= 0;
1055
+
1056
+ var isBitmapData = function(obj) {
1057
+ return obj &&
1058
+ obj.constructor &&
1059
+ obj.constructor === (new BitmapData (1, 1));
1060
+ }
1061
+
1062
+ var resolveDomEl = function (obj) {
1063
+ var ret = null;
1064
+ if (obj) {
1065
+ if (typeof obj == 'object' && obj.nodeType == 1) { ret = obj };
1066
+ if (typeof obj == 'string') {
1067
+ var el;
1068
+ if (el = document.getElementById(obj)) { ret = el };
1069
+ }
1070
+ }
1071
+ return ret;
1072
+ }
1073
+
1074
+ var checkUserIcon = function (obj) {
1075
+ var icon = app.icon;
1076
+ return icon.bitmaps.length > 0;
1077
+ }
1078
+
1079
+ var getIcons = function (userIcons) {
1080
+ var ret = [];
1081
+ var entries = [];
1082
+ if (userIcons && userIcons.length) {
1083
+ entries = userIcons;
1084
+ } else {
1085
+ var p = new DOMParser();
1086
+ var descr = String(app.applicationDescriptor);
1087
+ var descrDoc = p.parseFromString(descr, "text/xml");
1088
+ var appEl = descrDoc.getElementsByTagName('application')[0];
1089
+ var iconEl = appEl.getElementsByTagName('icon')[0];
1090
+ if (iconEl) {
1091
+ var iconEntries = iconEl.getElementsByTagName('*');
1092
+ for (var i=0; i<iconEntries.length; i++) {
1093
+ if (iconEntries[i].firstChild) {
1094
+ var path = iconEntries[i].firstChild.nodeValue;
1095
+ entries.push (path);
1096
+ }
1097
+ }
1098
+ }
1099
+ }
1100
+ for (var i=0; i<entries.length; i++) {
1101
+ var entry = entries[i];
1102
+ if (isBitmapData(entry)) {
1103
+ ret.push (entry)
1104
+ } else {
1105
+ var file = Shell.resolve(entry);
1106
+ if (!file.exists) {
1107
+ throw (new Error([
1108
+ 'Could not set icon(s) for the iconMenu.',
1109
+ 'Could not resolve this path:', file.url
1110
+ ].join('\n')));
1111
+ };
1112
+ ret.push (file);
1113
+ }
1114
+ }
1115
+ return ret;
1116
+ }
1117
+
1118
+ var loadDefaultBitmaps = function (icons, callback) {
1119
+ var bmpDataObjects = [];
1120
+ var completeHandler = function (event){
1121
+ var bitmap = event.target.loader.content;
1122
+ bmpDataObjects.push(bitmap.bitmapData);
1123
+ loadNext();
1124
+ }
1125
+ var ioErrorHandler = function(event){};
1126
+ var loadNext = function(){
1127
+ var icon = icons.pop();
1128
+ if (icon) {
1129
+ if (icon.url) {
1130
+ var iconURL = icon.url;
1131
+ var request = new URLRequest(iconURL);
1132
+ loader.load(request);
1133
+ } else { bmpDataObjects.push(icon) };
1134
+ } else {
1135
+ if (typeof callback == 'function') {
1136
+ callback.call(this, bmpDataObjects);
1137
+ }
1138
+ }
1139
+ }
1140
+ var loader = new Loader();
1141
+ loader.contentLoaderInfo.addEventListener(COMPLETE,completeHandler);
1142
+ loader.contentLoaderInfo.addEventListener(IO_ERROR,ioErrorHandler);
1143
+ loadNext();
1144
+ }
1145
+
1146
+ var setBitmaps = function (bitmaps) {
1147
+ var icon = app.icon;
1148
+ icon.bitmaps = bitmaps;
1149
+ }
1150
+
1151
+ var linkMenu = function (menu, doOverwrite) {
1152
+ var target = NativeWindow.supportsMenu? window.nativeWindow:
1153
+ NativeApplication.supportsMenu?
1154
+ NativeApplication.nativeApplication:
1155
+ null;
1156
+ var nic = new NIConnector(target, menu, doOverwrite);
1157
+ return nic.doConnect();
1158
+ }
1159
+
1160
+ var generateUID = function () { return ['el', ++uidSeed].join('_') };
1161
+
1162
+ var linkContextMenu = function (menu, domEl) {
1163
+ var stage = window.htmlLoader.stage;
1164
+ var listener = function (e) {
1165
+ if (e.returnValue && menu) { menu.display(stage, e.x, e.y)};
1166
+ e.preventDefault();
1167
+ e.stopPropagation();
1168
+ }
1169
+ var target = (domEl == Shell.UNSPECIFIED)? window :
1170
+ resolveDomEl(domEl);
1171
+ if (!target) {
1172
+ throw (new Error ([
1173
+ "Cannot set contextual menu.",
1174
+ "The DOM element that you specified was not found."
1175
+ ].join('\n')));
1176
+ }
1177
+ target.addEventListener (CONTEXT_MENU, listener, false);
1178
+ }
1179
+
1180
+ var linkIconMenu = function (menu, userIcons) {
1181
+ var haveCustomIcons = (typeof userIcons != "undefined" &&
1182
+ userIcons && userIcons.length);
1183
+ var haveIcon = checkUserIcon();
1184
+ if (!haveCustomIcons && haveIcon) { app.icon.menu = menu }
1185
+ else {
1186
+ var defaultIcons = getIcons (userIcons);
1187
+ var haveDefaultIcons = defaultIcons.length > 0;
1188
+ if (!haveDefaultIcons) {
1189
+ if (!isMac) {
1190
+ throw (new Error([
1191
+ "Cannot set the icon menu.",
1192
+ "On operating systems that do not provide a default",
1193
+ "tray icon, you must specify one before calling",
1194
+ "setAsIconMenu().",
1195
+ "Alternativelly, you can specify default icons in the",
1196
+ "application's XML descriptor."
1197
+ ].join('\n')));
1198
+ }
1199
+ }
1200
+ var doAttach = function(bitmaps){
1201
+ setBitmaps (bitmaps);
1202
+ app.icon.menu = menu;
1203
+ }
1204
+ if (defaultIcons) {
1205
+ loadDefaultBitmaps(defaultIcons, doAttach);
1206
+ }
1207
+ }
1208
+ }
1209
+
1210
+ this.link = function (oMenu, style, target, icons) {
1211
+ if (Shell.MENU & style) {
1212
+ var bOverwrite = style & Shell.OVERWRITE;
1213
+ return linkMenu(oMenu, bOverwrite);
1214
+ }
1215
+ if (Shell.CONTEXT & style) {return linkContextMenu(oMenu, target)};
1216
+ if (Shell.ICON & style) { return linkIconMenu(oMenu, icons) };
1217
+ }
1218
+
1219
+ $Shell.apply (this, arguments);
1220
+ }
1221
+ Shell.UNSPECIFIED = -1;
1222
+ Shell.MENU = 1;
1223
+ Shell.CONTEXT = 2;
1224
+ Shell.ICON = 4;
1225
+ Shell.OVERWRITE = 8;
1226
+
1227
+ Shell.resolve = function (pathOrFile) {
1228
+ var file = null;
1229
+ try {
1230
+ file = File(pathOrFile);
1231
+ } catch(e) {
1232
+ file = File.applicationDirectory.resolvePath (pathOrFile);
1233
+ if (!file.exists) {
1234
+ try {
1235
+ file = new File (pathOrFile);
1236
+ } catch(e) {
1237
+ // must be a path, both 'relative' AND 'non-existing'.
1238
+ }
1239
+ }
1240
+ }
1241
+ return file;
1242
+ }
1243
+
1244
+ /**
1245
+ * CLASS Walker
1246
+ * @class
1247
+ * @private
1248
+ */
1249
+ function Walker() {
1250
+ var t, c, currentItem, allSet, item;
1251
+
1252
+ function $Walker (target, callback) {
1253
+ if (target && target instanceof DataSource) {
1254
+ t = target;
1255
+ }
1256
+ if (callback && typeof callback == "function") {
1257
+ c = callback;
1258
+ }
1259
+ if (t && c) { allSet = true };
1260
+ }
1261
+
1262
+ function getNearestAncestorSibling(node) {
1263
+ while (node) {
1264
+ node = t.getParent(node);
1265
+ if(node) {
1266
+ var s = t.getNextSibling(node);
1267
+ if (s) { return s };
1268
+ }
1269
+ }
1270
+ return null;
1271
+ }
1272
+
1273
+ function getFirstChildOfRoot() {
1274
+ return t.getChildren(t.getRoot())[0] || null;
1275
+ }
1276
+
1277
+ function doTraverse() {
1278
+ if (allSet) {
1279
+ while (item = getNext()) { c.call (window, item) };
1280
+
1281
+ } else {
1282
+ throw (new Error([
1283
+ 'Cannot traverse data tree.',
1284
+ 'Please check the arguments you provided to the Walker class.',
1285
+ ].join('\n')));
1286
+ }
1287
+ }
1288
+
1289
+ function getNext() {
1290
+ if (currentItem === null) { return null };
1291
+
1292
+ if (typeof currentItem == 'undefined') {
1293
+ currentItem = getFirstChildOfRoot();
1294
+ }
1295
+
1296
+ if (t.hasChildren(currentItem)) {
1297
+ var parentNode = currentItem;
1298
+ currentItem = t.getChildren(currentItem)[0];
1299
+ return parentNode;
1300
+ }
1301
+
1302
+ if(t.getNextSibling(currentItem)) {
1303
+ var current = currentItem;
1304
+ currentItem = t.getNextSibling(currentItem);
1305
+ return current;
1306
+ }
1307
+
1308
+ var ci = currentItem;
1309
+ currentItem = getNearestAncestorSibling(currentItem);
1310
+ return ci;
1311
+ }
1312
+
1313
+ this.walk = function (callback) {
1314
+ doTraverse();
1315
+ if (typeof callback == "function") { callback.call (this) };
1316
+ }
1317
+
1318
+ $Walker.apply (this, arguments);
1319
+ }
1320
+
1321
+ constructor.apply (this, arguments);
1322
+ })();