Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Программы » Расширения для Firefox/Mozilla Firefox Extensions (часть 8)

Модерирует : gyra, Maz

gyra (16-09-2017 13:48): Расширения для Firefox/Mozilla Firefox Extensions (часть 9)  Версия для печати • ПодписатьсяДобавить в закладки
На первую страницук этому сообщениюк последнему сообщению

   

nfmzkvmx



Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Готовая кнопка (Кнопка уже не влазит в пост, поэтому ссылкой.)
 
Либо отдельно:
Код для секции "Инициализация":

Код:
((bmsHndlr, listener, popupListener) => {
    'use strict';
 
    this._handleClick = () => Services.ww.openWindow(null, xul(), '', f, null);
 
    const escapeXMLChr = str => str.replace(/["'<>&]/g, m => ({'"': '&quot;', '\'': '&apos;', '<': '&lt;', '>': '&gt;', '&': '&amp;'})[m]),
          f = 'chrome,titlebar,toolbar,centerscreen,modal=no,resizable',
          xul = (() => 'data:application/vnd.mozilla.xul+xml,' +
                 encodeURIComponent(this.Help.split('\n\n')[0].trim().replace('_buttonId', _id)
                                    .replace('_title', escapeXMLChr(this.label)))),
          prefs = {
              PTPref: 'CB.Places-Tooltips.enabled',
              addBmHere: 'CB.Places-Tooltips.dblclick-add-bm-to-folder.enabled',
              tagging: 'CB.Places-Tooltips.tagging.enabled',
              saveSel: 'CB.Places-Tooltips.save-selected-text.enabled',
              editXtraProps: 'CB.Places-Tooltips.extra-properties.enabled',
              hideDefProps: 'CB.Places-Tooltips.hide-default-properties',
              goPrntFldr: 'CB.Places-Tooltips.goParentFolder.enabled'
          },
          observer = {
              observe(win) {
                  win.addEventListener('load', this, false);
              },
              handleEvent(e) {
                  let win =  e ? e.target.defaultView : content.document.defaultView;
                  win.removeEventListener('load', this, false);
                  if (win.location != 'chrome://browser/content/places/places.xul') return;
                  win.addEventListener('popupshowing', popupListener, false);
                  addDestructor(() => win.removeEventListener('popupshowing', popupListener, false))
              }
          };
 
    if (!cbu.getPrefs(prefs.PTPref)) return;
 
    for(let pref of Object.values(prefs))
        cbu.isPref(pref, false);
 
    if (cbu.getPrefs(prefs.addBmHere)) {
        window.addEventListener('dblclick', listener, false);
        addDestructor(() => window.removeEventListener('dblclick', listener, false))
    };
 
    if (cbu.getPrefs(prefs.editXtraProps) || cbu.getPrefs(prefs.goPrntFldr)) {
        window.addEventListener('popupshowing', popupListener, false);
        Services.obs.addObserver(observer, 'domwindowopened', false);
        addDestructor(() => {
            window.removeEventListener('popupshowing', popupListener, false)
            Services.obs.removeObserver(observer, 'domwindowopened', false)
        })
    };
 
    const tltpXItms =
          {
              'CB.Places-Tooltips.show-date-add': '\n    var tltpAdded = aDocument.getElementById("CB.Places-Tooltips.date-add"),\n        add = node.dateAdded;\n    if (!tltpAdded) {\n        tltpAdded = box.appendChild(document.createElement("label"));\n        tltpAdded.className = "tooltip-label cb-pltltp-extra-item";\n        tltpAdded.id = "CB.Places-Tooltips.date-add";\n    };\n    tltpAdded.hidden = !add;\n    if (!tltpAdded.hidden)\n        tltpAdded.textContent = "Добавлено:\\t\\t" + formatDate(add);\n',
              'CB.Places-Tooltips.show-date-modified': '\n    var tltpMd = aDocument.getElementById("CB.Places-Tooltips.date-modified"),\n        md = node.lastModified;\n    if (!tltpMd) {\n        tltpMd = box.appendChild(document.createElement("label"));\n        tltpMd.className = "tooltip-label cb-pltltp-extra-item";\n        tltpMd.id = "CB.Places-Tooltips.date-modified";\n    };\n    tltpMd.hidden = !md;\n    if (!tltpMd.hidden)\n        tltpMd.textContent = "Изменено:\\t\\t" + formatDate(md);\n',
              'CB.Places-Tooltips.show-date-last-visit': '\n    var tltpLst = aDocument.getElementById("CB.Places-Tooltips.last-visit"),\n        tm = node.time;\n    if (!tltpLst) {\n        tltpLst = box.appendChild(document.createElement("label"));\n        tltpLst.className = "tooltip-label cb-pltltp-extra-item";\n        tltpLst.id = "CB.Places-Tooltips.last-visit";\n    };\n    tltpLst.hidden = !tm;\n    if (!tltpLst.hidden)\n        tltpLst.textContent = "Посещено:\\t\\t" + formatDate(tm);\n',
              'CB.Places-Tooltips.show-visits': '\n    var tltpVsts = aDocument.getElementById("CB.Places-Tooltips.visits"),\n        cnt = node.accessCount;\n    if (!tltpVsts) {\n        tltpVsts = box.appendChild(document.createElement("label"));\n        tltpVsts.className = "tooltip-label cb-pltltp-extra-item";\n        tltpVsts.id = "CB.Places-Tooltips.visits";\n    };\n    tltpVsts.hidden = !cnt;\n    if (!tltpVsts.hidden)\n        tltpVsts.textContent = "Посещений:\\t\\t" + cnt;\n',
              'CB.Places-Tooltips.show-tags': '\n    var tltpTgs = aDocument.getElementById("CB.Places-Tooltips.tags"),\n        tgs = node.tags;\n    if (!tltpTgs) {\n        tltpTgs = box.appendChild(document.createElement("label"));\n        tltpTgs.className = "tooltip-label cb-pltltp-extra-item";\n        tltpTgs.id = "CB.Places-Tooltips.tags";\n    };\n    tltpTgs.hidden = !tgs;\n    if (!tltpTgs.hidden)\n        tltpTgs.textContent = "Метки:\\t\\t\\t" + tgs;\n',
              'CB.Places-Tooltips.show-keywords': '\n    var tltpKs = aDocument.getElementById("CB.Places-Tooltips.keywords"),\n        ks;\n    if (!tltpKs) {\n        tltpKs = box.appendChild(document.createElement("label"));\n        tltpKs.className = "tooltip-label cb-pltltp-extra-item";\n        tltpKs.id = "CB.Places-Tooltips.keywords";\n    };\n    try {ks = plBms.getKeywordForBookmark(nId)} catch(ex) {};\n    tltpKs.hidden = !ks;\n    if (!tltpKs.hidden)\n        tltpKs.textContent = "Ключевые слова:\\t\\t" + ks;\n',
              'CB.Places-Tooltips.show-inWhichFolder': '\n    var getFolders = ((arr, ids) => {\n        var crntNdFldrId = getFldrId(nId),\n            crntNdFldr = getFldrTtl(crntNdFldrId);\n        if (!ids.length) return crntNdFldr ? crntNdFldr : false;\n        for(let id of ids) {\n            var fldrId = getFldrId(id),\n                fldr = getFldrTtl(fldrId);\n            fldr && fldr != crntNdFldr && arr.push(fldr)\n        };\n        if (!arr.length) return crntNdFldr ? crntNdFldr : false;\n        return crntNdFldr + " (" + arr.join(", ") + ")";\n    })([], getIds().filter(id => id != nId));\n\n    var tltpFolders = aDocument.getElementById("CB.Places-Tooltips.inWhichFolder");\n    if (!tltpFolders) {\n        tltpFolders = box.appendChild(document.createElement("label"));\n        tltpFolders.className = "tooltip-label cb-pltltp-extra-item";\n        tltpFolders.id = "CB.Places-Tooltips.inWhichFolder";\n    };\n    tltpFolders.hidden = !getFolders;\n    if (!tltpFolders.hidden)\n        tltpFolders.textContent = "Папки:\\t\\t\\t" + getFolders;\n',
              'CB.Places-Tooltips.show-descriptions': '\n    var desk = ((arr, ids) => {\n        ids = getIds();\n        if (!(ids && ids.length)) return false;\n        for(var id of ids) {\n            var descs = pl.getAnnotationsForItem(id);\n            if (descs && !!descs.length) {\n                for(var desc of descs) {\n                    let str;\n                    if (desc.value) {\n                        switch (desc.name) {\n                            case "bookmarkProperties/description":\n                                str = "Описание:\\t\\t" + desc.value;\n                                break;\n                            case "bookmarkProperties/loadInSidebar":\n                                str = "У закладки установлен флаг \\"Открывать в сайдбаре\\"";\n                                break;\n                            default:\n                                str = desc.name + "\\t\\t\\t" + desc.value;\n                        }\n                        arr.push(str);\n                    }\n                }\n                arr.push(undefined)\n            }\n        }\n        return !!arr.length && arr.join("\\n");\n    })([]);\n\n    var tltpDesk = aDocument.getElementById("CB.Places-Tooltips.descriptions");\n    if (!tltpDesk) {\n        tltpDesk = box.appendChild(document.createElement("label"));\n        tltpDesk.className = "tooltip-label cb-pltltp-extra-item";\n        tltpDesk.id = "CB.Places-Tooltips.descriptions";\n    };\n    tltpDesk.hidden = !desk;\n    if (!tltpDesk.hidden)\n        tltpDesk.textContent = "Комментарии:\\n" + desk;\n'
          };
 
    let oldStr = bmsHndlr.toString(),
        tmpStr = '\n    var nId = node.itemId,\n        box = aDocument.getElementById("bhTooltipTextBox"),\n        pl = PlacesUtils,\n        plBms = pl.bookmarks,\n        formatDate = int => new Date(int / 1000).toLocaleString(),\n        getIds = uri => {\n           try {\n              uri = Services.uriFixup.createFixupURI(url, 0);\n           }\n           catch(ex) {}\n           finally {\n              return uri ? pl.getBookmarksForURI(uri) : false\n           }\n        },\n        getFldrId = id => {try {return plBms.getFolderIdForItem(id)} catch(ex) {}},\n        getFldrTtl = id => {try {return plBms.getItemTitle(id)} catch(ex) {}};\n',
        newstr;
 
    for(let prop in tltpXItms) {
        cbu.isPref(prop, false);
        cbu.getPrefs(prop) && (tmpStr += tltpXItms[prop]);
    };
 
    newstr = oldStr.slice(oldStr.indexOf('{') + 1, oldStr.lastIndexOf('}'))
        .split(/(?=\n.+\n\s+return true)/).join(tmpStr);
 
    window.top.BookmarksEventHandler.fillInBHTooltip = new Function('aDocument', 'aEvent', newstr);
 
    addDestructor(() => {
        for(let node of [...document.getElementsByClassName('cb-pltltp-extra-item')]
            .concat([...SidebarUI.browser.contentDocument.getElementsByClassName('cb-pltltp-extra-item')]))
            node.remove();
        window.top.BookmarksEventHandler.fillInBHTooltip = bmsHndlr;
    })
})(
    window.top.BookmarksEventHandler.fillInBHTooltip,
    {
        plUtls: PlacesUtils,
        plUIUtls: PlacesUIUtils,
        alertS: Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService),
        crop(str) {
            typeof str != 'string' && (str = str.toString());
            return str.length > 45 ? [str.substr(0,20), str.substr(-20)].join('...') : str
        },
        wrap(str) {
            typeof str != 'string' && (str = str.toString());
            return str.match(/.{1,60}/g).map((sub, inx, arr) => (inx < arr.length - 1)
                                             ? sub.replace(/ (?=[^ ]*$)/, '\n')
                                             : sub).join('')
        },
        slider(img, title, txt) {
            return this.alertS.showAlertNotification(img, this.crop(title), this.wrap(txt), false, '', null, '')
        },
        getBmId(uri, id) {
            try {id = this.plUtls.getMostRecentBookmarkForURI(uri)}  
            catch(ex) {}
            finally {
                return id ? id : null
            }
        },
        getSel(doc) {
            return doc.getSelection().toString().trim()
        },
        setDesks(uri, key, val) {
            let id = this.getBmId(uri);
            return val && this.plUtls.setAnnotationsForItem(id, [{name: key, value: val}])
        },
        setTags(doc, uri) {
            let kwrds = doc.head.querySelector('meta[name="Keywords"]');
            if (kwrds && kwrds.content.length)
                return this.plUtls.tagging.tagURI(uri, kwrds.content.split(/\s+/g));
        },
        handleEvent(e) {
            let targ = e.originalTarget,
                riskyTags = ['menu', 'treechildren', 'toolbarbutton'];
 
            if (e.button != 0 || riskyTags.indexOf(targ.localName) == -1) return;
 
            let node = targ._placesNode;
 
            if (targ.localName == 'treechildren') {
                let tree = targ.parentNode,
                    tbo = tree.treeBoxObject,
                    cell = tbo.getCellAt(e.clientX, e.clientY);
                if (cell.row == -1) return;
                node = tree.view.nodeForTreeIndex(cell.row);
            };
 
            if (!node || !this.plUtls.nodeIsFolder(node)) return;
 
            e.preventDefault(); e.stopPropagation();
 
            let br = window.gBrowser.selectedBrowser.contentWindow,
                doc = br.content.document,
                loc = doc.location,
                ttl = this.plUIUtls.getBestTitle(doc),
                fldId = this.plUtls.getConcreteItemId(node),
                fldTtl = this.plUtls.bookmarks.getItemTitle(fldId),
                uri = Services.uriFixup.createFixupURI(loc.href, 0),
                obj = {
                    'bookmarkProperties/description': this.plUIUtls.getDescriptionFromDocument(doc),
                    'Текст:': cbu.getPrefs('CB.Places-Tooltips.save-selected-text.enabled') && this.getSel(doc)
                };
 
            try {
                this.plUtls.bookmarks.insertBookmark(fldId, uri, 0, ttl)
            }
            catch(ex) {
                return this.slider('chrome://browser/skin/warning.svg', 'Не удалось добавить закладку!', this.wrap(ex));
            };
 
            for(let prop in obj)
                this.setDesks(uri, prop, obj[prop]);
 
            cbu.getPrefs('CB.Places-Tooltips.tagging.enabled') && this.setTags(doc, uri);
 
            this.slider(gBrowser.mCurrentTab.image || 'chrome://mozapps/skin/places/defaultFavicon.png',
                        this.crop(ttl), 'Добавлено в папку: ' + fldTtl);
        }
    },
    {
        plProps: {
            bmId: null,
            bmTtl: null,
            bmURL: null,
            bmAdd: null,
            bmMod: null,
            bmVst: null,
            bmCnt: null,
            bmTgs: null,
            node: null,
        },
        f: 'chrome,titlebar,toolbar,centerscreen,modal=no,resizable',
        plUtls: PlacesUtils,
        formatDate(int) {
            return int && new Date(int / 1000).toLocaleString()
        },
        escapeXMLChr(str) {
            return str.replace(/["'<>&]/g, m => ({'"': '&quot;', '\'': '&apos;', '<': '&lt;', '>': '&gt;', '&': '&amp;'})[m])
        },
        box() {
            let xul = 'data:application/vnd.mozilla.xul+xml,' +
                encodeURIComponent(self.Help.split('\n\n')[1].trim()
                                   .replace(/_bmId|_title|_bmURL|_bmAdd|_bmMod|_bmVst|_bmCnt|_bmTgs/g
                                            , m => ({'_bmId': this.plProps.bmId
                                                     , '_title': this.plProps.bmTtl || ""
                                                     , '_bmURL': this.plProps.bmURL || ""
                                                     , '_bmAdd': this.plProps.bmAdd || ""
                                                     , '_bmMod': this.plProps.bmMod || ""
                                                     , '_bmVst': this.plProps.bmVst || ""
                                                     , '_bmCnt': this.plProps.bmCnt || ""
                                                     , '_bmTgs': this.plProps.bmTgs || ""
                                                    })[m])
                                   );
            return xul
        },
        shouldShow() {
            return (this.plProps.node && this.plUtls.nodeIsBookmark(this.plProps.node) && this.plProps.bmId)
        },
        cnItems(popup) {
            let isBm = this.shouldShow(),
                doc = popup.ownerDocument;
            if (cbu.getPrefs('CB.Places-Tooltips.extra-properties.enabled')) {
                let editXtraProps = doc.getElementById('CB.Places-Tooltips.extra-properties');
                if (!editXtraProps) {
                    editXtraProps = popup.appendChild(document.createElement('menuitem'));
                    editXtraProps.id = 'CB.Places-Tooltips.extra-properties';
                    editXtraProps.setAttribute("label", 'Свойства+');
                    editXtraProps.onclick = () => this.showDlg();
                    addDestructor(() => editXtraProps.remove())
                }
                cbu.getPrefs('CB.Places-Tooltips.hide-default-properties')
                    && (doc.getElementById('placesContext_show:info').collapsed = true);
                editXtraProps.hidden = editXtraProps.disabled = !isBm;
            }
            if (cbu.getPrefs('CB.Places-Tooltips.goParentFolder.enabled')) {
                let goPrntFldr = doc.getElementById('CB.Places-Tooltips.goParentFolder');
                if (!goPrntFldr) {
                    goPrntFldr = popup.insertBefore(document.createElement('menuitem'), doc.getElementById('placesContext_editSeparator'));
                    goPrntFldr.id = "CB.Places-Tooltips.goParentFolder";
                    goPrntFldr.setAttribute("label", 'Go Parent Folder');
                    goPrntFldr.onclick = () => this.goPrntFldr(popup, doc, this.plProps.bmId);
                    addDestructor(() => goPrntFldr.remove())
                }
                goPrntFldr.hidden = goPrntFldr.disabled =
                    !(isBm && doc.documentElement.id
                      && (doc.documentElement.id == 'bookmarksPanel' || doc.documentElement.id == 'places'));
            }
        },
        showDlg() {
            return Services.ww.openWindow(null, this.box(), '', this.f, null)
        },
        goPrntFldr(popup, doc, bmId) {
            let view = popup._view,
                id = bmId,
                vis = tree => {
                    let pos = 0.5, tbo = tree.treeBoxObject,
                        ind = tbo.view.selection.currentIndex,
                        first = tbo.getFirstVisibleRow(),
                        visibleRows = tbo.height/tbo.rowHeight,
                        newFirst = ind - pos*visibleRows + 1;
                    tbo.scrollByLines(Math.round(newFirst - first));
                },
                sel = (view, id) => {
                    let str = "node.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER",
                        src = view.selectItems.toString(),
                        code = src.replace(str + ";", "(" + str + " || " + str + "_SHORTCUT);");
                    view.place = view.place; eval("(" + code + ")").bind(view)([id]);
                    vis(view);
                };
            if (view.id == "placeContent") {
                let plView = doc.getElementById("placesList"),
                    parentId = PlacesUtils.bookmarks.getFolderIdForItem(id);
                sel(plView, parentId);
                setTimeout(() => {view.selectItems([id]); vis(view);}, 100);
            }
            else
                sel(view, id);
        },
        handleEvent(e) {
            if (!(e.target.id && e.target.id == 'placesContext')) return;
 
            for(let key of Object.keys(this.plProps))
                delete this.plProps[key];
 
            let popup = e.target,
                trNode = popup.triggerNode,
                node = trNode._placesNode;
 
            if (trNode.localName == 'treechildren') {
                let tree = trNode.parentNode,
                    tbo = tree.treeBoxObject,
                    cell = tbo.getCellAt(e.clientX, e.clientY);
                if (cell.row == -1) return;
                node = tree.view.nodeForTreeIndex(cell.row);
            };
 
            node && Object.assign(this.plProps
                                  , {node: node}
                                  , {bmId: node.itemId}
                                  , {bmTtl: this.escapeXMLChr(node.title)}
                                  , {bmURL: this.escapeXMLChr(node.uri)}
                                  , {bmAdd: this.formatDate(node.dateAdded)}
                                  , {bmMod: this.formatDate(node.lastModified)}
                                  , {bmVst: this.formatDate(node.time)}
                                  , {bmCnt: node.accessCount}
                                  , {bmTgs: node.tags}
                                 );
 
            this.cnItems(popup)
        }
    }
);
 

Для секции "Справка":

Код:
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<prefwindow xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
            title = "_title"
            autosize="true"
            id="PlacesTooltipsOptions"
            onload="onLoad()"
            onunload="onUnload()">
    <prefpane id="options" label="Настройки показа подсказок закладок">
        <preferences>
            <preference name="CB.Places-Tooltips.enabled" id="state" type="bool" onchange="toggleState(this.value)"/>
            <preference name="CB.Places-Tooltips.dblclick-add-bm-to-folder.enabled" id="addBmToFolder" type="bool" onchange="toggleState(this.previousElementSibling.value)"/>
            <preference name="CB.Places-Tooltips.tagging.enabled" id="tagging" type="bool"/>
            <preference name="CB.Places-Tooltips.show-date-add" id="add" type="bool"/>
            <preference name="CB.Places-Tooltips.show-date-modified" id="modified" type="bool"/>
            <preference name="CB.Places-Tooltips.show-date-last-visit" id="last" type="bool"/>
            <preference name="CB.Places-Tooltips.show-visits" id="visits" type="bool"/>
            <preference name="CB.Places-Tooltips.show-tags" id="tags" type="bool"/>
            <preference name="CB.Places-Tooltips.show-keywords" id="keywords" type="bool"/>
            <preference name="CB.Places-Tooltips.show-inWhichFolder" id="folders" type="bool"/>
            <preference name="CB.Places-Tooltips.save-selected-text.enabled" id="savesel" type="bool"/>
            <preference name="CB.Places-Tooltips.extra-properties.enabled" id="edit" type="bool" onchange="!this.value &amp;&amp; (this.nextElementSibling.value = this.value); toggleState();"/>
            <preference name="CB.Places-Tooltips.hide-default-properties" id="hide" type="bool"/>
            <preference name="CB.Places-Tooltips.goParentFolder.enabled" id="goPrntFldr" type="bool"/>
            <preference name="CB.Places-Tooltips.show-descriptions" id="descriptions" type="bool"/>
        </preferences>
        <groupbox>
            <caption>
                <checkbox class="header" label="Включить Places Tooltips" preference="state"/>
            </caption>
            <vbox style="padding: 5px 20px;" align="start">
                <checkbox label="Показывать дату добавления" preference="add"/>
                <checkbox label="Показывать дату изменения" preference="modified"/>
                <checkbox label="Показывать дату последнего посещения" preference="last"/>
                <checkbox label="Показывать колличество посещений" preference="visits"/>
                <checkbox label="Показывать метки" preference="tags"/>
                <checkbox label="Показывать ключевые слова" preference="keywords"/>
                <checkbox label="Показывать папки закладок" preference="folders"/>
                <checkbox label="Показывать описания" preference="descriptions"/>
                <groupbox style="padding: 0 20px;">
                    <caption class="header" label="Дополнительно:"/>
                    <checkbox label="Пункт меню &quot;Go Parent Folder&quot;, для перехода в родительскуб папку закладки" preference="goPrntFldr"/>
                    <groupbox>
                        <caption>
                            <checkbox class="header" id="editchck" label="Пункт меню закладок для редактирования свойств и доп. описаний" preference="edit"/>
                        </caption>
                        <checkbox id="hidechck" label="Скрыть дефолтный пункт редактирования свойств закладок" style="padding-inline-start: 20px;" preference="hide"/>
                    </groupbox>
                    <groupbox>
                        <caption>
                            <checkbox class="header" label="Включить добавление закладки в папку по двойному клику на ней" preference="addBmToFolder"/>
                        </caption>
                        <vbox id="extra" style="padding: 0 20px;" align="start">
                            <checkbox label="Сохранять выделенный текст в дополнительном описании" preference="savesel"/>
                            <checkbox label="Добавлять теги, взятые из ключевых слов заголовка страницы" preference="tagging"/>
                        </vbox>
                    </groupbox>
                </groupbox>
            </vbox>
        </groupbox>
    </prefpane>
    <script type="application/javascript">
        <![CDATA[
            Components.utils.import("resource://gre/modules/Services.jsm");
            const o = {// https://github.com/Infocatcher/Private_Tab/issues/228#issuecomment-238963363
                      get windows() {
                          return (function*() {
                              const ws = Services.wm.getEnumerator("navigator:browser");
                              while(ws.hasMoreElements())
                                  yield ws.getNext()
                          })()
                      }
                  },
                  toggleState = val => {
                      typeof val != "boolean" && (val = document.getElementById("state").value);
                      for(let el of document.querySelectorAll("vbox checkbox"))
                          el.disabled = !val;
                      if (val) {
                          for(let el of document.querySelectorAll("#extra checkbox"))
                              el.disabled = !document.getElementById("addBmToFolder").value;
                          let edEl = document.getElementById("editchck"),
                              hdEl = document.getElementById("hidechck");
                          hdEl.disabled = !edEl.checked;
                      }
                  },
                  onLoad = () => {
                      toggleState()
                  },
                  onUnload = () => {
                      for(let win of o.windows) {
                          let btn = win.document.getElementById("_buttonId");
                          if (btn) {
                              btn.destroy();
                              btn.init()
                          }
                      }
                  }
        ]]>
    </script>
</prefwindow>
 
 
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
            title = "Свойства закладки"
            autosize="true"
            height="520"
            width="600"
            id="ExtraDescriptions"
            onload="onLoad()">
    <vbox flex="1" style="overflow-x: hidden;">
        <groupbox id="bmProps" flex="1" style="padding: 5px 10px;">
            <caption flex="1" align="center">
                <label class="header" value="Заголовок:"/> <textbox value="_title" id="title" flex="1" placeholder="не задан"/>
            </caption>
            <hbox align="center" style="padding: 5px 0;">
                <label class="header" value="Адрес:"/> <textbox value="_bmURL" id="url" flex="1" placeholder="не задан"/>
            </hbox>
            <hbox align="center" style="padding: 5px 0;">
                <vbox flex="1" align="center">
                    <label class="header" value="Создано:"/> <textbox value="_bmAdd" id="add" flex="1" class="plain" size="17" readonly="true" placeholder="неизвестно"/>
                </vbox>
                <vbox flex="1" align="center">
                    <label class="header" value="Изменено:"/> <textbox value="_bmMod" id="changed" flex="1" class="plain" size="17" readonly="true" placeholder="неизвестно"/>
                </vbox>
                <vbox flex="1" align="center">
                    <label class="header" value="Посещено:"/> <textbox value="_bmVst" id="visited" class="plain" size="17" readonly="true" placeholder="неизвестно"/>
                </vbox>
                <vbox flex="1" align="center">
                    <label class="header" value="Посещений:"/> <textbox value="_bmCnt" id="counts" class="plain" size="9" readonly="true" placeholder="нет"/>
                </vbox>
            </hbox>
            <hbox align="center" style="padding: 5px 0;">
                <label class="header" value="Метки:"/> <textbox value="_bmTgs" id="tags" flex="1" placeholder="задайте метки, разделяя запятой"/>
            </hbox>
            <hbox align="center" style="padding: 5px 0;">
                <label class="header" value="Ключевые слова:"/> <textbox flex="1" id="keywords" placeholder="не задано"/>
            </hbox>
            <command id="cmd_bmLdSB" oncommand="setSBFlag(this.nextElementSibling.checked ? 1 : 0)"/>
            <checkbox style="padding: 5px 0;" class="header" id="loadInSB" label="Открывать в боковой панели" command="cmd_bmLdSB"/>
        </groupbox>
        <groupbox id="descriptions" style="overflow-x: scroll;">
            <caption flex="1" align="center">
                <label class="header" value="Описания в формате, выводимом как: &quot;Название:&#8194;&#8194;&#8194;Ваш текст&quot;"/>
            </caption>
        </groupbox>
        <button id="addDesc" label="Добавить новое описание" oncommand="crNode({}); addBtn.scrollIntoView({behavior: 'smooth'});"/>
    </vbox>
    <hbox align="center" pack="end" style="padding: 10px 20px">
        <button id="accept" label="Принять" oncommand="updBm(); window.close();"/>
        <button id="cancel" label="Отмена" oncommand="window.close();"/>
    </hbox>
    <script type="application/javascript">
        <![CDATA[
            Components.utils.import("resource://gre/modules/Services.jsm");
            Components.utils.import("resource://gre/modules/PlacesUtils.jsm");
            const plUtls = PlacesUtils,
                  plBms = plUtls.bookmarks,
                  bmId = _bmId,
                  descs = plUtls.getAnnotationsForItem(bmId),
                  sbdesc = "bookmarkProperties/loadInSidebar",
                  defDesc = "bookmarkProperties/description",
                  addBtn = document.getElementById("addDesc"),
                  group = document.getElementById("descriptions"),
                  setSBFlag = val => {
                      let sbDesc = document.getElementById("loadInSB-group");
                      if (sbDesc)
                          !!val ? (sbDesc.lastElementChild.value = val) : rmvNode(sbDesc);
                      else crNode({name: sbdesc, value: val})
                  },
                  crNode = obj => {
                      if (!(obj && typeof obj == "object")) return;
                      let box = group.appendChild(document.createElement("groupbox")),
                          cap = box.appendChild(document.createElement("caption")),
                          nmBox = cap.appendChild(document.createElement("textbox")),
                          spcr = cap.appendChild(document.createElement("spacer")),
                          btn = cap.appendChild(document.createElement("toolbarbutton")),
                          txtBox = box.appendChild(document.createElement("textbox")),
                          btnAttrs = {class: "close-icon tabbable", tooltiptext: "Удалить описание (для дефолного описания удаляется только текст)", oncommand: "rmvNode(this.parentNode.parentNode)"},
                          nmBoxAttrs = {class: "name", placeholder: "Задайте название", maxlength: "30", spellcheck: "true"},
                          txtBoxAttrs = {class: "desc", value: obj.value, multiline: "true", rows: 4, placeholder: "Введите описание (описание не будет сохранено, если это поле останется пустым)", spellcheck: "true"};
                      cap.flex = 1; spcr.flex = 1; spcr.width = 5000;
                      obj.name && (nmBox.defaultValue = obj.name);
                      for(let prop in btnAttrs)
                          btnAttrs[prop] && btn.setAttribute(prop, btnAttrs[prop]);
                      for(let prop in nmBoxAttrs)
                          nmBoxAttrs[prop] && nmBox.setAttribute(prop, nmBoxAttrs[prop]);
                      for(let prop in txtBoxAttrs)
                          txtBoxAttrs[prop] && txtBox.setAttribute(prop, txtBoxAttrs[prop]);
                      if (obj.name == defDesc) {
                          nmBox.value = "Описание:";
                          box.id = "defDesc-group"; nmBox.id = "defDesc-val";
                          nmBox.disabled = true
                      };
                      if (obj.name == sbdesc) {
                          document.getElementById("loadInSB").checked = !!obj.value;
                          box.id = "loadInSB-group"; nmBox.id = "loadInSB-val";
                          box.collapsed = true;
                      }
                  },
                  rmvNode = (box, txtbox = box.lastElementChild) => box.id == "defDesc-group" ? (txtbox.value = '') : box.remove(),
                  onLoad = () => {
                      let kws;
                      try {kws = plBms.getKeywordForBookmark(bmId)} catch(ex) {}
                      finally {kws && (document.getElementById("keywords").defaultValue = kws)};
                      if (descs && !!descs.length)
                          for(let desc of descs)
                              crNode(desc);
                      else crNode({name: defDesc, value: ""});
                  },
                  updBm = () => {
                      plUtls.annotations.removeItemAnnotations(bmId);
                      // https://stackoverflow.com/a/38916225
                      let names = [...document.getElementsByClassName("name")].map(n => !n.id ? n.value : n.defaultValue),
                          descs = [...document.getElementsByClassName("desc")].map(n => n.value),
                          obj = Object.assign({}, ...names.map((n, index) => ({[n]: descs[index]})));
                      for(let prop in obj) {
                          if (obj[prop] || prop == defDesc)
                              plUtls.setAnnotationsForItem(bmId, [{name: prop, value: obj[prop]}]);
                      };
                      let uri;
                      try {uri = Services.uriFixup.createFixupURI(document.getElementById("url").value, 0)} catch(ex) {};
                      for(let node of document.querySelectorAll("#bmProps textbox")) {
                          node.value = node.value.trim();
                          if (node.value != node.defaultValue) {
                              switch (node.id) {
                                  case "title":
                                      plBms.setItemTitle(bmId, node.value);
                                      break;
                                  case "url":
                                      uri && plBms.changeBookmarkURI(bmId, uri);
                                      break;
                                  case "tags":
                                      if (uri) {
                                          let tags = node.value.split(/,(?:\s+)?/g).filter(m => !!m.length);
                                          plUtls.tagging.untagURI(uri, null);
                                          !!tags.length && plUtls.tagging.tagURI(uri, tags)
                                      };
                                      break;
                                  case "keywords":
                                      plBms.setKeywordForBookmark(bmId, node.value);
                                      break;
                              }
                          }
                      }
                  }
        ]]>
    </script>
</window>

Иконка:

Код:
data:image/png;base64,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


Всего записей: 186 | Зарегистр. 09-04-2017 | Отправлено: 01:06 18-07-2017 | Исправлено: nfmzkvmx, 21:33 23-07-2017
   

На первую страницук этому сообщениюк последнему сообщению

Компьютерный форум Ru.Board » Компьютеры » Программы » Расширения для Firefox/Mozilla Firefox Extensions (часть 8)
gyra (16-09-2017 13:48): Расширения для Firefox/Mozilla Firefox Extensions (часть 9)


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.Board
© Ru.Board 2000-2020

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru