browser/components/places/content/bookmarkProperties.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /**
michael@0 7 * The panel is initialized based on data given in the js object passed
michael@0 8 * as window.arguments[0]. The object must have the following fields set:
michael@0 9 * @ action (String). Possible values:
michael@0 10 * - "add" - for adding a new item.
michael@0 11 * @ type (String). Possible values:
michael@0 12 * - "bookmark"
michael@0 13 * @ loadBookmarkInSidebar - optional, the default state for the
michael@0 14 * "Load this bookmark in the sidebar" field.
michael@0 15 * - "folder"
michael@0 16 * @ URIList (Array of nsIURI objects) - optional, list of uris to
michael@0 17 * be bookmarked under the new folder.
michael@0 18 * - "livemark"
michael@0 19 * @ uri (nsIURI object) - optional, the default uri for the new item.
michael@0 20 * The property is not used for the "folder with items" type.
michael@0 21 * @ title (String) - optional, the default title for the new item.
michael@0 22 * @ description (String) - optional, the default description for the new
michael@0 23 * item.
michael@0 24 * @ defaultInsertionPoint (InsertionPoint JS object) - optional, the
michael@0 25 * default insertion point for the new item.
michael@0 26 * @ keyword (String) - optional, the default keyword for the new item.
michael@0 27 * @ postData (String) - optional, POST data to accompany the keyword.
michael@0 28 * @ charSet (String) - optional, character-set to accompany the keyword.
michael@0 29 * Notes:
michael@0 30 * 1) If |uri| is set for a bookmark/livemark item and |title| isn't,
michael@0 31 * the dialog will query the history tables for the title associated
michael@0 32 * with the given uri. If the dialog is set to adding a folder with
michael@0 33 * bookmark items under it (see URIList), a default static title is
michael@0 34 * used ("[Folder Name]").
michael@0 35 * 2) The index field of the default insertion point is ignored if
michael@0 36 * the folder picker is shown.
michael@0 37 * - "edit" - for editing a bookmark item or a folder.
michael@0 38 * @ type (String). Possible values:
michael@0 39 * - "bookmark"
michael@0 40 * @ itemId (Integer) - the id of the bookmark item.
michael@0 41 * - "folder" (also applies to livemarks)
michael@0 42 * @ itemId (Integer) - the id of the folder.
michael@0 43 * @ hiddenRows (Strings array) - optional, list of rows to be hidden
michael@0 44 * regardless of the item edited or added by the dialog.
michael@0 45 * Possible values:
michael@0 46 * - "title"
michael@0 47 * - "location"
michael@0 48 * - "description"
michael@0 49 * - "keyword"
michael@0 50 * - "tags"
michael@0 51 * - "loadInSidebar"
michael@0 52 * - "feedLocation"
michael@0 53 * - "siteLocation"
michael@0 54 * - "folderPicker" - hides both the tree and the menu.
michael@0 55 * @ readOnly (Boolean) - optional, states if the panel should be read-only
michael@0 56 *
michael@0 57 * window.arguments[0].performed is set to true if any transaction has
michael@0 58 * been performed by the dialog.
michael@0 59 */
michael@0 60
michael@0 61 Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
michael@0 62 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
michael@0 63 "resource://gre/modules/PrivateBrowsingUtils.jsm");
michael@0 64
michael@0 65 const BOOKMARK_ITEM = 0;
michael@0 66 const BOOKMARK_FOLDER = 1;
michael@0 67 const LIVEMARK_CONTAINER = 2;
michael@0 68
michael@0 69 const ACTION_EDIT = 0;
michael@0 70 const ACTION_ADD = 1;
michael@0 71
michael@0 72 var BookmarkPropertiesPanel = {
michael@0 73
michael@0 74 /** UI Text Strings */
michael@0 75 __strings: null,
michael@0 76 get _strings() {
michael@0 77 if (!this.__strings) {
michael@0 78 this.__strings = document.getElementById("stringBundle");
michael@0 79 }
michael@0 80 return this.__strings;
michael@0 81 },
michael@0 82
michael@0 83 _action: null,
michael@0 84 _itemType: null,
michael@0 85 _itemId: -1,
michael@0 86 _uri: null,
michael@0 87 _loadInSidebar: false,
michael@0 88 _title: "",
michael@0 89 _description: "",
michael@0 90 _URIs: [],
michael@0 91 _keyword: "",
michael@0 92 _postData: null,
michael@0 93 _charSet: "",
michael@0 94 _feedURI: null,
michael@0 95 _siteURI: null,
michael@0 96
michael@0 97 _defaultInsertionPoint: null,
michael@0 98 _hiddenRows: [],
michael@0 99 _batching: false,
michael@0 100 _readOnly: false,
michael@0 101
michael@0 102 /**
michael@0 103 * This method returns the correct label for the dialog's "accept"
michael@0 104 * button based on the variant of the dialog.
michael@0 105 */
michael@0 106 _getAcceptLabel: function BPP__getAcceptLabel() {
michael@0 107 if (this._action == ACTION_ADD) {
michael@0 108 if (this._URIs.length)
michael@0 109 return this._strings.getString("dialogAcceptLabelAddMulti");
michael@0 110
michael@0 111 if (this._itemType == LIVEMARK_CONTAINER)
michael@0 112 return this._strings.getString("dialogAcceptLabelAddLivemark");
michael@0 113
michael@0 114 if (this._dummyItem || this._loadInSidebar)
michael@0 115 return this._strings.getString("dialogAcceptLabelAddItem");
michael@0 116
michael@0 117 return this._strings.getString("dialogAcceptLabelSaveItem");
michael@0 118 }
michael@0 119 return this._strings.getString("dialogAcceptLabelEdit");
michael@0 120 },
michael@0 121
michael@0 122 /**
michael@0 123 * This method returns the correct title for the current variant
michael@0 124 * of this dialog.
michael@0 125 */
michael@0 126 _getDialogTitle: function BPP__getDialogTitle() {
michael@0 127 if (this._action == ACTION_ADD) {
michael@0 128 if (this._itemType == BOOKMARK_ITEM)
michael@0 129 return this._strings.getString("dialogTitleAddBookmark");
michael@0 130 if (this._itemType == LIVEMARK_CONTAINER)
michael@0 131 return this._strings.getString("dialogTitleAddLivemark");
michael@0 132
michael@0 133 // add folder
michael@0 134 NS_ASSERT(this._itemType == BOOKMARK_FOLDER, "Unknown item type");
michael@0 135 if (this._URIs.length)
michael@0 136 return this._strings.getString("dialogTitleAddMulti");
michael@0 137
michael@0 138 return this._strings.getString("dialogTitleAddFolder");
michael@0 139 }
michael@0 140 if (this._action == ACTION_EDIT) {
michael@0 141 return this._strings.getFormattedString("dialogTitleEdit", [this._title]);
michael@0 142 }
michael@0 143 return "";
michael@0 144 },
michael@0 145
michael@0 146 /**
michael@0 147 * Determines the initial data for the item edited or added by this dialog
michael@0 148 */
michael@0 149 _determineItemInfo: function BPP__determineItemInfo() {
michael@0 150 var dialogInfo = window.arguments[0];
michael@0 151 this._action = dialogInfo.action == "add" ? ACTION_ADD : ACTION_EDIT;
michael@0 152 this._hiddenRows = dialogInfo.hiddenRows ? dialogInfo.hiddenRows : [];
michael@0 153 if (this._action == ACTION_ADD) {
michael@0 154 NS_ASSERT("type" in dialogInfo, "missing type property for add action");
michael@0 155
michael@0 156 if ("title" in dialogInfo)
michael@0 157 this._title = dialogInfo.title;
michael@0 158
michael@0 159 if ("defaultInsertionPoint" in dialogInfo) {
michael@0 160 this._defaultInsertionPoint = dialogInfo.defaultInsertionPoint;
michael@0 161 }
michael@0 162 else
michael@0 163 this._defaultInsertionPoint =
michael@0 164 new InsertionPoint(PlacesUtils.bookmarksMenuFolderId,
michael@0 165 PlacesUtils.bookmarks.DEFAULT_INDEX,
michael@0 166 Ci.nsITreeView.DROP_ON);
michael@0 167
michael@0 168 switch (dialogInfo.type) {
michael@0 169 case "bookmark":
michael@0 170 this._itemType = BOOKMARK_ITEM;
michael@0 171 if ("uri" in dialogInfo) {
michael@0 172 NS_ASSERT(dialogInfo.uri instanceof Ci.nsIURI,
michael@0 173 "uri property should be a uri object");
michael@0 174 this._uri = dialogInfo.uri;
michael@0 175 if (typeof(this._title) != "string") {
michael@0 176 this._title = this._getURITitleFromHistory(this._uri) ||
michael@0 177 this._uri.spec;
michael@0 178 }
michael@0 179 }
michael@0 180 else {
michael@0 181 this._uri = PlacesUtils._uri("about:blank");
michael@0 182 this._title = this._strings.getString("newBookmarkDefault");
michael@0 183 this._dummyItem = true;
michael@0 184 }
michael@0 185
michael@0 186 if ("loadBookmarkInSidebar" in dialogInfo)
michael@0 187 this._loadInSidebar = dialogInfo.loadBookmarkInSidebar;
michael@0 188
michael@0 189 if ("keyword" in dialogInfo) {
michael@0 190 this._keyword = dialogInfo.keyword;
michael@0 191 this._isAddKeywordDialog = true;
michael@0 192 if ("postData" in dialogInfo)
michael@0 193 this._postData = dialogInfo.postData;
michael@0 194 if ("charSet" in dialogInfo)
michael@0 195 this._charSet = dialogInfo.charSet;
michael@0 196 }
michael@0 197 break;
michael@0 198
michael@0 199 case "folder":
michael@0 200 this._itemType = BOOKMARK_FOLDER;
michael@0 201 if (!this._title) {
michael@0 202 if ("URIList" in dialogInfo) {
michael@0 203 this._title = this._strings.getString("bookmarkAllTabsDefault");
michael@0 204 this._URIs = dialogInfo.URIList;
michael@0 205 }
michael@0 206 else
michael@0 207 this._title = this._strings.getString("newFolderDefault");
michael@0 208 this._dummyItem = true;
michael@0 209 }
michael@0 210 break;
michael@0 211
michael@0 212 case "livemark":
michael@0 213 this._itemType = LIVEMARK_CONTAINER;
michael@0 214 if ("feedURI" in dialogInfo)
michael@0 215 this._feedURI = dialogInfo.feedURI;
michael@0 216 if ("siteURI" in dialogInfo)
michael@0 217 this._siteURI = dialogInfo.siteURI;
michael@0 218
michael@0 219 if (!this._title) {
michael@0 220 if (this._feedURI) {
michael@0 221 this._title = this._getURITitleFromHistory(this._feedURI) ||
michael@0 222 this._feedURI.spec;
michael@0 223 }
michael@0 224 else
michael@0 225 this._title = this._strings.getString("newLivemarkDefault");
michael@0 226 }
michael@0 227 }
michael@0 228
michael@0 229 if ("description" in dialogInfo)
michael@0 230 this._description = dialogInfo.description;
michael@0 231 }
michael@0 232 else { // edit
michael@0 233 NS_ASSERT("itemId" in dialogInfo);
michael@0 234 this._itemId = dialogInfo.itemId;
michael@0 235 this._title = PlacesUtils.bookmarks.getItemTitle(this._itemId);
michael@0 236 this._readOnly = !!dialogInfo.readOnly;
michael@0 237
michael@0 238 switch (dialogInfo.type) {
michael@0 239 case "bookmark":
michael@0 240 this._itemType = BOOKMARK_ITEM;
michael@0 241
michael@0 242 this._uri = PlacesUtils.bookmarks.getBookmarkURI(this._itemId);
michael@0 243 // keyword
michael@0 244 this._keyword = PlacesUtils.bookmarks
michael@0 245 .getKeywordForBookmark(this._itemId);
michael@0 246 // Load In Sidebar
michael@0 247 this._loadInSidebar = PlacesUtils.annotations
michael@0 248 .itemHasAnnotation(this._itemId,
michael@0 249 PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO);
michael@0 250 break;
michael@0 251
michael@0 252 case "folder":
michael@0 253 this._itemType = BOOKMARK_FOLDER;
michael@0 254 PlacesUtils.livemarks.getLivemark({ id: this._itemId })
michael@0 255 .then(aLivemark => {
michael@0 256 this._itemType = LIVEMARK_CONTAINER;
michael@0 257 this._feedURI = aLivemark.feedURI;
michael@0 258 this._siteURI = aLivemark.siteURI;
michael@0 259 this._fillEditProperties();
michael@0 260
michael@0 261 let acceptButton = document.documentElement.getButton("accept");
michael@0 262 acceptButton.disabled = !this._inputIsValid();
michael@0 263
michael@0 264 let newHeight = window.outerHeight +
michael@0 265 this._element("descriptionField").boxObject.height;
michael@0 266 window.resizeTo(window.outerWidth, newHeight);
michael@0 267 }, () => undefined);
michael@0 268
michael@0 269 break;
michael@0 270 }
michael@0 271
michael@0 272 // Description
michael@0 273 if (PlacesUtils.annotations
michael@0 274 .itemHasAnnotation(this._itemId, PlacesUIUtils.DESCRIPTION_ANNO)) {
michael@0 275 this._description = PlacesUtils.annotations
michael@0 276 .getItemAnnotation(this._itemId,
michael@0 277 PlacesUIUtils.DESCRIPTION_ANNO);
michael@0 278 }
michael@0 279 }
michael@0 280 },
michael@0 281
michael@0 282 /**
michael@0 283 * This method returns the title string corresponding to a given URI.
michael@0 284 * If none is available from the bookmark service (probably because
michael@0 285 * the given URI doesn't appear in bookmarks or history), we synthesize
michael@0 286 * a title from the first 100 characters of the URI.
michael@0 287 *
michael@0 288 * @param aURI
michael@0 289 * nsIURI object for which we want the title
michael@0 290 *
michael@0 291 * @returns a title string
michael@0 292 */
michael@0 293 _getURITitleFromHistory: function BPP__getURITitleFromHistory(aURI) {
michael@0 294 NS_ASSERT(aURI instanceof Ci.nsIURI);
michael@0 295
michael@0 296 // get the title from History
michael@0 297 return PlacesUtils.history.getPageTitle(aURI);
michael@0 298 },
michael@0 299
michael@0 300 /**
michael@0 301 * This method should be called by the onload of the Bookmark Properties
michael@0 302 * dialog to initialize the state of the panel.
michael@0 303 */
michael@0 304 onDialogLoad: function BPP_onDialogLoad() {
michael@0 305 this._determineItemInfo();
michael@0 306
michael@0 307 document.title = this._getDialogTitle();
michael@0 308 var acceptButton = document.documentElement.getButton("accept");
michael@0 309 acceptButton.label = this._getAcceptLabel();
michael@0 310
michael@0 311 this._beginBatch();
michael@0 312
michael@0 313 switch (this._action) {
michael@0 314 case ACTION_EDIT:
michael@0 315 this._fillEditProperties();
michael@0 316 acceptButton.disabled = this._readOnly;
michael@0 317 break;
michael@0 318 case ACTION_ADD:
michael@0 319 this._fillAddProperties();
michael@0 320 // if this is an uri related dialog disable accept button until
michael@0 321 // the user fills an uri value.
michael@0 322 if (this._itemType == BOOKMARK_ITEM)
michael@0 323 acceptButton.disabled = !this._inputIsValid();
michael@0 324 break;
michael@0 325 }
michael@0 326
michael@0 327 // When collapsible elements change their collapsed attribute we must
michael@0 328 // resize the dialog.
michael@0 329 // sizeToContent is not usable due to bug 90276, so we'll use resizeTo
michael@0 330 // instead and cache the element size. See WSucks in the legacy
michael@0 331 // UI code (addBookmark2.js).
michael@0 332 if (!this._element("tagsRow").collapsed) {
michael@0 333 this._element("tagsSelectorRow")
michael@0 334 .addEventListener("DOMAttrModified", this, false);
michael@0 335 }
michael@0 336 if (!this._element("folderRow").collapsed) {
michael@0 337 this._element("folderTreeRow")
michael@0 338 .addEventListener("DOMAttrModified", this, false);
michael@0 339 }
michael@0 340
michael@0 341 if (!this._readOnly) {
michael@0 342 // Listen on uri fields to enable accept button if input is valid
michael@0 343 if (this._itemType == BOOKMARK_ITEM) {
michael@0 344 this._element("locationField")
michael@0 345 .addEventListener("input", this, false);
michael@0 346 if (this._isAddKeywordDialog) {
michael@0 347 this._element("keywordField")
michael@0 348 .addEventListener("input", this, false);
michael@0 349 }
michael@0 350 }
michael@0 351 else if (this._itemType == LIVEMARK_CONTAINER) {
michael@0 352 this._element("feedLocationField")
michael@0 353 .addEventListener("input", this, false);
michael@0 354 this._element("siteLocationField")
michael@0 355 .addEventListener("input", this, false);
michael@0 356 }
michael@0 357 }
michael@0 358
michael@0 359 window.sizeToContent();
michael@0 360 },
michael@0 361
michael@0 362 // nsIDOMEventListener
michael@0 363 _elementsHeight: [],
michael@0 364 handleEvent: function BPP_handleEvent(aEvent) {
michael@0 365 var target = aEvent.target;
michael@0 366 switch (aEvent.type) {
michael@0 367 case "input":
michael@0 368 if (target.id == "editBMPanel_locationField" ||
michael@0 369 target.id == "editBMPanel_feedLocationField" ||
michael@0 370 target.id == "editBMPanel_siteLocationField" ||
michael@0 371 target.id == "editBMPanel_keywordField") {
michael@0 372 // Check uri fields to enable accept button if input is valid
michael@0 373 document.documentElement
michael@0 374 .getButton("accept").disabled = !this._inputIsValid();
michael@0 375 }
michael@0 376 break;
michael@0 377
michael@0 378 case "DOMAttrModified":
michael@0 379 // this is called when collapsing a node, but also its direct children,
michael@0 380 // we only need to resize when the original node changes.
michael@0 381 if ((target.id == "editBMPanel_tagsSelectorRow" ||
michael@0 382 target.id == "editBMPanel_folderTreeRow") &&
michael@0 383 aEvent.attrName == "collapsed" &&
michael@0 384 target == aEvent.originalTarget) {
michael@0 385 var id = target.id;
michael@0 386 var newHeight = window.outerHeight;
michael@0 387 if (aEvent.newValue) // is collapsed
michael@0 388 newHeight -= this._elementsHeight[id];
michael@0 389 else {
michael@0 390 this._elementsHeight[id] = target.boxObject.height;
michael@0 391 newHeight += this._elementsHeight[id];
michael@0 392 }
michael@0 393
michael@0 394 window.resizeTo(window.outerWidth, newHeight);
michael@0 395 }
michael@0 396 break;
michael@0 397 }
michael@0 398 },
michael@0 399
michael@0 400 _beginBatch: function BPP__beginBatch() {
michael@0 401 if (this._batching)
michael@0 402 return;
michael@0 403
michael@0 404 PlacesUtils.transactionManager.beginBatch(null);
michael@0 405 this._batching = true;
michael@0 406 },
michael@0 407
michael@0 408 _endBatch: function BPP__endBatch() {
michael@0 409 if (!this._batching)
michael@0 410 return;
michael@0 411
michael@0 412 PlacesUtils.transactionManager.endBatch(false);
michael@0 413 this._batching = false;
michael@0 414 },
michael@0 415
michael@0 416 _fillEditProperties: function BPP__fillEditProperties() {
michael@0 417 gEditItemOverlay.initPanel(this._itemId,
michael@0 418 { hiddenRows: this._hiddenRows,
michael@0 419 forceReadOnly: this._readOnly });
michael@0 420 },
michael@0 421
michael@0 422 _fillAddProperties: function BPP__fillAddProperties() {
michael@0 423 this._createNewItem();
michael@0 424 // Edit the new item
michael@0 425 gEditItemOverlay.initPanel(this._itemId,
michael@0 426 { hiddenRows: this._hiddenRows });
michael@0 427 // Empty location field if the uri is about:blank, this way inserting a new
michael@0 428 // url will be easier for the user, Accept button will be automatically
michael@0 429 // disabled by the input listener until the user fills the field.
michael@0 430 var locationField = this._element("locationField");
michael@0 431 if (locationField.value == "about:blank")
michael@0 432 locationField.value = "";
michael@0 433 },
michael@0 434
michael@0 435 // nsISupports
michael@0 436 QueryInterface: function BPP_QueryInterface(aIID) {
michael@0 437 if (aIID.equals(Ci.nsIDOMEventListener) ||
michael@0 438 aIID.equals(Ci.nsISupports))
michael@0 439 return this;
michael@0 440
michael@0 441 throw Cr.NS_NOINTERFACE;
michael@0 442 },
michael@0 443
michael@0 444 _element: function BPP__element(aID) {
michael@0 445 return document.getElementById("editBMPanel_" + aID);
michael@0 446 },
michael@0 447
michael@0 448 onDialogUnload: function BPP_onDialogUnload() {
michael@0 449 // gEditItemOverlay does not exist anymore here, so don't rely on it.
michael@0 450 // Calling removeEventListener with arguments which do not identify any
michael@0 451 // currently registered EventListener on the EventTarget has no effect.
michael@0 452 this._element("tagsSelectorRow")
michael@0 453 .removeEventListener("DOMAttrModified", this, false);
michael@0 454 this._element("folderTreeRow")
michael@0 455 .removeEventListener("DOMAttrModified", this, false);
michael@0 456 this._element("locationField")
michael@0 457 .removeEventListener("input", this, false);
michael@0 458 this._element("feedLocationField")
michael@0 459 .removeEventListener("input", this, false);
michael@0 460 this._element("siteLocationField")
michael@0 461 .removeEventListener("input", this, false);
michael@0 462 },
michael@0 463
michael@0 464 onDialogAccept: function BPP_onDialogAccept() {
michael@0 465 // We must blur current focused element to save its changes correctly
michael@0 466 document.commandDispatcher.focusedElement.blur();
michael@0 467 // The order here is important! We have to uninit the panel first, otherwise
michael@0 468 // late changes could force it to commit more transactions.
michael@0 469 gEditItemOverlay.uninitPanel(true);
michael@0 470 gEditItemOverlay = null;
michael@0 471 this._endBatch();
michael@0 472 window.arguments[0].performed = true;
michael@0 473 },
michael@0 474
michael@0 475 onDialogCancel: function BPP_onDialogCancel() {
michael@0 476 // The order here is important! We have to uninit the panel first, otherwise
michael@0 477 // changes done as part of Undo may change the panel contents and by
michael@0 478 // that force it to commit more transactions.
michael@0 479 gEditItemOverlay.uninitPanel(true);
michael@0 480 gEditItemOverlay = null;
michael@0 481 this._endBatch();
michael@0 482 PlacesUtils.transactionManager.undoTransaction();
michael@0 483 window.arguments[0].performed = false;
michael@0 484 },
michael@0 485
michael@0 486 /**
michael@0 487 * This method checks to see if the input fields are in a valid state.
michael@0 488 *
michael@0 489 * @returns true if the input is valid, false otherwise
michael@0 490 */
michael@0 491 _inputIsValid: function BPP__inputIsValid() {
michael@0 492 if (this._itemType == BOOKMARK_ITEM &&
michael@0 493 !this._containsValidURI("locationField"))
michael@0 494 return false;
michael@0 495 if (this._isAddKeywordDialog && !this._element("keywordField").value.length)
michael@0 496 return false;
michael@0 497
michael@0 498 return true;
michael@0 499 },
michael@0 500
michael@0 501 /**
michael@0 502 * Determines whether the XUL textbox with the given ID contains a
michael@0 503 * string that can be converted into an nsIURI.
michael@0 504 *
michael@0 505 * @param aTextboxID
michael@0 506 * the ID of the textbox element whose contents we'll test
michael@0 507 *
michael@0 508 * @returns true if the textbox contains a valid URI string, false otherwise
michael@0 509 */
michael@0 510 _containsValidURI: function BPP__containsValidURI(aTextboxID) {
michael@0 511 try {
michael@0 512 var value = this._element(aTextboxID).value;
michael@0 513 if (value) {
michael@0 514 PlacesUIUtils.createFixedURI(value);
michael@0 515 return true;
michael@0 516 }
michael@0 517 } catch (e) { }
michael@0 518 return false;
michael@0 519 },
michael@0 520
michael@0 521 /**
michael@0 522 * [New Item Mode] Get the insertion point details for the new item, given
michael@0 523 * dialog state and opening arguments.
michael@0 524 *
michael@0 525 * The container-identifier and insertion-index are returned separately in
michael@0 526 * the form of [containerIdentifier, insertionIndex]
michael@0 527 */
michael@0 528 _getInsertionPointDetails: function BPP__getInsertionPointDetails() {
michael@0 529 var containerId = this._defaultInsertionPoint.itemId;
michael@0 530 var indexInContainer = this._defaultInsertionPoint.index;
michael@0 531
michael@0 532 return [containerId, indexInContainer];
michael@0 533 },
michael@0 534
michael@0 535 /**
michael@0 536 * Returns a transaction for creating a new bookmark item representing the
michael@0 537 * various fields and opening arguments of the dialog.
michael@0 538 */
michael@0 539 _getCreateNewBookmarkTransaction:
michael@0 540 function BPP__getCreateNewBookmarkTransaction(aContainer, aIndex) {
michael@0 541 var annotations = [];
michael@0 542 var childTransactions = [];
michael@0 543
michael@0 544 if (this._description) {
michael@0 545 let annoObj = { name : PlacesUIUtils.DESCRIPTION_ANNO,
michael@0 546 type : Ci.nsIAnnotationService.TYPE_STRING,
michael@0 547 flags : 0,
michael@0 548 value : this._description,
michael@0 549 expires: Ci.nsIAnnotationService.EXPIRE_NEVER };
michael@0 550 let editItemTxn = new PlacesSetItemAnnotationTransaction(-1, annoObj);
michael@0 551 childTransactions.push(editItemTxn);
michael@0 552 }
michael@0 553
michael@0 554 if (this._loadInSidebar) {
michael@0 555 let annoObj = { name : PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO,
michael@0 556 value : true };
michael@0 557 let setLoadTxn = new PlacesSetItemAnnotationTransaction(-1, annoObj);
michael@0 558 childTransactions.push(setLoadTxn);
michael@0 559 }
michael@0 560
michael@0 561 if (this._postData) {
michael@0 562 let postDataTxn = new PlacesEditBookmarkPostDataTransaction(-1, this._postData);
michael@0 563 childTransactions.push(postDataTxn);
michael@0 564 }
michael@0 565
michael@0 566 //XXX TODO: this should be in a transaction!
michael@0 567 if (this._charSet && !PrivateBrowsingUtils.isWindowPrivate(window))
michael@0 568 PlacesUtils.setCharsetForURI(this._uri, this._charSet);
michael@0 569
michael@0 570 let createTxn = new PlacesCreateBookmarkTransaction(this._uri,
michael@0 571 aContainer,
michael@0 572 aIndex,
michael@0 573 this._title,
michael@0 574 this._keyword,
michael@0 575 annotations,
michael@0 576 childTransactions);
michael@0 577
michael@0 578 return new PlacesAggregatedTransaction(this._getDialogTitle(),
michael@0 579 [createTxn]);
michael@0 580 },
michael@0 581
michael@0 582 /**
michael@0 583 * Returns a childItems-transactions array representing the URIList with
michael@0 584 * which the dialog has been opened.
michael@0 585 */
michael@0 586 _getTransactionsForURIList: function BPP__getTransactionsForURIList() {
michael@0 587 var transactions = [];
michael@0 588 for (var i = 0; i < this._URIs.length; ++i) {
michael@0 589 var uri = this._URIs[i];
michael@0 590 var title = this._getURITitleFromHistory(uri);
michael@0 591 var createTxn = new PlacesCreateBookmarkTransaction(uri, -1,
michael@0 592 PlacesUtils.bookmarks.DEFAULT_INDEX,
michael@0 593 title);
michael@0 594 transactions.push(createTxn);
michael@0 595 }
michael@0 596 return transactions;
michael@0 597 },
michael@0 598
michael@0 599 /**
michael@0 600 * Returns a transaction for creating a new folder item representing the
michael@0 601 * various fields and opening arguments of the dialog.
michael@0 602 */
michael@0 603 _getCreateNewFolderTransaction:
michael@0 604 function BPP__getCreateNewFolderTransaction(aContainer, aIndex) {
michael@0 605 var annotations = [];
michael@0 606 var childItemsTransactions;
michael@0 607 if (this._URIs.length)
michael@0 608 childItemsTransactions = this._getTransactionsForURIList();
michael@0 609
michael@0 610 if (this._description)
michael@0 611 annotations.push(this._getDescriptionAnnotation(this._description));
michael@0 612
michael@0 613 return new PlacesCreateFolderTransaction(this._title, aContainer,
michael@0 614 aIndex, annotations,
michael@0 615 childItemsTransactions);
michael@0 616 },
michael@0 617
michael@0 618 /**
michael@0 619 * Returns a transaction for creating a new live-bookmark item representing
michael@0 620 * the various fields and opening arguments of the dialog.
michael@0 621 */
michael@0 622 _getCreateNewLivemarkTransaction:
michael@0 623 function BPP__getCreateNewLivemarkTransaction(aContainer, aIndex) {
michael@0 624 return new PlacesCreateLivemarkTransaction(this._feedURI, this._siteURI,
michael@0 625 this._title,
michael@0 626 aContainer, aIndex);
michael@0 627 },
michael@0 628
michael@0 629 /**
michael@0 630 * Dialog-accept code-path for creating a new item (any type)
michael@0 631 */
michael@0 632 _createNewItem: function BPP__getCreateItemTransaction() {
michael@0 633 var [container, index] = this._getInsertionPointDetails();
michael@0 634 var txn;
michael@0 635
michael@0 636 switch (this._itemType) {
michael@0 637 case BOOKMARK_FOLDER:
michael@0 638 txn = this._getCreateNewFolderTransaction(container, index);
michael@0 639 break;
michael@0 640 case LIVEMARK_CONTAINER:
michael@0 641 txn = this._getCreateNewLivemarkTransaction(container, index);
michael@0 642 break;
michael@0 643 default: // BOOKMARK_ITEM
michael@0 644 txn = this._getCreateNewBookmarkTransaction(container, index);
michael@0 645 }
michael@0 646
michael@0 647 PlacesUtils.transactionManager.doTransaction(txn);
michael@0 648 this._itemId = PlacesUtils.bookmarks.getIdForItemAt(container, index);
michael@0 649 }
michael@0 650 };

mercurial