Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Update orion.client

  • Loading branch information...
commit 2583a86b41dffdb2d42002b61bd8a24ec2eacdce 1 parent 9b960c6
Mark Macdonald authored

Showing 34 changed files with 1,142 additions and 224 deletions. Show diff stats Hide diff stats

  1. +47 4 lib/orion.client/bundles/org.eclipse.orion.client.core/web/css/ide.css
  2. +20 0 lib/orion.client/bundles/org.eclipse.orion.client.core/web/css/images.css
  3. +2 1  lib/orion.client/bundles/org.eclipse.orion.client.core/web/css/layout.css
  4. +7 7 lib/orion.client/bundles/org.eclipse.orion.client.core/web/css/theme.css
  5. +2 2 lib/orion.client/bundles/org.eclipse.orion.client.core/web/edit/edit.css
  6. +7 2 lib/orion.client/bundles/org.eclipse.orion.client.core/web/edit/setup.js
  7. +13 4 lib/orion.client/bundles/org.eclipse.orion.client.core/web/gcli/cli.js
  8. BIN  lib/orion.client/bundles/org.eclipse.orion.client.core/web/images/gear-white.png
  9. BIN  lib/orion.client/bundles/org.eclipse.orion.client.core/web/images/gear.png
  10. +48 4 lib/orion.client/bundles/org.eclipse.orion.client.core/web/js-tests/URL/testcase.js
  11. +1 1  lib/orion.client/bundles/org.eclipse.orion.client.core/web/js-tests/jsTestSuite.js
  12. +127 0 lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/Deferred.js
  13. +285 9 lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/URL-shim.js
  14. +4 2 lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/commands.js
  15. +3 0  lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/commonHTMLFragments.js
  16. +0 46 lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/editorCommands.js
  17. +96 0 lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/globalCommands.js
  18. +1 1  lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/outliner.js
  19. +10 2 lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/searchAndReplace/textSearcher.js
  20. +2 0  lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/sites/siteClient.js
  21. +28 6 lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/sites/sitesExplorer.js
  22. +14 1 lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/webui/dropdown.js
  23. +14 1 lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/webui/tooltip.js
  24. +4 5 lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/widgets/UserMenu.js
  25. +3 22 lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/widgets/themes/ThemeBuilder.js
  26. +319 0 lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/widgets/themes/editor/MiniThemeChooser.js
  27. +4 6 lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/widgets/themes/editor/ThemeData.js
  28. +18 38 lib/orion.client/bundles/org.eclipse.orion.client.core/web/plugins/filePlugin/fileImpl.js
  29. +18 38 lib/orion.client/bundles/org.eclipse.orion.client.core/web/plugins/filePlugin/webdavImpl.js
  30. +10 3 lib/orion.client/bundles/org.eclipse.orion.client.core/web/shell/shellPage.js
  31. +4 4 lib/orion.client/bundles/org.eclipse.orion.client.core/web/shell/shellPageFileService.js
  32. +0 2  lib/orion.client/bundles/org.eclipse.orion.client.editor/web/examples/textview/textStylerOptions.js
  33. +1 0  lib/orion.client/bundles/org.eclipse.orion.client.editor/web/orion/textview/rulers.css
  34. +30 13 lib/orion.client/bundles/org.eclipse.orion.client.editor/web/orion/textview/textView.js
51 lib/orion.client/bundles/org.eclipse.orion.client.core/web/css/ide.css
@@ -114,6 +114,7 @@ h2 {
114 114 color: #404040;
115 115 vertical-align: middle;
116 116 font-weight: normal;
  117 + color:silver;
117 118 }
118 119
119 120 .dismiss {
@@ -136,10 +137,12 @@ h2 {
136 137 margin-bottom: 8px;
137 138 font-weight: normal;
138 139 vertical-align: baseline;
  140 + color:silver;
139 141 }
140 142
141 143 .parameterInputurl {
142 144 width: 30em;
  145 + color:#333;
143 146 }
144 147
145 148 .parameterInputcheckbox {
@@ -149,6 +152,7 @@ h2 {
149 152 .parameterInputtextarea {
150 153 vertical-align: top;
151 154 width: 50em;
  155 + color:#333;
152 156 }
153 157
154 158 .parameterPopup {
@@ -394,14 +398,15 @@ h2 {
394 398 border-radius: 2px;
395 399 margin: 8px;
396 400 display: none;
397   - vertical-align:middle;
398   - font-size:11px;
  401 + vertical-align: middle;
  402 + font-size: 11px;
399 403 z-index: 50;
  404 + color: #999;
400 405 }
401 406
402 407 .slideParameters {
403   - border: 1px solid #808080;
404   - background-color: #d7d7d7;
  408 + border: 1px solid #555;
  409 + background-color: #555;
405 410 }
406 411
407 412 .slideContainerActive {
@@ -716,7 +721,17 @@ h2 {
716 721 }
717 722
718 723 input {
  724 + border-radius: 3px;
719 725 -moz-user-select: text;
  726 + text-indent: none;
  727 + text-indent: 0px;
  728 + text-shadow: none;
  729 + border: none;
  730 + border-radius: 2px;
  731 + color: #333;
  732 + font-size: 9pt;
  733 + padding: 2px;
  734 + margin-left: 5px;
720 735 }
721 736
722 737 .treeIterationCursor {
@@ -828,3 +843,31 @@ input {
828 843 .targetSelector{
829 844
830 845 }
  846 +
  847 +.setting-control {
  848 + display: inline-block;
  849 + width: 200px;
  850 + padding: 4px;
  851 + margin: 10px;
  852 + outline: none;
  853 + background-color: white;
  854 + border: 1px solid #CCC;
  855 + border-radius: 3px;
  856 + font-size: 12px;
  857 + color: #222;
  858 +}
  859 +
  860 +.settingsPanelLabel {
  861 + margin-top: 10px;
  862 + min-width: 145px;
  863 + text-transform: uppercase;
  864 + color: #B3ADAA;
  865 + display: inline-block;
  866 +}
  867 +
  868 +.settingsPanel{
  869 + position: relative;
  870 + float: right;
  871 + margin-right: 24px;
  872 + padding: 10px;
  873 +}
20 lib/orion.client/bundles/org.eclipse.orion.client.core/web/css/images.css
@@ -77,3 +77,23 @@
77 77 .core-sprite-stop{ background-position: 0 -685px; width: 16px; height: 16px; }
78 78 .core-sprite-stylesheet{ background-position: 0 -703px; width: 16px; height: 16px; }
79 79 .core-sprite-warning{ background-position: 0 -721px; width: 16px; height: 16px; }
  80 +
  81 +
  82 +.core-sprite-settings {
  83 + background: url(../images/gear.png) no-repeat top left;
  84 + vertical-align: middle;
  85 + display: inline-block;
  86 + margin-top: 4px;
  87 + height: 16px;
  88 + width: 16px;
  89 +}
  90 +
  91 +.core-sprite-settings-white {
  92 + background: url(../images/gear-white.png) no-repeat top left;
  93 + vertical-align: middle;
  94 + display: inline-block;
  95 + margin-top: 4px;
  96 + height: 16px;
  97 + width: 16px;
  98 +}
  99 +
3  lib/orion.client/bundles/org.eclipse.orion.client.core/web/css/layout.css
@@ -72,7 +72,8 @@ hard-coded numbers elsewhere.
72 72 .layoutBlock {
73 73 clear: both;
74 74 margin: 0;
75   - padding: 2px 8px;
  75 + /* padding: 2px 8px; */
  76 + padding: 4px 4px 2px 4px;
76 77 vertical-align: baseline;
77 78 }
78 79
14 lib/orion.client/bundles/org.eclipse.orion.client.core/web/css/theme.css
@@ -303,7 +303,7 @@ a.currentLocation:hover {
303 303 .dropdownMenu {
304 304 color: #222;
305 305 background-color: #fbfbfb;
306   - display: none;
  306 + visibility: hidden;
307 307 z-index: 150;
308 308 min-width: 120px;
309 309 position: absolute;
@@ -334,18 +334,18 @@ a.currentLocation:hover {
334 334 padding: 4px 0;
335 335 }
336 336
337   -.dropdownMenu > li:hover {
338   - text-decoration: none;
339   - background: #ffeecc;
340   -}
341   -
342 337 .dropdownMenu > li > *:focus {
343 338 outline: 1px dotted #aaa;
  339 + background: #f3f6fe;
  340 +}
  341 +
  342 +.dropdownMenu > li:hover {
  343 + text-decoration: none;
344 344 background: #ffeecc;
345 345 }
346 346
347 347 .dropdownMenuOpen {
348   - display: block;
  348 + visibility: visible;
349 349 }
350 350
351 351 .dropdownSeparator {
4 lib/orion.client/bundles/org.eclipse.orion.client.core/web/edit/edit.css
@@ -31,7 +31,7 @@
31 31 }
32 32
33 33 .findSlideoutButton {
34   - color: #222;
  34 + color: silver;
35 35 border: 1px solid transparent;
36 36 text-align: center;
37 37 vertical-align: top;
@@ -50,7 +50,7 @@
50 50 }
51 51
52 52 .findSlideoutMenu {
53   - color: #222;
  53 + color: silver;
54 54 background-color: transparent;
55 55 border: 1px solid transparent;
56 56 padding: 2px;
9 lib/orion.client/bundles/org.eclipse.orion.client.core/web/edit/setup.js
@@ -17,12 +17,12 @@ define(['i18n!orion/edit/nls/messages', 'require', 'dojo', 'orion/selection', 'o
17 17 'orion/problems', 'orion/editor/contentAssist', 'orion/editorCommands', 'orion/editor/editorFeatures', 'orion/editor/editor', 'orion/syntaxchecker',
18 18 'orion/textview/textView', 'orion/textview/textModel',
19 19 'orion/textview/projectionTextModel', 'orion/textview/keyBinding','orion/searchAndReplace/textSearcher',
20   - 'orion/edit/dispatcher', 'orion/contentTypes', 'orion/PageUtil', 'orion/highlight', "orion/i18nUtil", 'orion/edit/syntaxmodel',
  20 + 'orion/edit/dispatcher', 'orion/contentTypes', 'orion/PageUtil', 'orion/highlight', "orion/i18nUtil", 'orion/edit/syntaxmodel', 'orion/widgets/themes/editor/MiniThemeChooser',
21 21 'dojo/hash'],
22 22 function(messages, require, dojo, mSelection, mStatus, mProgress, mDialogs, mCommands, mFavorites,
23 23 mFileClient, mOperationsClient, mSearchClient, mGlobalCommands, mOutliner, mProblems, mContentAssist, mEditorCommands, mEditorFeatures, mEditor,
24 24 mSyntaxchecker, mTextView, mTextModel, mProjectionTextModel, mKeyBinding, mSearcher,
25   - mDispatcher, mContentTypes, PageUtil, Highlight, i18nUtil, SyntaxModelWirer) {
  25 + mDispatcher, mContentTypes, PageUtil, Highlight, i18nUtil, SyntaxModelWirer, mThemeChooser) {
26 26
27 27 var exports = exports || {};
28 28
@@ -139,6 +139,11 @@ exports.setUpEditor = function(serviceRegistry, preferences, isReadOnly){
139 139 this._contentType = contentTypeService.getFilenameContentType(this.getTitle());
140 140 name = this.getTitle();
141 141 }
  142 +
  143 + var chooser = new mThemeChooser.MiniThemeChooser( preferences, editor.getTextView() );
  144 +
  145 + mGlobalCommands.addSettings( chooser );
  146 +
142 147 mGlobalCommands.setPageTarget({task: "Coding", name: name, target: metadata,
143 148 isFavoriteTarget: true, makeAlternate: function() {
144 149 if (metadata.Parents && metadata.Parents.length > 0) {
17 lib/orion.client/bundles/org.eclipse.orion.client.core/web/gcli/cli.js
@@ -1107,11 +1107,10 @@ Requisition.prototype.exec = function(input) {
1107 1107 if (reply != null && typeof reply.then === 'function') {
1108 1108 reply.then(
1109 1109 function(data) { output.complete(data); },
1110   - function(error) { output.error = true; output.complete(error); });
  1110 + function(error) { output.error = true; output.complete(error); },
  1111 + function(data) { output.progress(data); });
1111 1112
1112 1113 output.promise = reply;
1113   - // Add progress to our promise and add a handler for it here
1114   - // See bug 659300
1115 1114 }
1116 1115 else {
1117 1116 output.complete(reply);
@@ -1629,7 +1628,7 @@ function Output(options) {
1629 1628 }
1630 1629
1631 1630 /**
1632   - * Called when there is data to display
  1631 + * Called when there is data to display and the data completes execution of the command.
1633 1632 * @param data
1634 1633 */
1635 1634 Output.prototype.complete = function(data) {
@@ -1643,6 +1642,16 @@ Output.prototype.complete = function(data) {
1643 1642 };
1644 1643
1645 1644 /**
  1645 + * Called when there is data to display.
  1646 + * @param data The data up to this point.
  1647 + */
  1648 +Output.prototype.progress = function(data) {
  1649 + this.data = data;
  1650 +
  1651 + this.onChange({ output: this });
  1652 +};
  1653 +
  1654 +/**
1646 1655 * Convert to a DOM element for display.
1647 1656 * @param element The DOM node to which the data should be written. Existing
1648 1657 * content of 'element' will be removed before 'outputData' is added.
BIN  lib/orion.client/bundles/org.eclipse.orion.client.core/web/images/gear-white.png
BIN  lib/orion.client/bundles/org.eclipse.orion.client.core/web/images/gear.png
52 lib/orion.client/bundles/org.eclipse.orion.client.core/web/js-tests/URL/testcase.js
@@ -13,7 +13,7 @@
13 13
14 14 define(["orion/assert", "orion/URL-shim", "domReady!"], function(assert) {
15 15 var tests = {};
16   -
  16 +
17 17 tests.testSpecificationURL = function() {
18 18 var spec = "http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html";
19 19 var url = new URL(spec);
@@ -27,7 +27,7 @@ define(["orion/assert", "orion/URL-shim", "domReady!"], function(assert) {
27 27 assert.equal(url.search, "");
28 28 assert.equal(url.hash, "");
29 29 };
30   -
  30 +
31 31 tests.testExampleURL = function() {
32 32 var spec = "http://www.example.com/a/b/c.html?p=q&r=s&p&p=t#hash";
33 33 var url = new URL(spec);
@@ -41,6 +41,50 @@ define(["orion/assert", "orion/URL-shim", "domReady!"], function(assert) {
41 41 assert.equal(url.search, "?p=q&r=s&p&p=t");
42 42 assert.equal(url.hash, "#hash");
43 43 };
44   -
  44 +
  45 + tests.testUsernamePasswordURL = function() {
  46 + var spec = "http://www.example.com/a/b/c.html?p=q&r=s&p&p=t#hash";
  47 + var url = new URL(spec);
  48 + url.username = "a name";
  49 + assert.equal(url.href, "http://a%20name@www.example.com/a/b/c.html?p=q&r=s&p&p=t#hash");
  50 + url.password = "a password";
  51 + assert.equal(url.href, "http://a%20name:a%20password@www.example.com/a/b/c.html?p=q&r=s&p&p=t#hash");
  52 + url.username = "";
  53 + assert.equal(url.href, "http://:a%20password@www.example.com/a/b/c.html?p=q&r=s&p&p=t#hash");
  54 + url.username = "a name";
  55 + url.password = "";
  56 + assert.equal(url.href, "http://a%20name@www.example.com/a/b/c.html?p=q&r=s&p&p=t#hash");
  57 + url.username = "";
  58 + assert.equal(url.href, spec);
  59 + };
  60 +
  61 + tests.testQuery = function() {
  62 + var spec = "http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html";
  63 + var url = new URL(spec);
  64 + assert.equal(url.search,"");
  65 + assert.equal(url.query.size,0);
  66 + url.search = "?a=1&b=2";
  67 + assert.equal(url.query.size,2);
  68 + assert.equal(url.query.get("a"), "1");
  69 + assert.equal(url.query.get("b"), "2");
  70 + url.query.set("b","3");
  71 + assert.equal(url.query.get("b"), "3");
  72 + assert.equal(url.search, "?a=1&b=3");
  73 + assert.equal(url.query.has("c"), false);
  74 + assert.equal(url.query.has("a"), true);
  75 + assert.equal(url.query.has("b"), true);
  76 + url.query.append("b","4");
  77 + url.query.append("c","5");
  78 + url.query.append("a param","a value");
  79 + url.query.set("empty");
  80 + url.query.append("b","6");
  81 + assert.equal(url.search, "?a=1&b=3&b=4&c=5&a%20param=a%20value&empty&b=6");
  82 + url.query['delete']("b");
  83 + assert.equal(url.search, "?a=1&c=5&a%20param=a%20value&empty");
  84 + url.query.clear();
  85 + assert.equal(url.search, "");
  86 +
  87 + };
  88 +
45 89 return tests;
46   -});
  90 +});
2  lib/orion.client/bundles/org.eclipse.orion.client.core/web/js-tests/jsTestSuite.js
@@ -110,7 +110,6 @@ OrionTestCase("textview", "/js-tests/textview/test.html");
110 110 OrionTestCase("contentAssist", "/js-tests/editor/contentAssist/test.html");
111 111 OrionTestCase("jsTemplateContentAssist", "/js-tests/jsTemplateContentAssist/test.html");
112 112 OrionTestCase("contentTypes", "/js-tests/contentTypes/test.html");
113   -OrionTestCase("commands", "/js-tests/commands/test.html");
114 113 OrionTestCase("extensionParsing", "/js-tests/extensionParsing/test.html");
115 114 OrionTestCase("xhr", "/js-tests/xhr/test.html");
116 115 OrionTestCase("config", "/js-tests/config/test.html");
@@ -119,6 +118,7 @@ OrionTestCase("setting", "/js-tests/settings/test.html");
119 118 OrionTestCase("esprima-content-assist", "/js-tests/esprima/esprimaJsContentAssistTests.html");
120 119 OrionTestCase("asyncStyler", "/js-tests/asyncStyler/test.html");
121 120 OrionTestCase("syntaxmodel", "/js-tests/syntaxmodel/test.html");
  121 +OrionTestCase("commands", "/js-tests/commands/test.html");
122 122
123 123 //OrionTestCase("searchRendering", "/js-tests/searchRendering/test.html");
124 124 //OrionUITestCase("textviewPerformance", "/js-tests/textview/test-performance.html");
127 lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/Deferred.js
@@ -69,6 +69,39 @@
69 69 };
70 70 }
71 71
  72 +
  73 + /**
  74 + * @name orion.Promise
  75 + * @class Interface representing an eventual value.
  76 + * @description Promise is an interface that represents an eventual value returned from the single completion of an operation.
  77 + *
  78 + * <p>For a concrete class that provides Promise-based APIs, see {@link orion.Deferred}.</p>
  79 + * @see orion.Deferred#promise
  80 + * @see orion.Deferred
  81 + */
  82 + /**
  83 + * @name then
  84 + * @methodOf orion.Promise.prototype
  85 + * @description Adds handlers to be called on fulfillment or progress of this promise.
  86 + * @param {Function} [onResolve] Called when this promise is resolved.
  87 + * @param {Function} [onReject] Called when this promise is rejected.
  88 + * @param {Function} [onProgress] May be called to report progress events on this promise.
  89 + * @returns {orion.Promise} A new promise that is fulfilled when the given onResolve or onReject callback is finished.
  90 + * The callback's return value gives the fulfillment value of the returned promise.
  91 + */
  92 +
  93 + /**
  94 + * @name orion.Deferred
  95 + * @borrows orion.Promise#then as #then
  96 + * @class Provides abstraction over asynchronous operations.
  97 + * @description Deferred provides abstraction over asynchronous operations.
  98 + *
  99 + * <p>Because Deferred implements the {@link orion.Promise} interface, a Deferred may be used anywhere a Promise is called for.
  100 + * However, in most such cases it is recommended to use the Deferred's {@link #promise} field instead, which exposes a read-only
  101 + * interface to callers.</p>
  102 + * @param {Function} [optOnCancel] Will be invoked if the Deferred is canceled. The <code>optOnCancel</code> function is invoked
  103 + * passing the reason the Deferred was canceled (or a new <code>Error</code> if no reason was provided).
  104 + */
72 105 function Deferred(optOnCancel) {
73 106 var result, state, head, tail, canceled = false,
74 107 _this = this;
@@ -108,6 +141,14 @@
108 141 return false;
109 142 }
110 143
  144 + /**
  145 + * Rejects this Deferred.
  146 + * @name reject
  147 + * @methodOf orion.Deferred.prototype
  148 + * @param {Object} error
  149 + * @param {Boolean} [strict]
  150 + * @returns {orion.Promise}
  151 + */
111 152 this.reject = function(error, strict) {
112 153 if (!checkFulfilled(strict)) {
113 154 state = "rejected"; //$NON-NLS-0$
@@ -119,6 +160,14 @@
119 160 return _this.promise;
120 161 };
121 162
  163 + /**
  164 + * Resolves this Deferred.
  165 + * @name resolve
  166 + * @methodOf orion.Deferred.prototype
  167 + * @param {Object} value
  168 + * @param {Boolean} [strict]
  169 + * @returns {orion.Promise}
  170 + */
122 171 this.resolve = function(value, strict) {
123 172 if (!checkFulfilled(strict)) {
124 173 state = "resolved"; //$NON-NLS-0$
@@ -130,6 +179,14 @@
130 179 return _this.promise;
131 180 };
132 181
  182 + /**
  183 + * Notifies listeners of progress on this Deferred.
  184 + * @name progress
  185 + * @methodOf orion.Deferred.prototype
  186 + * @param {Object} update The progress update.
  187 + * @param {Boolean} [strict]
  188 + * @returns {orion.Promise}
  189 + */
133 190 this.progress = function(update, strict) {
134 191 if (!checkFulfilled(strict)) {
135 192 var listener = head;
@@ -143,6 +200,13 @@
143 200 return _this.promise;
144 201 };
145 202
  203 + /**
  204 + * Cancels this Deferred.
  205 + * @name cancel
  206 + * @methodOf orion.Deferred.prototype
  207 + * @param {Object} reason The reason for canceling this Deferred.
  208 + * @param {Boolean} [strict]
  209 + */
146 210 this.cancel = function(reason, strict) {
147 211 if (!checkFulfilled(strict)) {
148 212 canceled = true;
@@ -187,22 +251,53 @@
187 251 return listener.deferred.promise;
188 252 };
189 253
  254 + /**
  255 + * Returns whether this Deferred was resolved.
  256 + * @name isResolved
  257 + * @methodOf orion.Deferred.prototype
  258 + * @returns {Boolean} <code>true</code> if this Deferred was resolved, otherwise <code>false</code>.
  259 + */
190 260 this.isResolved = function() {
191 261 return state === "resolved"; //$NON-NLS-0$
192 262 };
193 263
  264 + /**
  265 + * Returns whether this Deferred was rejected.
  266 + * @name isRejected
  267 + * @methodOf orion.Deferred.prototype
  268 + * @returns {Boolean} <code>true</code> if this Deferred was rejected, otherwise <code>false</code>.
  269 + */
194 270 this.isRejected = function() {
195 271 return state === "rejected"; //$NON-NLS-0$
196 272 };
197 273
  274 + /**
  275 + * Returns whether this Deferred was fulfilled. A Deferred is <dfn>fulfilled</dfn> iff it was rejected or resolved.
  276 + * Thus, calling this method is equivalent to checking <code>deferred.isResolved() || deferred.isRejected()</code>.
  277 + * @name isFulfilled
  278 + * @methodOf orion.Deferred.prototype
  279 + * @returns {Boolean} <code>true</code> if this Deferred was fulfilled, otherwise <code>false</code>.
  280 + */
198 281 this.isFulfilled = function() {
199 282 return !!state;
200 283 };
201 284
  285 + /**
  286 + * Returns whether this Deferred was canceled.
  287 + * @name isCanceled
  288 + * @methodOf orion.Deferred.prototype
  289 + * @returns {Boolean} <code>true</code> if this Deferred was canceled, otherwise <code>false</code>.
  290 + */
202 291 this.isCanceled = function() {
203 292 return canceled;
204 293 };
205 294
  295 + /**
  296 + * The read-only promise underlying this Deferred.
  297 + * @name promise
  298 + * @fieldOf orion.Deferred.prototype
  299 + * @type orion.Promise
  300 + */
206 301 this.promise = {
207 302 then: this.then,
208 303 cancel: this.cancel,
@@ -220,6 +315,24 @@
220 315 this.promise.state = this.state;
221 316 }
222 317
  318 + /**
  319 + * Takes multiple promises and returns a new promise that represents the outcome of all the promises.
  320 + * <p>When <code>all</code> is called with a single parameter, the returned promise has <dfn>eager</dfn> semantics,
  321 + * meaning if one of the input promises is rejected, the returned promise also rejects, without waiting for the
  322 + * rest of the promises to fulfill.</p>
  323 + *
  324 + * To obtain <dfn>lazy</dfn> semantics (meaning the returned promise waits for all input promises to fulfill), pass the
  325 + * optional parameter <code>optOnError</code>.
  326 + * @name all
  327 + * @methodOf orion.Deferred
  328 + * @static
  329 + * @param {orion.Promise[]} promises The promises.
  330 + * @param {Function} [optOnError] Handles a rejected input promise. When invoked, <code>optOnError</code> is passed the reason
  331 + * the input promise was rejected. The return value of this <code>optOnError</code> call serves as the value of the rejected promise.
  332 + * @returns {orion.Promise} A new promise. The returned promise is generally fulfilled to an <code>Array</code> whose elements
  333 + * give the fulfillment values of the input promises. However if an input promise is rejected and eager semantics is used, the
  334 + * returned promise will instead be fulfilled to a single error value.</p>
  335 + */
223 336 Deferred.all = function(promises, optOnError) {
224 337 var count = promises.length,
225 338 result = [],
@@ -263,6 +376,20 @@
263 376 return deferred.promise;
264 377 };
265 378
  379 + /**
  380 + * Applies callbacks to a promise or to a regular object.
  381 + * @name when
  382 + * @methodOf orion.Deferred
  383 + * @static
  384 + * @param {Object|orion.Promise} value Either a {@link orion.Promise}, or a normal value.
  385 + * @param {Function} onResolve Called when the <code>value</code> promise is resolved. If <code>value</code> is not a promise,
  386 + * this function is called immediately.
  387 + * @param {Function} onReject Called when the <code>value</code> promise is rejected. If <code>value</code> is not a promise,
  388 + * this function is never called.
  389 + * @param {Function} onProgress Called when the <code>value</code> promise provides a progress update. If <code>value</code> is
  390 + * not a promise, this function is never called.
  391 + * @returns {orion.Promise} A new promise.
  392 + */
266 393 Deferred.when = function(value, onResolve, onReject, onProgress) {
267 394 var promise, deferred;
268 395 if (value && typeof value.then === "function") { //$NON-NLS-0$
294 lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/URL-shim.js
@@ -10,13 +10,231 @@
10 10 * IBM Corporation - initial API and implementation
11 11 *******************************************************************************/
12 12 /*global document window*/
13   -// URL Shim -- see http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html
  13 +// URL Shim -- see http://http://url.spec.whatwg.org/ and http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html
14 14
15 15 (function() {
16 16 if (typeof window.URL === "function" && new window.URL("http://www.w3.org").protocol === "http:") {
17 17 return;
18 18 }
  19 +
  20 + var _USERNAME_PASSWORD_RE = /([^:]*):?(.*)/;
19 21
  22 + function _createMapIterator(entries, kind) {
  23 + var index = 0;
  24 + return {
  25 + next: function() {
  26 + if (index < entries.length) {
  27 + var entry = entries[index++];
  28 + switch (kind) {
  29 + case "keys":
  30 + return entry[0];
  31 + case "values":
  32 + return entry[1];
  33 + case "keys+values":
  34 + return [entry[0], entry[1]];
  35 + default:
  36 + throw new TypeError();
  37 + }
  38 + }
  39 + throw new Error("Stop Iteration");
  40 + }
  41 + };
  42 + }
  43 +
  44 + function _checkString(txt) {
  45 + if (typeof txt !== "string") {
  46 + throw new TypeError();
  47 + }
  48 + }
  49 +
  50 + function _checkValue(value) {
  51 + if (typeof value !== "string" && value !== null) {
  52 + if (typeof value === "undefined") {
  53 + value = null;
  54 + } else {
  55 + throw new TypeError();
  56 + }
  57 + }
  58 + return value;
  59 + }
  60 +
  61 + // See http://url.spec.whatwg.org/#interface-urlquery
  62 + function URLQuery() {
  63 + Object.defineProperty(this, "_entries", {
  64 + value: [] // array of [key,value]
  65 + });
  66 + Object.defineProperty(this, "_dirty", {
  67 + value: false,
  68 + writable: true
  69 + });
  70 + }
  71 +
  72 + Object.defineProperties(URLQuery.prototype, {
  73 + _parseSearch: {
  74 + value: function(search) {
  75 + this.clear();
  76 + this._dirty = false;
  77 + if (search) {
  78 + _checkString(search);
  79 + var pairs = search.slice(1).split("&");
  80 + for (var i = 0; i < pairs.length; i++) {
  81 + var pair = pairs[i];
  82 + var parsed = /([^=]*)(=?)(.*)/.exec(pair);
  83 + var name = decodeURIComponent(parsed[1] || "");
  84 + var hasEquals = !!parsed[2];
  85 + var value = hasEquals ? decodeURIComponent(parsed[3] || "") : null;
  86 + this.append(name, value);
  87 + }
  88 + }
  89 + }
  90 + },
  91 + _updateSearch: {
  92 + value: function(anchor) {
  93 + if (this._dirty) {
  94 + this._dirty = false;
  95 + if (this.size === 0) {
  96 + anchor.search = "";
  97 + } else {
  98 + anchor.search = "?" + this._entries.map(function(entry) {
  99 + var pair = encodeURIComponent(entry[0]);
  100 + if (entry[1] !== null) {
  101 + pair += "=" + encodeURIComponent(entry[1]);
  102 + }
  103 + return pair;
  104 + }).join("&");
  105 + }
  106 + }
  107 + }
  108 + },
  109 + get: {
  110 + value: function(key) {
  111 + _checkString(key);
  112 + var result;
  113 + this._entries.some(function(entry) {
  114 + if (entry[0] === key) {
  115 + result = entry[1];
  116 + return true;
  117 + }
  118 + });
  119 + return result;
  120 + },
  121 + enumerable: true
  122 + },
  123 + set: {
  124 + value: function(key, value) {
  125 + _checkString(key);
  126 + value = _checkValue(value);
  127 + var found = false;
  128 + this._dirty = true;
  129 + this._entries.some(function(entry) {
  130 + if (entry[0] === key) {
  131 + found = true;
  132 + entry[1] = value;
  133 + return true;
  134 + }
  135 + });
  136 + if (!found) {
  137 + this._entries.push([key, value]);
  138 + }
  139 + },
  140 + enumerable: true
  141 + },
  142 + has: {
  143 + value: function(key) {
  144 + _checkString(key);
  145 + var found = false;
  146 + this._entries.some(function(entry) {
  147 + if (entry[0] === key) {
  148 + found = true;
  149 + return true;
  150 + }
  151 + });
  152 + return found;
  153 + },
  154 + enumerable: true
  155 + },
  156 + 'delete': {
  157 + value: function(key) {
  158 + _checkString(key);
  159 + var found = false;
  160 + for (var i = this._entries.length - 1; i > -1; i--) {
  161 + var entry = this._entries[i];
  162 + if (entry[0] === key) {
  163 + this._dirty = true;
  164 + found = true;
  165 + this._entries.splice(i, 1);
  166 + }
  167 + }
  168 + return found;
  169 + },
  170 + enumerable: true
  171 + },
  172 + clear: {
  173 + value: function() {
  174 + if (this._entries.length !== 0) {
  175 + this._entries.length = 0;
  176 + this._dirty = true;
  177 + }
  178 + },
  179 + enumerable: true
  180 + },
  181 + forEach: {
  182 + value: function(callback, thisArg) {
  183 + var thisMap = this;
  184 + this._entries.forEach(function(entry) {
  185 + callback.call(thisArg, entry[1], entry[0], thisMap);
  186 + });
  187 + },
  188 + enumerable: true
  189 + },
  190 + keys: {
  191 + value: function() {
  192 + return _createMapIterator(this._entries, "keys");
  193 + },
  194 + enumerable: true
  195 + },
  196 + values: {
  197 + value: function() {
  198 + return _createMapIterator(this._entries, "values");
  199 + },
  200 + enumerable: true
  201 + },
  202 + items: {
  203 + value: function() {
  204 + return _createMapIterator(this._entries, "keys+values");
  205 + }
  206 + },
  207 + size: {
  208 + get: function() {
  209 + return this._entries.length;
  210 + },
  211 + enumerable: true
  212 + },
  213 + getAll: {
  214 + value: function(key) {
  215 + _checkString(key);
  216 + var result = [];
  217 + this._entries.forEach(function(entry) {
  218 + if (entry[0] === key) {
  219 + result.push(entry[1]);
  220 + }
  221 + });
  222 + return result;
  223 + },
  224 + enumerable: true
  225 + },
  226 + append: {
  227 + value: function(key, value) {
  228 + _checkString(key);
  229 + value = _checkValue(value);
  230 + this._entries.push([key, value]);
  231 + this._dirty = true;
  232 + },
  233 + enumerable: true
  234 + }
  235 + });
  236 +
  237 + // See http://url.spec.whatwg.org/#api
20 238 function URL(url, base) {
21 239 url = url || "";
22 240 if (typeof url !== "string") {
@@ -32,7 +250,7 @@
32 250 if (base) {
33 251 var baseAnchor = doc.createElement("a");
34 252 baseAnchor.href = base;
35   - if (baseAnchor.protocol.length < 2) {
  253 + if (baseAnchor.protocol.length < 2 || !baseAnchor.host) {
36 254 throw new Error("InvalidStateError");
37 255 }
38 256 var baseElement = doc.createElement("base");
@@ -46,21 +264,22 @@
46 264 Object.defineProperty(this, "_urlAnchor", {
47 265 value: urlAnchor
48 266 });
  267 + Object.defineProperty(this, "query", {
  268 + value: new URLQuery(urlAnchor.search),
  269 + enumerable: true
  270 + });
49 271 }
50 272
51 273 Object.defineProperties(URL.prototype, {
52   - toString: {
53   - value: function() {
54   - return this._urlAnchor.href;
55   - },
56   - enumerable: false
57   - },
58 274 href: {
59 275 get: function() {
  276 + this.query._updateSearch(this._urlAnchor);
60 277 return this._urlAnchor.href;
61 278 },
62 279 set: function(value) {
  280 + _checkString(value);
63 281 this._urlAnchor.href = value;
  282 + this.query._parseSearch(this._urlAnchor.search);
64 283 },
65 284 enumerable: true
66 285 },
@@ -78,15 +297,66 @@
78 297 return this._urlAnchor.protocol;
79 298 },
80 299 set: function(value) {
  300 + _checkString(value);
81 301 this._urlAnchor.protocol = value;
82 302 },
83 303 enumerable: true
84 304 },
  305 + _userinfo: { // note: not part of spec so not enumerable
  306 + get: function() {
  307 + var re = new RegExp("^" + this._urlAnchor.protocol + "(\\/\\/)(?:([^@]*)?@)?" + this._urlAnchor.host);
  308 + var result = re.exec(this._urlAnchor.href);
  309 + var userinfo = result[2];
  310 + return userinfo || "";
  311 + },
  312 + set: function(value) {
  313 + _checkString(value);
  314 + this.query._updateSearch(this._urlAnchor);
  315 + var re = new RegExp("^" + this._urlAnchor.protocol + "(\\/\\/)(?:([^@]*)?@)?" + this._urlAnchor.host);
  316 + var replacement = this._urlAnchor.protocol + "//" + (value ? value + "@" : "") + this._urlAnchor.host;
  317 + this._urlAnchor.href = this._urlAnchor.href.replace(re, replacement);
  318 + }
  319 + },
  320 + username: {
  321 + get: function() {
  322 + var parsed = _USERNAME_PASSWORD_RE.exec(this._userinfo);
  323 + var username = decodeURIComponent(parsed[1] || "");
  324 + return username;
  325 + },
  326 + set: function(value) {
  327 + _checkString(value);
  328 + var parsed = _USERNAME_PASSWORD_RE.exec(this._userinfo);
  329 + var userpass = [encodeURIComponent(value || "")];
  330 + if (parsed[2] !== null) {
  331 + userpass.push(parsed[2]);
  332 + }
  333 + this._userinfo = userpass.join(":");
  334 + },
  335 + enumerable: true
  336 + },
  337 + password: {
  338 + get: function() {
  339 + var parsed = _USERNAME_PASSWORD_RE.exec(this._userinfo);
  340 + var password = decodeURIComponent(parsed[2] || "");
  341 + return password;
  342 + },
  343 + set: function(value) {
  344 + _checkString(value);
  345 + var parsed = _USERNAME_PASSWORD_RE.exec(this._userinfo);
  346 + var userpass = [parsed[1] || ""];
  347 + if (value) {
  348 + userpass.push(encodeURIComponent(value));
  349 + }
  350 + this._userinfo = userpass.join(":");
  351 + },
  352 + enumerable: true
  353 + },
85 354 host: {
86 355 get: function() {
87 356 return this._urlAnchor.host;
88 357 },
89 358 set: function(value) {
  359 + _checkString(value);
90 360 this._urlAnchor.host = value;
91 361 },
92 362 enumerable: true
@@ -96,6 +366,7 @@
96 366 return this._urlAnchor.hostname;
97 367 },
98 368 set: function(value) {
  369 + _checkString(value);
99 370 this._urlAnchor.hostname = value;
100 371 },
101 372 enumerable: true
@@ -105,6 +376,7 @@
105 376 return this._urlAnchor.port;
106 377 },
107 378 set: function(value) {
  379 + _checkString(value);
108 380 this._urlAnchor.port = value;
109 381 },
110 382 enumerable: true
@@ -114,16 +386,20 @@
114 386 return this._urlAnchor.pathname;
115 387 },
116 388 set: function(value) {
  389 + _checkString(value);
117 390 this._urlAnchor.pathname = value;
118 391 },
119 392 enumerable: true
120 393 },
121 394 search: {
122 395 get: function() {
  396 + this.query._updateSearch(this._urlAnchor);
123 397 return this._urlAnchor.search;
124 398 },
125 399 set: function(value) {
  400 + _checkString(value);
126 401 this._urlAnchor.search = value;
  402 + this.query._parseSearch(this._urlAnchor.search);
127 403 },
128 404 enumerable: true
129 405 },
@@ -132,6 +408,7 @@
132 408 return this._urlAnchor.hash;
133 409 },
134 410 set: function(value) {
  411 + _checkString(value);
135 412 this._urlAnchor.hash = value;
136 413 },
137 414 enumerable: true
@@ -150,5 +427,4 @@
150 427 });
151 428 }
152 429 window.URL = URL;
153   - return URL;
154 430 }());
6 lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/commands.js
@@ -849,8 +849,10 @@ define(['i18n!orion/nls/messages', 'require', 'orion/uiUtils', 'orion/PageUtil',
849 849 if (command.choiceCallback) {
850 850 var menuParent;
851 851 var nodeClass;
  852 + var nested;
852 853 if (renderType === "tool" || renderType === "button") { //$NON-NLS-1$ //$NON-NLS-0$
853 854 menuParent = parent;
  855 + nested = false;
854 856 if (parent.nodeName.toLowerCase() === "ul") { //$NON-NLS-0$
855 857 menuParent = document.createElement("li"); //$NON-NLS-0$
856 858 parent.appendChild(menuParent);
@@ -859,13 +861,14 @@ define(['i18n!orion/nls/messages', 'require', 'orion/uiUtils', 'orion/PageUtil',
859 861 }
860 862 } else {
861 863 menuParent = parent;
  864 + nested = true;
862 865 }
863 866 // dropdown button
864 867 var self = this;
865 868 var populateFunction = function(menu) {
866 869 this.populateChoicesMenu(menu, items, handler, userData, self);
867 870 };
868   - this._createDropdownMenu(menuParent, command.name, true, populateFunction.bind(command));
  871 + this._createDropdownMenu(menuParent, command.name, nested, populateFunction.bind(command));
869 872 } else {
870 873 if (renderType === "tool") { //$NON-NLS-0$
871 874 id = "tool" + command.id + i; //$NON-NLS-0$ // using the index ensures unique ids within the DOM when a command repeats for each item
@@ -1196,7 +1199,6 @@ define(['i18n!orion/nls/messages', 'require', 'orion/uiUtils', 'orion/PageUtil',
1196 1199 */
1197 1200 _makeLink: function(parent, context, aClass, position) {
1198 1201 var element = document.createElement("a"); //$NON-NLS-0$
1199   - element.tabIndex = 0;
1200 1202 element.id = this.name;
1201 1203 if (aClass) {
1202 1204 element.classList.add(aClass); //$NON-NLS-0$
3  lib/orion.client/bundles/org.eclipse.orion.client.core/web/orion/commonHTMLFragments.js
@@ -90,6 +90,9 @@ define(['i18n!orion/nls/messages', 'require', 'orion/webui/littlelib'],
90 90 '<ul class="layoutLeft commandList pageActions" id="pageActions"></ul>' + //$NON-NLS-0$
91 91 '<ul class="layoutLeft commandList pageActions" id="selectionTools"></ul>' + //$NON-NLS-0$
92 92 '<img class="layoutRight progressPane" src="'+ require.toUrl("images/none.png") +'" id="progressPane" tabindex="0" role="progressbar" aria-label="Operations - Press spacebar to show current operations"></img>' + //$NON-NLS-4$ //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
  93 + '<div class="layoutRight" style="padding-left:7px;padding-right:7px;margin-top:3px;" id="settingsTab" style="visibility:hidden;">' +
  94 + '<div class="layoutRight settings core-sprite-settings" id="settingsAction" role="settings" aria-live="off" style="visibility:hidden;"></div>' + //$NON-NLS-0$
  95 + '</div>' +
93 96 '<div class="layoutRight status" id="statusPane" role="status" aria-live="off"></div>' + //$NON-NLS-0$
94