📄 utils.js
字号:
if (!parent) return -1; var wasOpen = parent.containerOpen; var result, oldViewer; if (!wasOpen) { result = parent.parentResult; oldViewer = result.viewer; result.viewer = null; parent.containerOpen = true; } var cc = parent.childCount; for (var i = 0; i < cc && parent.getChild(i) != aNode; ++i); if (!wasOpen) { parent.containerOpen = false; result.viewer = oldViewer; } return i < cc ? i : -1; }, /** * String-wraps a result node according to the rules of the specified * content type. * @param aNode * The Result node to wrap (serialize) * @param aType * The content type to serialize as * @param [optional] aOverrideURI * Used instead of the node's URI if provided. * This is useful for wrapping a container as TYPE_X_MOZ_URL, * TYPE_HTML or TYPE_UNICODE. * @param aForceCopy * Does a full copy, resolving folder shortcuts. * @returns A string serialization of the node */ wrapNode: function PU_wrapNode(aNode, aType, aOverrideURI, aForceCopy) { var self = this; // when wrapping a node, we want all the items, even if the original // query options are excluding them. // this can happen when copying from the left hand pane of the bookmarks // organizer function convertNode(cNode) { if (self.nodeIsFolder(cNode) && asQuery(cNode).queryOptions.excludeItems) { var concreteId = self.getConcreteItemId(cNode); return self.getFolderContents(concreteId, false, true).root; } return cNode; } switch (aType) { case this.TYPE_X_MOZ_PLACE: case this.TYPE_X_MOZ_PLACE_SEPARATOR: case this.TYPE_X_MOZ_PLACE_CONTAINER: var writer = { value: "", write: function PU_wrapNode__write(aStr, aLen) { this.value += aStr; } }; self.serializeNodeAsJSONToOutputStream(convertNode(aNode), writer, true, aForceCopy); return writer.value; case this.TYPE_X_MOZ_URL: function gatherDataUrl(bNode) { if (self.nodeIsLivemarkContainer(bNode)) { var siteURI = self.livemarks.getSiteURI(bNode.itemId).spec; return siteURI + NEWLINE + bNode.title; } if (self.nodeIsURI(bNode)) return (aOverrideURI || bNode.uri) + NEWLINE + bNode.title; // ignore containers and separators - items without valid URIs return ""; } return gatherDataUrl(convertNode(aNode)); case this.TYPE_HTML: function gatherDataHtml(bNode) { function htmlEscape(s) { s = s.replace(/&/g, "&"); s = s.replace(/>/g, ">"); s = s.replace(/</g, "<"); s = s.replace(/"/g, """); s = s.replace(/'/g, "'"); return s; } // escape out potential HTML in the title var escapedTitle = bNode.title ? htmlEscape(bNode.title) : ""; if (self.nodeIsLivemarkContainer(bNode)) { var siteURI = self.livemarks.getSiteURI(bNode.itemId).spec; return "<A HREF=\"" + siteURI + "\">" + escapedTitle + "</A>" + NEWLINE; } if (self.nodeIsContainer(bNode)) { asContainer(bNode); var wasOpen = bNode.containerOpen; if (!wasOpen) bNode.containerOpen = true; var childString = "<DL><DT>" + escapedTitle + "</DT>" + NEWLINE; var cc = bNode.childCount; for (var i = 0; i < cc; ++i) childString += "<DD>" + NEWLINE + gatherDataHtml(bNode.getChild(i)) + "</DD>" + NEWLINE; bNode.containerOpen = wasOpen; return childString + "</DL>" + NEWLINE; } if (self.nodeIsURI(bNode)) return "<A HREF=\"" + bNode.uri + "\">" + escapedTitle + "</A>" + NEWLINE; if (self.nodeIsSeparator(bNode)) return "<HR>" + NEWLINE; return ""; } return gatherDataHtml(convertNode(aNode)); } // case this.TYPE_UNICODE: function gatherDataText(bNode) { if (self.nodeIsLivemarkContainer(bNode)) return self.livemarks.getSiteURI(bNode.itemId).spec; if (self.nodeIsContainer(bNode)) { asContainer(bNode); var wasOpen = bNode.containerOpen; if (!wasOpen) bNode.containerOpen = true; var childString = bNode.title + NEWLINE; var cc = bNode.childCount; for (var i = 0; i < cc; ++i) { var child = bNode.getChild(i); var suffix = i < (cc - 1) ? NEWLINE : ""; childString += gatherDataText(child) + suffix; } bNode.containerOpen = wasOpen; return childString; } if (self.nodeIsURI(bNode)) return (aOverrideURI || bNode.uri); if (self.nodeIsSeparator(bNode)) return "--------------------"; return ""; } return gatherDataText(convertNode(aNode)); }, /** * Unwraps data from the Clipboard or the current Drag Session. * @param blob * A blob (string) of data, in some format we potentially know how * to parse. * @param type * The content type of the blob. * @returns An array of objects representing each item contained by the source. */ unwrapNodes: function PU_unwrapNodes(blob, type) { // We split on "\n" because the transferable system converts "\r\n" to "\n" var nodes = []; switch(type) { case this.TYPE_X_MOZ_PLACE: case this.TYPE_X_MOZ_PLACE_SEPARATOR: case this.TYPE_X_MOZ_PLACE_CONTAINER: var JSON = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON); nodes = JSON.decode("[" + blob + "]"); break; case this.TYPE_X_MOZ_URL: var parts = blob.split("\n"); // data in this type has 2 parts per entry, so if there are fewer // than 2 parts left, the blob is malformed and we should stop // but drag and drop of files from the shell has parts.length = 1 if (parts.length != 1 && parts.length % 2) break; for (var i = 0; i < parts.length; i=i+2) { var uriString = parts[i]; var titleString = ""; if (parts.length > i+1) titleString = parts[i+1]; else { // for drag and drop of files, try to use the leafName as title try { titleString = this._uri(uriString).QueryInterface(Ci.nsIURL) .fileName; } catch (e) {} } // note: this._uri() will throw if uriString is not a valid URI if (this._uri(uriString)) { nodes.push({ uri: uriString, title: titleString ? titleString : uriString , type: this.TYPE_X_MOZ_URL }); } } break; case this.TYPE_UNICODE: var parts = blob.split("\n"); for (var i = 0; i < parts.length; i++) { var uriString = parts[i]; // note: this._uri() will throw if uriString is not a valid URI if (uriString != "" && this._uri(uriString)) nodes.push({ uri: uriString, title: uriString, type: this.TYPE_X_MOZ_URL }); } break; default: LOG("Cannot unwrap data of type " + type); throw Cr.NS_ERROR_INVALID_ARG; } return nodes; }, /** * Generates a nsINavHistoryResult for the contents of a folder. * @param folderId * The folder to open * @param [optional] excludeItems * True to hide all items (individual bookmarks). This is used on * the left places pane so you just get a folder hierarchy. * @param [optional] expandQueries * True to make query items expand as new containers. For managing, * you want this to be false, for menus and such, you want this to * be true. * @returns A nsINavHistoryResult containing the contents of the * folder. The result.root is guaranteed to be open. */ getFolderContents: function PU_getFolderContents(aFolderId, aExcludeItems, aExpandQueries) { var query = this.history.getNewQuery(); query.setFolders([aFolderId], 1); var options = this.history.getNewQueryOptions(); options.excludeItems = aExcludeItems; options.expandQueries = aExpandQueries; var result = this.history.executeQuery(query, options); result.root.containerOpen = true; return result; }, /** * Fetch all annotations for a URI, including all properties of each * annotation which would be required to recreate it. * @param aURI * The URI for which annotations are to be retrieved. * @return Array of objects, each containing the following properties: * name, flags, expires, mimeType, type, value */ getAnnotationsForURI: function PU_getAnnotationsForURI(aURI) { var annosvc = this.annotations; var annos = [], val = null; var annoNames = annosvc.getPageAnnotationNames(aURI, {}); for (var i = 0; i < annoNames.length; i++) { var flags = {}, exp = {}, mimeType = {}, storageType = {}; annosvc.getPageAnnotationInfo(aURI, annoNames[i], flags, exp, mimeType, storageType); if (storageType.value == annosvc.TYPE_BINARY) { var data = {}, length = {}, mimeType = {}; annosvc.getPageAnnotationBinary(aURI, annoNames[i], data, length, mimeType); val = data.value; } else val = annosvc.getPageAnnotation(aURI, annoNames[i]); annos.push({name: annoNames[i], flags: flags.value, expires: exp.value, mimeType: mimeType.value, type: storageType.value, value: val}); } return annos; }, /** * Fetch all annotations for an item, including all properties of each * annotation which would be required to recreate it. * @param aItemId * The identifier of the itme for which annotations are to be * retrieved. * @return Array of objects, each containing the following properties: * name, flags, expires, mimeType, type, value */ getAnnotationsForItem: function PU_getAnnotationsForItem(aItemId) { var annosvc = this.annotations; var annos = [], val = null; var annoNames = annosvc.getItemAnnotationNames(aItemId, {}); for (var i = 0; i < annoNames.length; i++) { var flags = {}, exp = {}, mimeType = {}, storageType = {}; annosvc.getItemAnnotationInfo(aItemId, annoNames[i], flags, exp, mimeType, storageType); if (storageType.value == annosvc.TYPE_BINARY) { var data = {}, length = {}, mimeType = {}; annosvc.geItemAnnotationBinary(aItemId, annoNames[i], data, length, mimeType); val = data.value; } else val = annosvc.getItemAnnotation(aItemId, annoNames[i]); annos.push({name: annoNames[i], flags: flags.value, expires: exp.value, mimeType: mimeType.value, type: storageType.value, value: val}); } return annos; }, /** * Annotate a URI with a batch of annotations. * @param aURI * The URI for which annotations are to be set. * @param aAnnotations * Array of objects, each containing the following properties: * name, flags, expires, type, mimeType (only used for binary * annotations) value. */ setAnnotationsForURI: function PU_setAnnotationsForURI(aURI, aAnnos) { var annosvc = this.annotations; aAnnos.forEach(function(anno) { var flags = ("flags" in anno) ? anno.flags : 0; var expires = ("expires" in anno) ? anno.expires : Ci.nsIAnnotationService.EXPIRE_NEVER; if (anno.type == annosvc.TYPE_BINARY) { annosvc.setPageAnnotationBinary(aURI, anno.name, anno.value, anno.value.length, anno.mimeType, flags, expires); } else annosvc.setPageAnnotation(aURI, anno.name, anno.value, flags, expires); }); }, /** * Annotate an item with a batch of annotations. * @param aItemId * The identifier of the item for which annotations are to be set * @param aAnnotations * Array of objects, each containing the following properties: * name, flags, expires, type, mimeType (only used for binary * annotations) value. */ setAnnotationsForItem: function PU_setAnnotationsForItem(aItemId, aAnnos) { var annosvc = this.annotations; aAnnos.forEach(function(anno) { var flags = ("flags" in anno) ? anno.flags : 0; var expires = ("expires" in anno) ? anno.expires : Ci.nsIAnnotationService.EXPIRE_NEVER; if (anno.type == annosvc.TYPE_BINARY) { annosvc.setItemAnnotationBinary(aItemId, anno.name, anno.value, anno.value.length, anno.mimeType, flags, expires); } else { annosvc.setItemAnnotation(aItemId, anno.name, anno.value, flags, expires); } }); }, /** * Helper for getting a serialized Places query for a particular folder. * @param aFolderId The folder id to get a query for. * @return string serialized place URI */ getQueryStringForFolder: function PU_getQueryStringForFolder(aFolderId) { var options = this.history.getNewQueryOptions(); var query = this.history.getNewQuery(); query.setFolders([aFolderId], 1); return this.history.queriesToQueryString([query], 1, options); }, // identifier getters for special folders get placesRootId() { delete this.placesRootId; return this.placesRootId = this.bookmarks.placesRoot; }, get bookmarksMenuFolderId() { delete this.bookmarksMenuFolderId; return this.bookmarksMenuFolderId = this.bookmarks.bookmarksMenuFolder; }, get toolbarFolderId() { delete this.toolbarFolderId; return this.toolbarFolderId = this.bookmarks.toolbarFolder; }, get tagsFolderId() { delete this.tagsFolderId; return this.tagsFolderId = this.bookmarks.tagsFolder; }, get unfiledBookmarksFolderId() { delete this.unfiledBookmarksFolderId; return this.unfiledBookmarksFolderId = this.bookmarks.unfiledBookmarksFolder; }, /** * Set the POST data associated with a bookmark, if any. * Used by POST keywords. * @param aBookmarkId * @returns string of POST data */ setPostDataForBookmark: function PU_setPostDataForBookmark(aBookmarkId, aPostData) { const annos = this.annotations; if (aPostData) annos.setItemAnnotation(aBookmarkId, POST_DATA_ANNO, aPostData, 0, Ci.nsIAnnotationService.EXPIRE_NEVER); else if (annos.itemHasAnnotation(aBookmarkId, POST_DATA_ANNO)) annos.removeItemAnnotation(aBookmarkId, POST_DATA_ANNO); },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -