diff options
author | Ruben Rodriguez <ruben@gnu.org> | 2015-11-28 15:24:36 -0600 |
---|---|---|
committer | Ruben Rodriguez <ruben@gnu.org> | 2015-11-28 16:27:06 -0600 |
commit | e4a3586a14996bbece3b26c9e3b7704ea6af8615 (patch) | |
tree | 499bdd16b3a90c30b01e4b47a5882d13b4800f50 /data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui | |
parent | 4dbc2fae927bb02ef243c87938e638af9afee8fa (diff) |
LibreJS upgraded to 6.0.10
Diffstat (limited to 'data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui')
12 files changed, 1148 insertions, 0 deletions
diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/awesomebar.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/awesomebar.js new file mode 100644 index 0000000..641dc14 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/awesomebar.js @@ -0,0 +1,205 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const {Cc, Ci, Cu, Cm, components} = require('chrome'); +Cu.import("resource://gre/modules/AddonManager.jsm", this); +Cu.import("resource://gre/modules/Services.jsm", this); +Cu.import("resource://gre/modules/XPCOMUtils.jsm", this); + +var {unload} = require("../addon/unload"); +var {listen} = require("../xul/listen"); +var {watchWindows} = require("window-watcher"); +var {clearTimeout, setTimeout} = require("timer"); + +let handlers = []; + +// public api for adding a keyword and search handler +// TODO: validate, yo +exports.AwesomeBarSuggestion = function AwesomeBarSuggestion(options) { + var i = handlers.push(options) - 1; + var destroyed = false; + + return { + destroy: function() { + if (destroyed) return; + destroyed = true; + handlers[i] = null; + } + }; +}; + +// Bool check if a given string matches a given handler +function handlerMatch(query, handler) !!(handler && handler.matches.test(query)); + +// Get first registered handler that matches a given string +function getMatchingHandler(query) handlers.filter(function(handler) handlerMatch(query, handler)).shift() + +// Add functionality to search from the location bar and hook up autocomplete +function addAddressBarSearch(window) { + let {change} = makeWindowHelpers(window); + let {BrowserUI, gBrowser, gURLBar} = window; + + // Check the input to see if the add-on icon should be shown + // Called when the location bar fires the input event + function onLocationBarInput() { + if (skipCheck()) + return; + + let icon = ""; + let handler = getMatchingHandler(urlbar.value); + if (handler && handler.icon) + icon = handler.icon; + setIcon(icon); + } + + // Implement these functions depending on the platform + let setIcon, skipCheck, urlbar; + + // mobile + if (gBrowser == null) { + setIcon = function(url) BrowserUI._updateIcon(url); + skipCheck = function() false; + urlbar = BrowserUI._edit; + + // Check the input on various events + listen(window, BrowserUI._edit, "input", onLocationBarInput); + + // Convert inputs to twitter urls + change(window.Browser, "getShortcutOrURI", function(orig) { + return function(uri, data) { + return orig.call(this, uri, data); + }; + }); + } + // desktop + else { + setIcon = function(url) window.PageProxySetIcon(url); + skipCheck = function() gURLBar.getAttribute("pageproxystate") == "valid" && + !gURLBar.hasAttribute("focused"); + urlbar = gURLBar; + + // Check the input on various events + listen(window, gURLBar, "input", onLocationBarInput); + listen(window, gBrowser.tabContainer, "TabSelect", onLocationBarInput); + + // Convert inputs to twitter urls + change(gURLBar, "_canonizeURL", function(orig) { + return function(event) { + return orig.call(this, event); + }; + }); + } + + // Provide a way to set the autocomplete search engines and initialize + function setSearch(engines) { + urlbar.setAttribute("autocompletesearch", engines); + urlbar.mSearchNames = null; + urlbar.initSearchNames(); + }; + + // Add in the twitter search and remove on cleanup + let origSearch = urlbar.getAttribute("autocompletesearch"); + setSearch(require('self').id + " " + origSearch); + unload(function() setSearch(origSearch)); +} + +// Add an autocomplete search engine to provide location bar suggestions +function addAutocomplete() { + const contract = "@mozilla.org/autocomplete/search;1?name=" + require('self').id; + const desc = "Jetpack Autocomplete"; + const uuid = components.ID("504A8466-8D3D-11E0-A57E-D2F94824019B"); + + // Keep a timer to send a delayed no match + let timer; + function clearTimer() { + if (timer != null) + clearTimeout(timer); + timer = null; + } + + // call back in one second + function setTimer(callback) { + timer = setTimeout(callback, 1000); + } + + // Implement the autocomplete search that handles twitter queries + let search = { + createInstance: function(outer, iid) search.QueryInterface(iid), + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIAutoCompleteSearch]), + + // Handle searches from the location bar + startSearch: function(query, param, previous, listener) { + + // Always clear the timer on a new search + clearTimer(); + + function suggest(o, done) { + listener.onSearchResult(search, { + getCommentAt: function() o.title, + getImageAt: function() o.favicon, + getLabelAt: function() o.label || o.url, + getValueAt: function() o.url, + getStyleAt: function() "favicon", + get matchCount() 1, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIAutoCompleteResult]), + removeValueAt: function() {}, + searchResult: Ci.nsIAutoCompleteResult.RESULT_SUCCESS, + get searchString() query, + }); + } + + // TODO: if no search yet, but matched keyword, show example text + + // if there's a query string and a match + if (query.length) { + let handler = getMatchingHandler(query); + if (handler) { + if (query) { + handler.onSearch(query, suggest); + } + } + } + // Send a delayed NOMATCH so the autocomplete doesn't close early + else { + setTimer(function() { + listener.onSearchResult(search, { + searchResult: Ci.nsIAutoCompleteResult.RESULT_NOMATCH, + }); + }); + } + }, + + // Nothing to cancel other than a delayed search as results are synchronous + stopSearch: function() { + clearTimer(); + }, + }; + + // Register this autocomplete search service and clean up when necessary + const registrar = Ci.nsIComponentRegistrar; + Cm.QueryInterface(registrar).registerFactory(uuid, desc, contract, search); + unload(function() { + Cm.QueryInterface(registrar).unregisterFactory(uuid, search); + }); +} + +// Add support to the browser +watchWindows(addAddressBarSearch); +addAutocomplete(); + +// Take a window and create various helper properties and functions +function makeWindowHelpers(window) { + // Replace a value with another value or a function of the original value + function change(obj, prop, val) { + let orig = obj[prop]; + obj[prop] = typeof val == "function" ? val(orig) : val; + unload(function() obj[prop] = orig, window); + } + + return { + change: change, + }; +} diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/findbar/suggestion.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/findbar/suggestion.js new file mode 100644 index 0000000..efbc665 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/findbar/suggestion.js @@ -0,0 +1,77 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const winUtils = require('sdk/deprecated/window-utils'); +const { Class } = require('sdk/core/heritage'); +const { validateOptions } = require('sdk/deprecated/api-utils'); +const { isBrowser } = require('sdk/window/utils'); +const { unload } = require('../../addon/unload'); +const { listen } = require('../../xul/listen'); + +const findsuggestionNS = require('sdk/core/namespace').ns(); +const NS_XUL = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'; + +function FindSuggestionOptions(options) { + return validateOptions(options, { + word: { is: ['string'] }, + //onClick: { is: ['undefined', 'function'] } + }); +} + +const FindSuggestion = Class({ + initialize: function(options) { + options = findsuggestionNS(this).options = FindSuggestionOptions(options); + let unloaders = findsuggestionNS(this).unloaders = []; + + winUtils.WindowTracker({ + onTrack: function(window) { + if (!isBrowser(window)) return; + + let findBar = window.gFindBar; + let findContainer = findBar.getElement('findbar-container'); + + // Show these suggestions in the findbar + let ele = window.document.createElementNS(NS_XUL, 'label'); + ele.setAttribute('value', options.word); + ele.style.margin = '2px'; + ele.style.cursor = 'pointer'; + ele.style.fontWeight = 'bold'; + findContainer.appendChild(ele); + + ele.addEventListener('click', suggestionClick.bind({ + findBar: findBar + }), false); + + // Clear out the suggestions when removing the add-on + function clearSuggestion() { + findContainer.removeChild(ele); + } + + // save a destroyer + unloaders.push( + destroyer.bind(null, unload(clearSuggestion, window), clearSuggestion)); + } + }); + }, + destroy: function() findsuggestionNS(this).unloaders.forEach(function(x) x()) +}); +exports.FindSuggestion = FindSuggestion; + +function suggestionClick(event) { + let suggestion = event.target.value; + let findField = this.findBar._findField; + + if (findField.value === suggestion) { + this.findBar.onFindAgainCommand(false); + } + else { + findField.value = suggestion; + findBar._find(); + } +} +function destroyer(remover, clearSuggestion) { + clearSuggestion(); + remover(); +} diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/menuitems.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/menuitems.js new file mode 100644 index 0000000..5e34106 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/menuitems.js @@ -0,0 +1,218 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const windowUtils = require("sdk/deprecated/window-utils"); +const { Class } = require("sdk/core/heritage"); +const { validateOptions } = require("sdk/deprecated/api-utils"); +const { on, emit, once, off } = require("sdk/event/core"); +const { isBrowser } = require("sdk/window/utils"); +const { EventTarget } = require('sdk/event/target'); +const menuitemNS = require("sdk/core/namespace").ns(); + +const { unload } = require('../addon/unload'); + +const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + +function MenuitemOptions(options) { + return validateOptions(options, { + id: { is: ['string'] }, + menuid: { is: ['undefined', 'string'] }, + insertbefore: { is: ['undefined', 'string', 'object', 'number'] }, + label: { is: ["string"] }, + include: { is: ['string', 'undefined'] }, + disabled: { is: ["undefined", "boolean"], map: function(v) !!v}, + accesskey: { is: ["undefined", "string"] }, + key: { is: ["undefined", "string"] }, + checked: { is: ['undefined', 'boolean'] }, + className: { is: ["undefined", "string"] }, + onCommand: { is: ['undefined', 'function'] }, + useChrome: { map: function(v) !!v } + }); +} + +let Menuitem = Class({ + extends: EventTarget, + initialize: function(options) { + options = menuitemNS(this).options = MenuitemOptions(options); + EventTarget.prototype.initialize.call(this, options); + + menuitemNS(this).destroyed = false; + menuitemNS(this).unloaders = []; + menuitemNS(this).menuitems = addMenuitems(this, options).menuitems; + }, + get id() menuitemNS(this).options.id, + get label() menuitemNS(this).options.label, + set label(val) updateProperty(this, 'label', val), + get checked() menuitemNS(this).options.checked, + set checked(val) updateProperty(this, 'checked', !!val), + get disabled() menuitemNS(this).options.disabled, + set disabled(val) updateProperty(this, 'disabled', !!val), + get key() menuitemNS(this).options.key, + set key(val) updateProperty(this, 'key', val), + clone: function (overwrites) { + let opts = Object.clone(menuitemNS(this).options); + for (let key in overwrites) { + opts[key] = ovrewrites[key]; + } + return Menuitem(opts); + }, + get menuid() menuitemNS(this).options.menuid, + set menuid(val) { + let options = menuitemNS(this).options; + options.menuid = val; + + forEachMI(function(menuitem, i, $) { + updateMenuitemParent(menuitem, options, $); + }); + }, + destroy: function() { + if (!menuitemNS(this).destroyed) { + menuitemNS(this).destroyed = true; + menuitemNS(this).unloaders.forEach(function(u) u()); + menuitemNS(this).unloaders = null; + menuitemNS(this).menuitems = null; + } + return true; + } +}); + +function addMenuitems(self, options) { + let menuitems = []; + + // setup window tracker + windowUtils.WindowTracker({ + onTrack: function (window) { + if (menuitemNS(self).destroyed) return; + if (options.include) { + if (options.include != window.location) return; + } + else if (!isBrowser(window)) { + return; + } + + // add the new menuitem to a menu + var menuitem = updateMenuitemAttributes( + window.document.createElementNS(NS_XUL, "menuitem"), options); + var menuitems_i = menuitems.push(menuitem) - 1; + + // add the menutiem to the ui + let added = updateMenuitemParent(menuitem, options, function(id) window.document.getElementById(id)); + + menuitem.addEventListener("command", function() { + if (!self.disabled) + emit(self, 'command', options.useChrome ? window : null); + }, true); + + // add unloader + let unloader = function unloader() { + menuitem.parentNode && menuitem.parentNode.removeChild(menuitem); + menuitems[menuitems_i] = null; + }; + + menuitemNS(self).unloaders.push(function() { + remover(); + unloader(); + }); + + let remover = unload(unloader, window); + } + + }); + + return { menuitems: menuitems }; +} + +function updateMenuitemParent(menuitem, options, $) { + // add the menutiem to the ui + if (Array.isArray(options.menuid)) { + let ids = options.menuid; + for (var len = ids.length, i = 0; i < len; i++) { + if (tryParent($(ids[i]), menuitem, options.insertbefore)) + return true; + } + } + else { + return tryParent($(options.menuid), menuitem, options.insertbefore); + } + + return false; +} + +function updateMenuitemAttributes(menuitem, options) { + menuitem.setAttribute("id", options.id); + menuitem.setAttribute("label", options.label); + + if (options.accesskey) + menuitem.setAttribute("accesskey", options.accesskey); + + if (options.key) + menuitem.setAttribute("key", options.key); + + menuitem.setAttribute("disabled", !!options.disabled); + + if (options.image) { + menuitem.classList.add("menuitem-iconic"); + menuitem.style.listStyleImage = "url('" + options.image + "')"; + } + + if (options.checked) + menuitem.setAttribute('checked', options.checked); + + if (options.className) + options.className.split(/\s+/).forEach(function(name) menuitem.classList.add(name)); + + return menuitem; +} + +function updateProperty(menuitem, key, val) { + menuitemNS(menuitem).options[key] = val; + + forEachMI(function(menuitem) { + menuitem.setAttribute(key, val); + }, menuitem); + return val; +} + +function forEachMI(callback, menuitem) { + menuitemNS(menuitem).menuitems.forEach(function(mi, i) { + if (!mi) return; + callback(mi, i, function(id) mi.ownerDocument.getElementById(id)); + }); +} + +function tryParent(parent, menuitem, before) { + if (parent) { + if (!before) { + parent.appendChild(menuitem); + return true; + } + + parent.insertBefore(menuitem, insertBefore(parent, before)); + return true; + } + + return false; +} + +function insertBefore(parent, insertBefore) { + if (typeof insertBefore == "number") { + switch (insertBefore) { + case MenuitemExport.FIRST_CHILD: + return parent.firstChild; + } + return null; + } + else if (typeof insertBefore == "string") { + return parent.querySelector("#" + insertBefore); + } + return insertBefore; +} + +function MenuitemExport(options) { + return Menuitem(options); +} +MenuitemExport.FIRST_CHILD = 1; + +exports.Menuitem = MenuitemExport; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/actions.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/actions.js new file mode 100644 index 0000000..12076ca --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/actions.js @@ -0,0 +1,9 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const method = require('method/core'); + +exports.show = method('show'); +exports.hide = method('hide'); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/contract.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/contract.js new file mode 100644 index 0000000..244e60e --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/contract.js @@ -0,0 +1,30 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { contract } = require('sdk/util/contract'); +const { isValidURI } = require('sdk/url'); + +let string = { is: ['string'] }; + +exports.contract = contract({ + id: { + is: [ 'string' ], + ok: function (v) /^[a-z0-9-_]+$/i.test(v), + msg: 'The option "id" must be a valid alphanumeric id (hyphens and ' + + 'underscores are allowed).' + }, + title: { + is: [ 'string' ], + ok: function (v) v.length + }, + url: { + is: [ 'string' ], + ok: function(url) { + return isValidURI(url); + }, + map: function(v) v.toString(), + msg: 'The option "url" must be a valid URI.' + } +}); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/state.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/state.js new file mode 100644 index 0000000..05225da --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/state.js @@ -0,0 +1,8 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const method = require('method/core'); + +exports.isShowing = method('isShowing'); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/utils.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/utils.js new file mode 100644 index 0000000..4576c5b --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/sidebar/utils.js @@ -0,0 +1,31 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { getMostRecentBrowserWindow } = require('sdk/window/utils'); + +const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + +function create(window, details) { + let { document } = window; + + let menuitem = document.createElementNS(XUL_NS, 'menuitem'); + menuitem.setAttribute('id', details.id); + menuitem.setAttribute('label', details.title); + menuitem.setAttribute('checked', 'false'); + menuitem.setAttribute('sidebarurl', details.sidebarurl); + menuitem.setAttribute('type', 'checkbox'); + menuitem.setAttribute('group', 'sidebar'); + menuitem.setAttribute('autoCheck', 'false'); + + document.getElementById('viewSidebarMenu').appendChild(menuitem); + + return menuitem; +} +exports.create = create; + +function dispose(menuitem) { + menuitem.parentNode.removeChild(menuitem); +} +exports.dispose = dispose; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/toolbarbutton.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/toolbarbutton.js new file mode 100644 index 0000000..38bfb2e --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/toolbarbutton.js @@ -0,0 +1,179 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const winUtils = require("sdk/deprecated/window-utils"); +const { isBrowser } = require('sdk/window/utils'); +const { Class } = require('sdk/core/heritage'); +const TBB_NS = require('sdk/core/namespace').ns(); + +const { validate: validateOptions } = require('./validate'); +const { getToolbarButtons, toolbarbuttonExists } = require('./utils'); +const { unload } = require("../addon/unload"); +const { listen } = require("../xul/listen"); + +const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + +exports.ToolbarButton = Class({ + initialize: function(options) { + TBB_NS(this).unloaders = []; + + const self = this; + TBB_NS(this).destroyed = false; + TBB_NS(this).destroyFuncs = []; + let safeOptions = TBB_NS(this).options = validateOptions(options); + + winUtils.WindowTracker({ + onTrack: function (window) { + if (!isBrowser(window) || TBB_NS(self).destroyed) + return; + + let doc = window.document; + let $ = function(id) doc.getElementById(id); + + // create toolbar button + let tbb = doc.createElementNS(NS_XUL, "toolbarbutton"); + tbb.setAttribute("id", safeOptions.id); + tbb.setAttribute("type", "button"); + if (safeOptions.image) + tbb.setAttribute("image", safeOptions.image); + tbb.setAttribute("class", "toolbarbutton-1 chromeclass-toolbar-additional"); + tbb.setAttribute("label", safeOptions.label); + tbb.setAttribute('tooltiptext', safeOptions.tooltiptext); + tbb.addEventListener("command", function() { + if (safeOptions.onCommand) + safeOptions.onCommand({}); // TODO: provide something? + + if (safeOptions.panel) { + safeOptions.panel.show(tbb); + } + }, true); + + // add toolbarbutton to palette + ($("navigator-toolbox") || $("mail-toolbox")).palette.appendChild(tbb); + + // find a toolbar to insert the toolbarbutton into + if (TBB_NS(self).options.toolbarID) { + var tb = $(TBB_NS(self).options.toolbarID); + } + if (!tb) { + var tb = toolbarbuttonExists(doc, safeOptions.id); + } + + // found a toolbar to use? + if (tb) { + let b4; + + // find the toolbarbutton to insert before + if (TBB_NS(self).options.insertbefore) { + b4 = $(TBB_NS(self).options.insertbefore); + } + if (!b4) { + let currentset = tb.getAttribute("currentset").split(","); + let i = currentset.indexOf(safeOptions.id) + 1; + + // was the toolbarbutton id found in the curent set? + if (i > 0) { + let len = currentset.length; + // find a toolbarbutton to the right which actually exists + for (; i < len; i++) { + b4 = $(currentset[i]); + if (b4) break; + } + } + } + + tb.insertItem(safeOptions.id, b4, null, false); + } + + var saveTBNodeInfo = function(e) { + TBB_NS(self).options.toolbarID = tbb.parentNode.getAttribute("id") || ""; + TBB_NS(self).options.insertbefore = (tbb.nextSibling || "") + && tbb.nextSibling.getAttribute("id").replace(/^wrapper-/i, ""); + }; + + window.addEventListener("aftercustomization", saveTBNodeInfo, false); + + // add unloader to unload+'s queue + var unloadFunc = function() { + tbb.parentNode.removeChild(tbb); + window.removeEventListener("aftercustomization", saveTBNodeInfo, false); + }; + var index = TBB_NS(self).destroyFuncs.push(unloadFunc) - 1; + listen(window, window, "unload", function() { + TBB_NS(self).destroyFuncs[index] = null; + }, false); + TBB_NS(self).unloaders.push(unload(unloadFunc, window)); + } + }); + }, + destroy: function() { + if (TBB_NS(this).destroyed) return; + TBB_NS(this).destroyed = true; + + let options = TBB_NS(this).options; + + if (options.panel) + options.panel.destroy(); + + // run unload functions + TBB_NS(this).destroyFuncs.forEach(function(f) f && f()); + TBB_NS(this).destroyFuncs.length = 0; + + // remove unload functions from unload+'s queue + TBB_NS(this).unloaders.forEach(function(f) f()); + TBB_NS(this).unloaders.length = 0; + }, + moveTo: function(pos) { + if (TBB_NS(this).destroyed) return; + + let options = TBB_NS(this).options; + + // record the new position for future windows + TBB_NS(this).options.toolbarID = pos.toolbarID; + TBB_NS(this).options.insertbefore = pos.insertbefore; + + // change the current position for open windows + for each (var window in winUtils.windowIterator()) { + if (!isBrowser(window)) continue; + + let $ = function (id) window.document.getElementById(id); + + // if the move isn't being forced and it is already in the window, abort + if (!pos.forceMove && $(this.id)) continue; + + var tb = $(TBB_NS(this).options.toolbarID); + var b4 = $(TBB_NS(this).options.insertbefore); + + // TODO: if b4 dne, but insertbefore is in currentset, then find toolbar to right + + if (tb) tb.insertItem(this.id, b4, null, false); + }; + }, + get id() TBB_NS(this).options.id, + get label() TBB_NS(this).options.label, + set label(value) { + TBB_NS(this).options.label = value; + getToolbarButtons(function(tbb) { + tbb.label = value; + }, this.id); + return value; + }, + setIcon: function setIcon(options) { + let val = TBB_NS(this).options.image = options.image || options.url; + getToolbarButtons(function(tbb) { + tbb.image = val; + }, this.id); + return val; + }, + get image() TBB_NS(this).options.image, + set image(value) this.setIcon({image: value}), + get tooltiptext() TBB_NS(this).options.tooltiptext, + set tooltiptext(value) { + TBB_NS(this).options.tooltiptext = value; + getToolbarButtons(function(tbb) { + tbb.setAttribute('tooltiptext', value); + }, this.id); + } +}); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/utils.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/utils.js new file mode 100644 index 0000000..6ad0304 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/utils.js @@ -0,0 +1,28 @@ +'use strict'; + +const winUtils = require("sdk/deprecated/window-utils"); +const { isBrowser } = require('sdk/window/utils'); + +const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + +function getToolbarButtons(callback, id) { + let buttons = []; + for each (var window in winUtils.windowIterator()) { + if (!isBrowser(window)) continue; + let tbb = window.document.getElementById(id); + if (tbb) buttons.push(tbb); + } + if (callback) buttons.forEach(callback); + return buttons; +} +exports.getToolbarButtons = getToolbarButtons; + +function toolbarbuttonExists(doc, id) { + var toolbars = doc.getElementsByTagNameNS(NS_XUL, "toolbar"); + for (var i = toolbars.length - 1; ~i; i--) { + if ((new RegExp("(?:^|,)" + id + "(?:,|$)")).test(toolbars[i].getAttribute("currentset"))) + return toolbars[i]; + } + return false; +} +exports.toolbarbuttonExists = toolbarbuttonExists; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/validate.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/validate.js new file mode 100644 index 0000000..3de6d30 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/validate.js @@ -0,0 +1,31 @@ +'use strict'; + +const { validateOptions } = require('sdk/deprecated/api-utils'); +const { Panel } = require('sdk/panel'); + + const RULES = { + image: { is: ["null", "undefined", "string"] }, + tooltiptext: { + is: ["null", "undefined", "string"], + defaultValue: '' + }, + id: { + is: ["string"], + ok: function (v) v.length > 0, + msg: 'BAD ID', + readonly: true + }, + label: { + is: ["string"], + ok: function (v) v.length > 0, + msg: 'BAD Label' + }, + panel: { + is: ["null", "undefined", "object"], + ok: function(v) !v || v instanceof Panel + }, + onCommand: { + is: ["null", "undefined", "function"], + } +}; +exports.validate = function(o) validateOptions(o, RULES); diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/warning.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/warning.js new file mode 100644 index 0000000..bf2b449 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/warning.js @@ -0,0 +1,43 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const self = require('sdk/self'); +const tabs = require('sdk/tabs'); +const { Class } = require('sdk/core/heritage'); +const { on, emit, once, off } = require('sdk/event/core'); +const { EventTarget } = require('sdk/event/target'); + +const awNS = require('sdk/core/namespace').ns(); + +let AddonWarning = Class({ + extends: EventTarget, + initialize: function initialize(options) { + EventTarget.prototype.initialize.call(this, options); + awNS(this).options = options; + }, + open: function() { + let self = this; + let options = awNS(self).options; + + tabs.open({ + url: module.uri.replace(/lib\/addon-warning\.js/, 'data/warning.html'), + onReady: function(tab) { + let worker = tab.attach({ + contentScriptFile: module.uri.replace(/lib\/addon-warning\.js/, 'data/warning-mod.js') + }); + + worker.port.on('cancel', function(data) { + emit(self, 'cancel'); + }); + worker.port.on('accept', function(data) { + emit(self, 'accept'); + }); + + worker.port.emit('load', options); + } + }); + } +}); +exports.AddonWarning = AddonWarning; diff --git a/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/web-panel.js b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/web-panel.js new file mode 100644 index 0000000..f61c958 --- /dev/null +++ b/data/extensions/jid1-KtlZuoiikVfFew@jetpack/node_modules/pathfinder/lib/ui/web-panel.js @@ -0,0 +1,289 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +module.metadata = { + 'stability': 'experimental', + 'engines': { + 'Firefox': '*' + } +}; + +const { Class } = require('sdk/core/heritage'); +const { merge } = require('sdk/util/object'); +const { Disposable } = require('sdk/core/disposable'); +const { off, emit, setListeners } = require('sdk/event/core'); +const { EventTarget } = require('sdk/event/target'); +const { URL } = require('sdk/url'); +const { add, remove, has, clear, iterator } = require('sdk/lang/weak-set'); +const { WindowTracker } = require('sdk/deprecated/window-utils'); +const { isBrowser, getMostRecentBrowserWindow, windows } = require('sdk/window/utils'); +const { ns } = require('sdk/core/namespace'); +const { remove: removeFromArray } = require('sdk/util/array'); +const { Worker: WorkerTrait } = require('sdk/content/worker'); + +const { create, dispose } = require('./sidebar/utils'); +const { show, hide } = require('./sidebar/actions'); +const { isShowing } = require('./sidebar/state'); +const { contract } = require('./sidebar/contract'); + +const Worker = WorkerTrait.resolve({ + _injectInDocument: '__injectInDocument' +}).compose({ + get _injectInDocument() false +}); + +const sidebarNS = ns(); + +const WEB_PANEL_BROWSER_ID = 'web-panels-browser'; + +let sidebars = {}; +let models = new WeakMap(); +let views = new WeakMap(); + +function viewsFor(sidebar) views.get(sidebar); +function modelFor(sidebar) models.get(sidebar); + +const WebPanel = Class({ + implements: [ Disposable ], + extends: EventTarget, + setup: function(options) { + let self = this; + + const windowNS = ns(); + + let model = merge({}, contract(options)); + + models.set(this, model); + + setListeners(this, options); + + let bars = []; + sidebarNS(self).tracker = WindowTracker({ + onTrack: function(window) { + if (!isBrowser(window)) + return; + + let sidebar = window.document.getElementById('sidebar'); + let sidebarBox = window.document.getElementById('sidebar-box'); + + let bar = create(window, { + id: makeID(model.id), + title: model.title, + sidebarurl: model.url + }); + bars.push(bar); + windowNS(window).bar = bar; + + bar.addEventListener('command', function() { + if (isSidebarShowing(window, self)) { + hideSidebar(window, self); + return; + } + + showSidebar(window, self); + }, false); + + function onSidebarLoad() { + // check if the sidebar is ready + let isReady = sidebar.docShell && sidebar.contentDocument; + if (!isReady) + return; + + // check if it is a web panel + let panelBrowser = sidebar.contentDocument.getElementById(WEB_PANEL_BROWSER_ID); + if (!panelBrowser) { + bar.removeAttribute('checked'); + return; + } + + let sbTitle = window.document.getElementById('sidebar-title'); + function onWebPanelSidebarLoad() { + if (panelBrowser.contentWindow.location != model.url || + sbTitle.value != model.title) { + return; + } + + let worker = windowNS(window).worker = Worker({ + window: panelBrowser.contentWindow + }); + + function onWebPanelSidebarUnload() { + panelBrowser.removeEventListener('unload', onWebPanelSidebarUnload, true); + + windowNS(window).onWebPanelSidebarLoad = null; + + // uncheck the associated menuitem + bar.setAttribute('checked', 'false'); + + emit(self, 'hide', null); + emit(self, 'detach', worker); + } + windowNS(window).onWebPanelSidebarUnload = onWebPanelSidebarUnload; + panelBrowser.contentWindow.addEventListener('unload', onWebPanelSidebarUnload, false); + + // check the associated menuitem + bar.setAttribute('checked', 'true'); + + emit(self, 'show', null); + emit(self, 'attach', worker); + } + windowNS(window).onWebPanelSidebarLoad = onWebPanelSidebarLoad; + panelBrowser.addEventListener('DOMWindowCreated', onWebPanelSidebarLoad, true); + } + windowNS(window).onSidebarLoad = onSidebarLoad; + sidebar.addEventListener('load', onSidebarLoad, true); + }, + onUntrack: function(window) { + if (!isBrowser(window)) + return; + + let { bar } = windowNS(window); + if (bar) { + removeFromArray(viewsFor(self), bar); + dispose(bar); + } + + let sidebar = window.document.getElementById('sidebar'); + if (!sidebar) + return; + + if (windowNS(window).onSidebarLoad) { + sidebar.removeEventListener('load', windowNS(window).onSidebarLoad, true) + windowNS(window).onSidebarLoad = null; + } + + if (windowNS(window).onWebPanelSidebarLoad) { + let webPanel = sidebar.contentDocument.getElementById(WEB_PANEL_BROWSER_ID); + webPanel && webPanel.removeEventListener('DOMWindowCreated', windowNS(window).onWebPanelSidebarLoad, true); + windowNS(window).onWebPanelSidebarLoad = null; + } + + if (windowNS(window).onWebPanelSidebarUnload) { + windowNS(window).onWebPanelSidebarUnload(); + } + } + }); + + views.set(this, bars); + + add(sidebars, this); + }, + get id() modelFor(this).id, + get title() modelFor(this).title, + get url() modelFor(this).url, + show: function() show(this), + hide: function() hide(this), + dispose: function() { + off(this); + + let wins = windows('navigator:browser', { includePrivate: true }); + for each (let win in wins) { + hideSidebar(win, this); + } + + remove(sidebars, this); + + // stop tracking windows + sidebarNS(this).tracker.unload(); + sidebarNS(this).tracker = null; + + views.delete(this); + } +}); +exports.WebPanel = WebPanel; + +function showSidebar(window, sidebar) { + let model = modelFor(sidebar); + //let window = window || getMostRecentBrowserWindow(); + + window.openWebPanel(model.title, model.url); + + let menuitem = window.document.getElementById(makeID(model.id)); + menuitem.setAttribute('checked', true); +} +show.define(WebPanel, showSidebar.bind(null, null)); + +function hideSidebar(window, sidebar) { + //window = window || getMostRecentBrowserWindow(); + + if (!isSidebarShowing(window, sidebar)) + return; + + // return window.toggleSidebar(); + + // Below was taken from http://mxr.mozilla.org/mozilla-central/source/browser/base/content/browser.js#4775 + // the code for window.todggleSideBar().. + let { document } = window; + //let sidebar = document.getElementById('sidebar'); + let sidebarTitle = document.getElementById('sidebar-title'); + let sidebarBox = document.getElementById('sidebar-box'); + let sidebarSplitter = document.getElementById('sidebar-splitter'); + let commandID = sidebarBox.getAttribute('sidebarcommand'); + let sidebarBroadcaster = document.getElementById(commandID); + + sidebarBox.hidden = true; + sidebarSplitter.hidden = true; + + sidebar.setAttribute('src', 'about:blank'); + //sidebar.docShell.createAboutBlankContentViewer(null); + + sidebarBroadcaster.removeAttribute('checked'); + sidebarBox.setAttribute('sidebarcommand', ''); + sidebarTitle.value = ''; + sidebarBox.hidden = true; + sidebarSplitter.hidden = true; + + // TODO: perhaps this isn't necessary if the window is not most recent? + window.gBrowser.selectedBrowser.focus(); +} +hide.define(WebPanel, hideSidebar.bind(null, null)); + +function isSidebarShowing(window, sidebar) { + let win = window || getMostRecentBrowserWindow(); + + // make sure there is a window + if (!win) { + return false; + } + + // make sure there is a sidebar for the window + let sb = win.document.getElementById('sidebar'); + let sidebarTitle = win.document.getElementById('sidebar-title'); + if (!(sb && sidebarTitle)) { + return false; + } + + // checks if the sidebar box is hidden + let sbb = win.document.getElementById('sidebar-box'); + if (!sbb || sbb.hidden) { + return false; + } + + // checks if the sidebar is loading + if (win.gWebPanelURI == modelFor(sidebar).url) { + return false; + } + + if (sidebarTitle.value == modelFor(sidebar).title) { + // checks if the sidebar loaded already + let ele = sb.contentDocument && sb.contentDocument.getElementById(WEB_PANEL_BROWSER_ID); + + if (ele.getAttribute('cachedurl') == modelFor(sidebar).url) { + return true; + } + + if (ele && ele.contentWindow && ele.contentWindow.location == modelFor(sidebar).url) { + return true; + } + } + + // default + return false; +} +isShowing.define(WebPanel, isSidebarShowing.bind(null, null)); + +function makeID(id) { + return 'pathfinder-sidebar-' + id; +} |