michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /** michael@0: * The panel is initialized based on data given in the js object passed michael@0: * as window.arguments[0]. The object must have the following fields set: michael@0: * @ action (String). Possible values: michael@0: * - "add" - for adding a new item. michael@0: * @ type (String). Possible values: michael@0: * - "bookmark" michael@0: * @ loadBookmarkInSidebar - optional, the default state for the michael@0: * "Load this bookmark in the sidebar" field. michael@0: * - "folder" michael@0: * @ URIList (Array of nsIURI objects) - optional, list of uris to michael@0: * be bookmarked under the new folder. michael@0: * - "livemark" michael@0: * @ uri (nsIURI object) - optional, the default uri for the new item. michael@0: * The property is not used for the "folder with items" type. michael@0: * @ title (String) - optional, the default title for the new item. michael@0: * @ description (String) - optional, the default description for the new michael@0: * item. michael@0: * @ defaultInsertionPoint (InsertionPoint JS object) - optional, the michael@0: * default insertion point for the new item. michael@0: * @ keyword (String) - optional, the default keyword for the new item. michael@0: * @ postData (String) - optional, POST data to accompany the keyword. michael@0: * @ charSet (String) - optional, character-set to accompany the keyword. michael@0: * Notes: michael@0: * 1) If |uri| is set for a bookmark/livemark item and |title| isn't, michael@0: * the dialog will query the history tables for the title associated michael@0: * with the given uri. If the dialog is set to adding a folder with michael@0: * bookmark items under it (see URIList), a default static title is michael@0: * used ("[Folder Name]"). michael@0: * 2) The index field of the default insertion point is ignored if michael@0: * the folder picker is shown. michael@0: * - "edit" - for editing a bookmark item or a folder. michael@0: * @ type (String). Possible values: michael@0: * - "bookmark" michael@0: * @ itemId (Integer) - the id of the bookmark item. michael@0: * - "folder" (also applies to livemarks) michael@0: * @ itemId (Integer) - the id of the folder. michael@0: * @ hiddenRows (Strings array) - optional, list of rows to be hidden michael@0: * regardless of the item edited or added by the dialog. michael@0: * Possible values: michael@0: * - "title" michael@0: * - "location" michael@0: * - "description" michael@0: * - "keyword" michael@0: * - "tags" michael@0: * - "loadInSidebar" michael@0: * - "feedLocation" michael@0: * - "siteLocation" michael@0: * - "folderPicker" - hides both the tree and the menu. michael@0: * @ readOnly (Boolean) - optional, states if the panel should be read-only michael@0: * michael@0: * window.arguments[0].performed is set to true if any transaction has michael@0: * been performed by the dialog. michael@0: */ michael@0: michael@0: Components.utils.import('resource://gre/modules/XPCOMUtils.jsm'); michael@0: XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils", michael@0: "resource://gre/modules/PrivateBrowsingUtils.jsm"); michael@0: michael@0: const BOOKMARK_ITEM = 0; michael@0: const BOOKMARK_FOLDER = 1; michael@0: const LIVEMARK_CONTAINER = 2; michael@0: michael@0: const ACTION_EDIT = 0; michael@0: const ACTION_ADD = 1; michael@0: michael@0: var BookmarkPropertiesPanel = { michael@0: michael@0: /** UI Text Strings */ michael@0: __strings: null, michael@0: get _strings() { michael@0: if (!this.__strings) { michael@0: this.__strings = document.getElementById("stringBundle"); michael@0: } michael@0: return this.__strings; michael@0: }, michael@0: michael@0: _action: null, michael@0: _itemType: null, michael@0: _itemId: -1, michael@0: _uri: null, michael@0: _loadInSidebar: false, michael@0: _title: "", michael@0: _description: "", michael@0: _URIs: [], michael@0: _keyword: "", michael@0: _postData: null, michael@0: _charSet: "", michael@0: _feedURI: null, michael@0: _siteURI: null, michael@0: michael@0: _defaultInsertionPoint: null, michael@0: _hiddenRows: [], michael@0: _batching: false, michael@0: _readOnly: false, michael@0: michael@0: /** michael@0: * This method returns the correct label for the dialog's "accept" michael@0: * button based on the variant of the dialog. michael@0: */ michael@0: _getAcceptLabel: function BPP__getAcceptLabel() { michael@0: if (this._action == ACTION_ADD) { michael@0: if (this._URIs.length) michael@0: return this._strings.getString("dialogAcceptLabelAddMulti"); michael@0: michael@0: if (this._itemType == LIVEMARK_CONTAINER) michael@0: return this._strings.getString("dialogAcceptLabelAddLivemark"); michael@0: michael@0: if (this._dummyItem || this._loadInSidebar) michael@0: return this._strings.getString("dialogAcceptLabelAddItem"); michael@0: michael@0: return this._strings.getString("dialogAcceptLabelSaveItem"); michael@0: } michael@0: return this._strings.getString("dialogAcceptLabelEdit"); michael@0: }, michael@0: michael@0: /** michael@0: * This method returns the correct title for the current variant michael@0: * of this dialog. michael@0: */ michael@0: _getDialogTitle: function BPP__getDialogTitle() { michael@0: if (this._action == ACTION_ADD) { michael@0: if (this._itemType == BOOKMARK_ITEM) michael@0: return this._strings.getString("dialogTitleAddBookmark"); michael@0: if (this._itemType == LIVEMARK_CONTAINER) michael@0: return this._strings.getString("dialogTitleAddLivemark"); michael@0: michael@0: // add folder michael@0: NS_ASSERT(this._itemType == BOOKMARK_FOLDER, "Unknown item type"); michael@0: if (this._URIs.length) michael@0: return this._strings.getString("dialogTitleAddMulti"); michael@0: michael@0: return this._strings.getString("dialogTitleAddFolder"); michael@0: } michael@0: if (this._action == ACTION_EDIT) { michael@0: return this._strings.getFormattedString("dialogTitleEdit", [this._title]); michael@0: } michael@0: return ""; michael@0: }, michael@0: michael@0: /** michael@0: * Determines the initial data for the item edited or added by this dialog michael@0: */ michael@0: _determineItemInfo: function BPP__determineItemInfo() { michael@0: var dialogInfo = window.arguments[0]; michael@0: this._action = dialogInfo.action == "add" ? ACTION_ADD : ACTION_EDIT; michael@0: this._hiddenRows = dialogInfo.hiddenRows ? dialogInfo.hiddenRows : []; michael@0: if (this._action == ACTION_ADD) { michael@0: NS_ASSERT("type" in dialogInfo, "missing type property for add action"); michael@0: michael@0: if ("title" in dialogInfo) michael@0: this._title = dialogInfo.title; michael@0: michael@0: if ("defaultInsertionPoint" in dialogInfo) { michael@0: this._defaultInsertionPoint = dialogInfo.defaultInsertionPoint; michael@0: } michael@0: else michael@0: this._defaultInsertionPoint = michael@0: new InsertionPoint(PlacesUtils.bookmarksMenuFolderId, michael@0: PlacesUtils.bookmarks.DEFAULT_INDEX, michael@0: Ci.nsITreeView.DROP_ON); michael@0: michael@0: switch (dialogInfo.type) { michael@0: case "bookmark": michael@0: this._itemType = BOOKMARK_ITEM; michael@0: if ("uri" in dialogInfo) { michael@0: NS_ASSERT(dialogInfo.uri instanceof Ci.nsIURI, michael@0: "uri property should be a uri object"); michael@0: this._uri = dialogInfo.uri; michael@0: if (typeof(this._title) != "string") { michael@0: this._title = this._getURITitleFromHistory(this._uri) || michael@0: this._uri.spec; michael@0: } michael@0: } michael@0: else { michael@0: this._uri = PlacesUtils._uri("about:blank"); michael@0: this._title = this._strings.getString("newBookmarkDefault"); michael@0: this._dummyItem = true; michael@0: } michael@0: michael@0: if ("loadBookmarkInSidebar" in dialogInfo) michael@0: this._loadInSidebar = dialogInfo.loadBookmarkInSidebar; michael@0: michael@0: if ("keyword" in dialogInfo) { michael@0: this._keyword = dialogInfo.keyword; michael@0: this._isAddKeywordDialog = true; michael@0: if ("postData" in dialogInfo) michael@0: this._postData = dialogInfo.postData; michael@0: if ("charSet" in dialogInfo) michael@0: this._charSet = dialogInfo.charSet; michael@0: } michael@0: break; michael@0: michael@0: case "folder": michael@0: this._itemType = BOOKMARK_FOLDER; michael@0: if (!this._title) { michael@0: if ("URIList" in dialogInfo) { michael@0: this._title = this._strings.getString("bookmarkAllTabsDefault"); michael@0: this._URIs = dialogInfo.URIList; michael@0: } michael@0: else michael@0: this._title = this._strings.getString("newFolderDefault"); michael@0: this._dummyItem = true; michael@0: } michael@0: break; michael@0: michael@0: case "livemark": michael@0: this._itemType = LIVEMARK_CONTAINER; michael@0: if ("feedURI" in dialogInfo) michael@0: this._feedURI = dialogInfo.feedURI; michael@0: if ("siteURI" in dialogInfo) michael@0: this._siteURI = dialogInfo.siteURI; michael@0: michael@0: if (!this._title) { michael@0: if (this._feedURI) { michael@0: this._title = this._getURITitleFromHistory(this._feedURI) || michael@0: this._feedURI.spec; michael@0: } michael@0: else michael@0: this._title = this._strings.getString("newLivemarkDefault"); michael@0: } michael@0: } michael@0: michael@0: if ("description" in dialogInfo) michael@0: this._description = dialogInfo.description; michael@0: } michael@0: else { // edit michael@0: NS_ASSERT("itemId" in dialogInfo); michael@0: this._itemId = dialogInfo.itemId; michael@0: this._title = PlacesUtils.bookmarks.getItemTitle(this._itemId); michael@0: this._readOnly = !!dialogInfo.readOnly; michael@0: michael@0: switch (dialogInfo.type) { michael@0: case "bookmark": michael@0: this._itemType = BOOKMARK_ITEM; michael@0: michael@0: this._uri = PlacesUtils.bookmarks.getBookmarkURI(this._itemId); michael@0: // keyword michael@0: this._keyword = PlacesUtils.bookmarks michael@0: .getKeywordForBookmark(this._itemId); michael@0: // Load In Sidebar michael@0: this._loadInSidebar = PlacesUtils.annotations michael@0: .itemHasAnnotation(this._itemId, michael@0: PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO); michael@0: break; michael@0: michael@0: case "folder": michael@0: this._itemType = BOOKMARK_FOLDER; michael@0: PlacesUtils.livemarks.getLivemark({ id: this._itemId }) michael@0: .then(aLivemark => { michael@0: this._itemType = LIVEMARK_CONTAINER; michael@0: this._feedURI = aLivemark.feedURI; michael@0: this._siteURI = aLivemark.siteURI; michael@0: this._fillEditProperties(); michael@0: michael@0: let acceptButton = document.documentElement.getButton("accept"); michael@0: acceptButton.disabled = !this._inputIsValid(); michael@0: michael@0: let newHeight = window.outerHeight + michael@0: this._element("descriptionField").boxObject.height; michael@0: window.resizeTo(window.outerWidth, newHeight); michael@0: }, () => undefined); michael@0: michael@0: break; michael@0: } michael@0: michael@0: // Description michael@0: if (PlacesUtils.annotations michael@0: .itemHasAnnotation(this._itemId, PlacesUIUtils.DESCRIPTION_ANNO)) { michael@0: this._description = PlacesUtils.annotations michael@0: .getItemAnnotation(this._itemId, michael@0: PlacesUIUtils.DESCRIPTION_ANNO); michael@0: } michael@0: } michael@0: }, michael@0: michael@0: /** michael@0: * This method returns the title string corresponding to a given URI. michael@0: * If none is available from the bookmark service (probably because michael@0: * the given URI doesn't appear in bookmarks or history), we synthesize michael@0: * a title from the first 100 characters of the URI. michael@0: * michael@0: * @param aURI michael@0: * nsIURI object for which we want the title michael@0: * michael@0: * @returns a title string michael@0: */ michael@0: _getURITitleFromHistory: function BPP__getURITitleFromHistory(aURI) { michael@0: NS_ASSERT(aURI instanceof Ci.nsIURI); michael@0: michael@0: // get the title from History michael@0: return PlacesUtils.history.getPageTitle(aURI); michael@0: }, michael@0: michael@0: /** michael@0: * This method should be called by the onload of the Bookmark Properties michael@0: * dialog to initialize the state of the panel. michael@0: */ michael@0: onDialogLoad: function BPP_onDialogLoad() { michael@0: this._determineItemInfo(); michael@0: michael@0: document.title = this._getDialogTitle(); michael@0: var acceptButton = document.documentElement.getButton("accept"); michael@0: acceptButton.label = this._getAcceptLabel(); michael@0: michael@0: this._beginBatch(); michael@0: michael@0: switch (this._action) { michael@0: case ACTION_EDIT: michael@0: this._fillEditProperties(); michael@0: acceptButton.disabled = this._readOnly; michael@0: break; michael@0: case ACTION_ADD: michael@0: this._fillAddProperties(); michael@0: // if this is an uri related dialog disable accept button until michael@0: // the user fills an uri value. michael@0: if (this._itemType == BOOKMARK_ITEM) michael@0: acceptButton.disabled = !this._inputIsValid(); michael@0: break; michael@0: } michael@0: michael@0: // When collapsible elements change their collapsed attribute we must michael@0: // resize the dialog. michael@0: // sizeToContent is not usable due to bug 90276, so we'll use resizeTo michael@0: // instead and cache the element size. See WSucks in the legacy michael@0: // UI code (addBookmark2.js). michael@0: if (!this._element("tagsRow").collapsed) { michael@0: this._element("tagsSelectorRow") michael@0: .addEventListener("DOMAttrModified", this, false); michael@0: } michael@0: if (!this._element("folderRow").collapsed) { michael@0: this._element("folderTreeRow") michael@0: .addEventListener("DOMAttrModified", this, false); michael@0: } michael@0: michael@0: if (!this._readOnly) { michael@0: // Listen on uri fields to enable accept button if input is valid michael@0: if (this._itemType == BOOKMARK_ITEM) { michael@0: this._element("locationField") michael@0: .addEventListener("input", this, false); michael@0: if (this._isAddKeywordDialog) { michael@0: this._element("keywordField") michael@0: .addEventListener("input", this, false); michael@0: } michael@0: } michael@0: else if (this._itemType == LIVEMARK_CONTAINER) { michael@0: this._element("feedLocationField") michael@0: .addEventListener("input", this, false); michael@0: this._element("siteLocationField") michael@0: .addEventListener("input", this, false); michael@0: } michael@0: } michael@0: michael@0: window.sizeToContent(); michael@0: }, michael@0: michael@0: // nsIDOMEventListener michael@0: _elementsHeight: [], michael@0: handleEvent: function BPP_handleEvent(aEvent) { michael@0: var target = aEvent.target; michael@0: switch (aEvent.type) { michael@0: case "input": michael@0: if (target.id == "editBMPanel_locationField" || michael@0: target.id == "editBMPanel_feedLocationField" || michael@0: target.id == "editBMPanel_siteLocationField" || michael@0: target.id == "editBMPanel_keywordField") { michael@0: // Check uri fields to enable accept button if input is valid michael@0: document.documentElement michael@0: .getButton("accept").disabled = !this._inputIsValid(); michael@0: } michael@0: break; michael@0: michael@0: case "DOMAttrModified": michael@0: // this is called when collapsing a node, but also its direct children, michael@0: // we only need to resize when the original node changes. michael@0: if ((target.id == "editBMPanel_tagsSelectorRow" || michael@0: target.id == "editBMPanel_folderTreeRow") && michael@0: aEvent.attrName == "collapsed" && michael@0: target == aEvent.originalTarget) { michael@0: var id = target.id; michael@0: var newHeight = window.outerHeight; michael@0: if (aEvent.newValue) // is collapsed michael@0: newHeight -= this._elementsHeight[id]; michael@0: else { michael@0: this._elementsHeight[id] = target.boxObject.height; michael@0: newHeight += this._elementsHeight[id]; michael@0: } michael@0: michael@0: window.resizeTo(window.outerWidth, newHeight); michael@0: } michael@0: break; michael@0: } michael@0: }, michael@0: michael@0: _beginBatch: function BPP__beginBatch() { michael@0: if (this._batching) michael@0: return; michael@0: michael@0: PlacesUtils.transactionManager.beginBatch(null); michael@0: this._batching = true; michael@0: }, michael@0: michael@0: _endBatch: function BPP__endBatch() { michael@0: if (!this._batching) michael@0: return; michael@0: michael@0: PlacesUtils.transactionManager.endBatch(false); michael@0: this._batching = false; michael@0: }, michael@0: michael@0: _fillEditProperties: function BPP__fillEditProperties() { michael@0: gEditItemOverlay.initPanel(this._itemId, michael@0: { hiddenRows: this._hiddenRows, michael@0: forceReadOnly: this._readOnly }); michael@0: }, michael@0: michael@0: _fillAddProperties: function BPP__fillAddProperties() { michael@0: this._createNewItem(); michael@0: // Edit the new item michael@0: gEditItemOverlay.initPanel(this._itemId, michael@0: { hiddenRows: this._hiddenRows }); michael@0: // Empty location field if the uri is about:blank, this way inserting a new michael@0: // url will be easier for the user, Accept button will be automatically michael@0: // disabled by the input listener until the user fills the field. michael@0: var locationField = this._element("locationField"); michael@0: if (locationField.value == "about:blank") michael@0: locationField.value = ""; michael@0: }, michael@0: michael@0: // nsISupports michael@0: QueryInterface: function BPP_QueryInterface(aIID) { michael@0: if (aIID.equals(Ci.nsIDOMEventListener) || michael@0: aIID.equals(Ci.nsISupports)) michael@0: return this; michael@0: michael@0: throw Cr.NS_NOINTERFACE; michael@0: }, michael@0: michael@0: _element: function BPP__element(aID) { michael@0: return document.getElementById("editBMPanel_" + aID); michael@0: }, michael@0: michael@0: onDialogUnload: function BPP_onDialogUnload() { michael@0: // gEditItemOverlay does not exist anymore here, so don't rely on it. michael@0: // Calling removeEventListener with arguments which do not identify any michael@0: // currently registered EventListener on the EventTarget has no effect. michael@0: this._element("tagsSelectorRow") michael@0: .removeEventListener("DOMAttrModified", this, false); michael@0: this._element("folderTreeRow") michael@0: .removeEventListener("DOMAttrModified", this, false); michael@0: this._element("locationField") michael@0: .removeEventListener("input", this, false); michael@0: this._element("feedLocationField") michael@0: .removeEventListener("input", this, false); michael@0: this._element("siteLocationField") michael@0: .removeEventListener("input", this, false); michael@0: }, michael@0: michael@0: onDialogAccept: function BPP_onDialogAccept() { michael@0: // We must blur current focused element to save its changes correctly michael@0: document.commandDispatcher.focusedElement.blur(); michael@0: // The order here is important! We have to uninit the panel first, otherwise michael@0: // late changes could force it to commit more transactions. michael@0: gEditItemOverlay.uninitPanel(true); michael@0: gEditItemOverlay = null; michael@0: this._endBatch(); michael@0: window.arguments[0].performed = true; michael@0: }, michael@0: michael@0: onDialogCancel: function BPP_onDialogCancel() { michael@0: // The order here is important! We have to uninit the panel first, otherwise michael@0: // changes done as part of Undo may change the panel contents and by michael@0: // that force it to commit more transactions. michael@0: gEditItemOverlay.uninitPanel(true); michael@0: gEditItemOverlay = null; michael@0: this._endBatch(); michael@0: PlacesUtils.transactionManager.undoTransaction(); michael@0: window.arguments[0].performed = false; michael@0: }, michael@0: michael@0: /** michael@0: * This method checks to see if the input fields are in a valid state. michael@0: * michael@0: * @returns true if the input is valid, false otherwise michael@0: */ michael@0: _inputIsValid: function BPP__inputIsValid() { michael@0: if (this._itemType == BOOKMARK_ITEM && michael@0: !this._containsValidURI("locationField")) michael@0: return false; michael@0: if (this._isAddKeywordDialog && !this._element("keywordField").value.length) michael@0: return false; michael@0: michael@0: return true; michael@0: }, michael@0: michael@0: /** michael@0: * Determines whether the XUL textbox with the given ID contains a michael@0: * string that can be converted into an nsIURI. michael@0: * michael@0: * @param aTextboxID michael@0: * the ID of the textbox element whose contents we'll test michael@0: * michael@0: * @returns true if the textbox contains a valid URI string, false otherwise michael@0: */ michael@0: _containsValidURI: function BPP__containsValidURI(aTextboxID) { michael@0: try { michael@0: var value = this._element(aTextboxID).value; michael@0: if (value) { michael@0: PlacesUIUtils.createFixedURI(value); michael@0: return true; michael@0: } michael@0: } catch (e) { } michael@0: return false; michael@0: }, michael@0: michael@0: /** michael@0: * [New Item Mode] Get the insertion point details for the new item, given michael@0: * dialog state and opening arguments. michael@0: * michael@0: * The container-identifier and insertion-index are returned separately in michael@0: * the form of [containerIdentifier, insertionIndex] michael@0: */ michael@0: _getInsertionPointDetails: function BPP__getInsertionPointDetails() { michael@0: var containerId = this._defaultInsertionPoint.itemId; michael@0: var indexInContainer = this._defaultInsertionPoint.index; michael@0: michael@0: return [containerId, indexInContainer]; michael@0: }, michael@0: michael@0: /** michael@0: * Returns a transaction for creating a new bookmark item representing the michael@0: * various fields and opening arguments of the dialog. michael@0: */ michael@0: _getCreateNewBookmarkTransaction: michael@0: function BPP__getCreateNewBookmarkTransaction(aContainer, aIndex) { michael@0: var annotations = []; michael@0: var childTransactions = []; michael@0: michael@0: if (this._description) { michael@0: let annoObj = { name : PlacesUIUtils.DESCRIPTION_ANNO, michael@0: type : Ci.nsIAnnotationService.TYPE_STRING, michael@0: flags : 0, michael@0: value : this._description, michael@0: expires: Ci.nsIAnnotationService.EXPIRE_NEVER }; michael@0: let editItemTxn = new PlacesSetItemAnnotationTransaction(-1, annoObj); michael@0: childTransactions.push(editItemTxn); michael@0: } michael@0: michael@0: if (this._loadInSidebar) { michael@0: let annoObj = { name : PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO, michael@0: value : true }; michael@0: let setLoadTxn = new PlacesSetItemAnnotationTransaction(-1, annoObj); michael@0: childTransactions.push(setLoadTxn); michael@0: } michael@0: michael@0: if (this._postData) { michael@0: let postDataTxn = new PlacesEditBookmarkPostDataTransaction(-1, this._postData); michael@0: childTransactions.push(postDataTxn); michael@0: } michael@0: michael@0: //XXX TODO: this should be in a transaction! michael@0: if (this._charSet && !PrivateBrowsingUtils.isWindowPrivate(window)) michael@0: PlacesUtils.setCharsetForURI(this._uri, this._charSet); michael@0: michael@0: let createTxn = new PlacesCreateBookmarkTransaction(this._uri, michael@0: aContainer, michael@0: aIndex, michael@0: this._title, michael@0: this._keyword, michael@0: annotations, michael@0: childTransactions); michael@0: michael@0: return new PlacesAggregatedTransaction(this._getDialogTitle(), michael@0: [createTxn]); michael@0: }, michael@0: michael@0: /** michael@0: * Returns a childItems-transactions array representing the URIList with michael@0: * which the dialog has been opened. michael@0: */ michael@0: _getTransactionsForURIList: function BPP__getTransactionsForURIList() { michael@0: var transactions = []; michael@0: for (var i = 0; i < this._URIs.length; ++i) { michael@0: var uri = this._URIs[i]; michael@0: var title = this._getURITitleFromHistory(uri); michael@0: var createTxn = new PlacesCreateBookmarkTransaction(uri, -1, michael@0: PlacesUtils.bookmarks.DEFAULT_INDEX, michael@0: title); michael@0: transactions.push(createTxn); michael@0: } michael@0: return transactions; michael@0: }, michael@0: michael@0: /** michael@0: * Returns a transaction for creating a new folder item representing the michael@0: * various fields and opening arguments of the dialog. michael@0: */ michael@0: _getCreateNewFolderTransaction: michael@0: function BPP__getCreateNewFolderTransaction(aContainer, aIndex) { michael@0: var annotations = []; michael@0: var childItemsTransactions; michael@0: if (this._URIs.length) michael@0: childItemsTransactions = this._getTransactionsForURIList(); michael@0: michael@0: if (this._description) michael@0: annotations.push(this._getDescriptionAnnotation(this._description)); michael@0: michael@0: return new PlacesCreateFolderTransaction(this._title, aContainer, michael@0: aIndex, annotations, michael@0: childItemsTransactions); michael@0: }, michael@0: michael@0: /** michael@0: * Returns a transaction for creating a new live-bookmark item representing michael@0: * the various fields and opening arguments of the dialog. michael@0: */ michael@0: _getCreateNewLivemarkTransaction: michael@0: function BPP__getCreateNewLivemarkTransaction(aContainer, aIndex) { michael@0: return new PlacesCreateLivemarkTransaction(this._feedURI, this._siteURI, michael@0: this._title, michael@0: aContainer, aIndex); michael@0: }, michael@0: michael@0: /** michael@0: * Dialog-accept code-path for creating a new item (any type) michael@0: */ michael@0: _createNewItem: function BPP__getCreateItemTransaction() { michael@0: var [container, index] = this._getInsertionPointDetails(); michael@0: var txn; michael@0: michael@0: switch (this._itemType) { michael@0: case BOOKMARK_FOLDER: michael@0: txn = this._getCreateNewFolderTransaction(container, index); michael@0: break; michael@0: case LIVEMARK_CONTAINER: michael@0: txn = this._getCreateNewLivemarkTransaction(container, index); michael@0: break; michael@0: default: // BOOKMARK_ITEM michael@0: txn = this._getCreateNewBookmarkTransaction(container, index); michael@0: } michael@0: michael@0: PlacesUtils.transactionManager.doTransaction(txn); michael@0: this._itemId = PlacesUtils.bookmarks.getIdForItemAt(container, index); michael@0: } michael@0: };