?? feed-subscriptions.js
字號:
ds.Change(resource, FZ_DESTFOLDER, currentParentResource, newParentResource); // we need to update the feed url attributes on the databases for each folder updateFolderFeedUrl(currentParentResource.QueryInterface(Components.interfaces.nsIMsgFolder), currentItem.url, true); // remove our feed url property from the current folder updateFolderFeedUrl(newParentResource.QueryInterface(Components.interfaces.nsIMsgFolder), currentItem.url, false); // add our feed url property to the new folder // Finally, update our view layer this.mView.removeItemAtIndex(aOldFeedIndex, 1); if (aNewParentIndex > aOldFeedIndex) aNewParentIndex--; currentItem.level = newParentItem.level + 1; newParentItem.children.push(currentItem); var indexOfNewItem = aNewParentIndex + newParentItem.children.length;; if (!newParentItem.open) // force open the container this.mView.toggleOpenState(aNewParentIndex); else { this.mFeedContainers.splice(indexOfNewItem, 0, currentItem); this.mView.mRowCount++; this.mTree.treeBoxObject.rowCountChanged(indexOfNewItem, 1); } gFeedSubscriptionsWindow.mTree.view.selection.select(indexOfNewItem) }, beginDrag: function (aEvent) { // get the selected feed article (if there is one) var seln = this.mView.selection; if (seln.count != 1) return; // only initiate a drag if the item is a feed (i.e. ignore folders/containers) var item = this.mView.getItemAtIndex(seln.currentIndex); if (!item || item.container) return; var transfer = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable); var transArray = Components.classes["@mozilla.org/supports-array;1"].createInstance(Components.interfaces.nsISupportsArray); var dragData = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString); transfer.addDataFlavor("text/x-moz-feed-index"); // i made this flavor type up dragData.data = seln.currentIndex.toString(); transfer.setTransferData ( "text/x-moz-feed-index", dragData, seln.currentIndex.toString() * 2 ); // doublebyte byte data transArray.AppendElement(transfer.QueryInterface(Components.interfaces.nsISupports)); var dragService = Components.classes["@mozilla.org/widget/dragservice;1"].getService().QueryInterface(nsIDragService); dragService.invokeDragSession ( aEvent.target, transArray, null, nsIDragService.DRAGDROP_ACTION_MOVE); }, mFeedDownloadCallback: { downloaded: function(feed, aErrorCode) { // feed is null if our attempt to parse the feed failed if (aErrorCode == kNewsBlogSuccess) { updateStatusItem('progressMeter', 100); // if we get here...we should always have a folder by now...either // in feed.folder or FeedItems created the folder for us.... updateFolderFeedUrl(feed.folder, feed.url, false); // add feed just adds the feed we have validated and downloaded to our datasource // it also flushes the subscription datasource addFeed(feed.url, feed.name, feed.folder); // now add the feed to our view refreshSubscriptionView(); } else if (aErrorCode == kNewsBlogInvalidFeed) // the feed was bad... window.alert(gFeedSubscriptionsWindow.mBundle.getFormattedString('newsblog-invalidFeed', [feed.url])); else if (aErrorCode == kNewsBlogRequestFailure) window.alert(gFeedSubscriptionsWindow.mBundle.getFormattedString('newsblog-networkError', [feed.url])); // re-enable the add button now that we are done subscribing document.getElementById('addFeed').removeAttribute('disabled'); // our operation is done...clear out the status text and progressmeter setTimeout(clearStatusInfo, 1000); }, // this gets called after the RSS parser finishes storing a feed item to disk // aCurrentFeedItems is an integer corresponding to how many feed items have been downloaded so far // aMaxFeedItems is an integer corresponding to the total number of feed items to download onFeedItemStored: function (feed, aCurrentFeedItems, aMaxFeedItems) { updateStatusItem('statusText', gFeedSubscriptionsWindow.mBundle.getFormattedString("subscribe-fetchingFeedItems", [aCurrentFeedItems, aMaxFeedItems])); this.onProgress(feed, aCurrentFeedItems, aMaxFeedItems); }, onProgress: function(feed, aProgress, aProgressMax) { updateStatusItem('progressMeter', (aProgress * 100) / aProgressMax); }, }, exportOPML: function() { if (this.mRSSServer.rootFolder.hasSubFolders) { var opmlDoc = document.implementation.createDocument("","opml",null); var opmlRoot = opmlDoc.documentElement; opmlRoot.setAttribute("version","1.0"); this.generatePPSpace(opmlRoot," "); // Make the <head> element var head = opmlDoc.createElement("head"); this.generatePPSpace(head, " "); var title = opmlDoc.createElement("title"); title.appendChild(opmlDoc.createTextNode(this.mBundle.getString("subscribe-OPMLExportFileTitle"))); head.appendChild(title); this.generatePPSpace(head, " "); var dt = opmlDoc.createElement("dateCreated"); dt.appendChild(opmlDoc.createTextNode((new Date()).toGMTString())); head.appendChild(dt); this.generatePPSpace(head, " "); opmlRoot.appendChild(head); this.generatePPSpace(opmlRoot, " "); //add <outline>s to the <body> var body = opmlDoc.createElement("body"); this.generateOutline(this.mRSSServer.rootFolder, body, 4); this.generatePPSpace(body, " "); opmlRoot.appendChild(body); this.generatePPSpace(opmlRoot, ""); var serial=new XMLSerializer(); var rv = pickSaveAs(this.mBundle.getString("subscribe-OPMLExportTitle"),'$all', this.mBundle.getString("subscribe-OPMLExportFileName")); if(rv.reason == PICK_CANCEL) return; else if(rv) { //debug("opml:\n"+serial.serializeToString(opmlDoc)+"\n"); var file = new LocalFile(rv.file, MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE); serial.serializeToStream(opmlDoc,file.outputStream,'utf-8'); file.close(); } } }, generatePPSpace: function(aNode, indentString) { aNode.appendChild(aNode.ownerDocument.createTextNode("\n")); aNode.appendChild(aNode.ownerDocument.createTextNode(indentString)); }, generateOutline: function(baseFolder, parent, indentLevel) { var folderEnumerator = baseFolder.GetSubFolders(); var done = false; // pretty printing var indentString = ""; for(i = 0; i < indentLevel; i++) indentString = indentString + " "; while (!done) { var folder = folderEnumerator.currentItem().QueryInterface(Components.interfaces.nsIMsgFolder); if (folder && !folder.getFlag(MSG_FOLDER_FLAG_TRASH)) { var outline; if(folder.hasSubFolders) { // Make a mostly empty outline element outline = parent.ownerDocument.createElement("outline"); outline.setAttribute("text",folder.prettiestName); this.generateOutline(folder, outline, indentLevel+2); // recurse this.generatePPSpace(parent, indentString); this.generatePPSpace(outline, indentString); parent.appendChild(outline); } else { // Add outline elements with xmlUrls var feeds = this.getFeedsInFolder(folder); for (feed in feeds) { outline = this.opmlFeedToOutline(feeds[feed],parent.ownerDocument); this.generatePPSpace(parent, indentString); parent.appendChild(outline); } } } try { folderEnumerator.next(); } catch (ex) { done = true; } } }, opmlFeedToOutline: function(aFeed,aDoc) { var outRv = aDoc.createElement("outline"); outRv.setAttribute("title",aFeed.title); outRv.setAttribute("text",aFeed.title); outRv.setAttribute("type","rss"); outRv.setAttribute("version","RSS"); outRv.setAttribute("xmlUrl",aFeed.url); outRv.setAttribute("htmlUrl",aFeed.link); return outRv; }, importOPML: function() { var rv = pickOpen(this.mBundle.getString("subscribe-OPMLImportTitle"), '$xml $opml $all'); if(rv.reason == PICK_CANCEL) return; var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(IPS); var stream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream); var opmlDom = null; // read in file as raw bytes, so Expat can do the decoding for us try{ stream.init(rv.file, MODE_RDONLY, PERM_IROTH, 0); var parser = new DOMParser(); opmlDom = parser.parseFromStream(stream, null, stream.available(), 'application/xml'); }catch(e){ return promptService.alert(window, null, this.mBundle.getString("subscribe-errorOpeningFile")); }finally{ stream.close(); } // return if the user didn't give us an OPML file if(!opmlDom || !(opmlDom.documentElement.tagName == "opml")) return promptService.alert(window, null, this.mBundle.getFormattedString("subscribe-errorInvalidOPMLFile", [rv.file.leafName])); var outlines = opmlDom.getElementsByTagName("body")[0].getElementsByTagName("outline"); var feedsAdded = false; for (var index = 0; index < outlines.length; index++) { var outline = outlines[index]; // XXX only dealing with flat OPML files for now. // We still need to add support for grouped files. if(outline.hasAttribute("xmlUrl") || outline.hasAttribute("url")) { var userAddedFeed = false; var newFeedUrl = outline.getAttribute("xmlUrl") || outline.getAttribute("url") var defaultQuickMode = this.mRSSServer.getBoolAttribute('quickMode'); var feedProperties = { feedName: this.findOutlineTitle(outline), feedLocation: newFeedUrl, serverURI: this.mRSSServer.serverURI, serverPrettyName: this.mRSSServer.prettyName, folderURI: "", quickMode: this.mRSSServer.getBoolAttribute('quickMode')}; debug("importing feed: "+ feedProperties.feedName); // Silently skip feeds that are already subscribed to. if (!feedAlreadyExists(feedProperties.feedLocation, this.mRSSServer)) { var feed = this.storeFeed(feedProperties); if(feed) { feed.title = feedProperties.feedName; if(outline.hasAttribute("htmlUrl")) feed.link = outline.getAttribute("htmlUrl"); feed.createFolder(); updateFolderFeedUrl(feed.folder, feed.url, false); // add feed adds the feed we have validated and downloaded to our datasource // it also flushes the subscription datasource addFeed(feed.url, feed.name, feed.folder); feedsAdded = true; } } } } if (!outlines.length || !feedsAdded) return promptService.alert(window, null, this.mBundle.getFormattedString("subscribe-errorInvalidOPMLFile", [rv.file.leafName])); //add the new feeds to our view refreshSubscriptionView(); }, findOutlineTitle: function(anOutline) { var outlineTitle; if (anOutline.hasAttribute("text")) outlineTitle = anOutline.getAttribute("text"); else if (anOutline.hasAttribute("title")) outlineTitle = anOutline.getAttribute("title"); else if (anOutline.hasAttribute("xmlUrl")) outlineTitle = anOutline.getAttribute("xmlUrl"); return outlineTitle; },};// opens the feed properties dialogfunction openFeedEditor(aFeedProperties){ window.openDialog('chrome://messenger-newsblog/content/feed-properties.xul', 'feedproperties', 'modal,titlebar,chrome,center', aFeedProperties); return aFeedProperties;} function refreshSubscriptionView(){ gFeedSubscriptionsWindow.loadSubscriptions(); gFeedSubscriptionsWindow.mTree.treeBoxObject.invalidate(); gFeedSubscriptionsWindow.mTree.treeBoxObject.view = gFeedSubscriptionsWindow.mView; if (gFeedSubscriptionsWindow.mView.rowCount > 0) gFeedSubscriptionsWindow.mTree.view.selection.select(0);}function processDrop(){ gFeedSubscriptionsWindow.addFeed(gFeedSubscriptionsWindow.mView.mDropUrl, gFeedSubscriptionsWindow.mView.mDropFolderUrl);}// status helper routinesfunction updateStatusItem(aID, aValue){ var el = document.getElementById(aID); if (el.getAttribute('collapsed')) el.removeAttribute('collapsed'); el.value = aValue;}function clearStatusInfo(){ document.getElementById('statusText').value = ""; document.getElementById('progressMeter').collapsed = true;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -