villa777
Получилось!
Если кому понадобится:
Значит, чтобу сортировать закладки A,B,C -> А,Б,В, как было до 29 версии (если не ошибаюсь)
1. Качаем дополнение
Custom Buttons 2. В меню "Вид" появился пункт "Добавить новую кнопку".
3. В подпункт "Инициализация" копируем код (или можно добавить в существующую кнопку, если такие есть, чтобы она не мешала потом на панели, т.к. нажимать ее не нужно)
Код: // Добавить новый пункт "Сортировать по типу, названию и домену" в меню папок закладок, от 05.07.2014. ................................
(function() {
var menuitem = document.createElement("menuitem");
menuitem.id = "placesContext_sortBy:locationAndName";
menuitem.setAttribute("label", "Сортировать по домену и названию");
menuitem.setAttribute("selection", "folder");
menuitem.setAttribute("closemenu", "single");
menuitem.setAttribute("oncommand", "this.run(document)"); // если клик или команда на пункте меню
menuitem.run = function(doc) {
// получить Id и контент папки закладок
var node = PlacesUIUtils.getViewForNode( doc.popupNode ).selectedNode;
var folderId = node.folderItemId ? node.folderItemId : node.itemId;
var contents = PlacesUtils.getFolderContents( folderId, false, false ).root;
// удалить разделители из папки закладок, создать массив с закладками и массив c подпапками закладок
for ( var primaryList = [], foldersList = [], i = 0; i < contents.childCount; ++i ) {
var item = contents.getChild(i);
item.type == 7
? (PlacesUtils.bookmarks.removeItem( item.itemId ), i--) // удалить разделители
: (!item.type ? primaryList : foldersList).push( item ); // заполнить массивы
}
// создать массив с закладками у которых есть одинаковые домены и массив c обычными закладками
primaryList.forEach(function(item) {
var domain = item.uri.split(/\/+/g)[1];
primaryList[domain] = domain in primaryList;
});
var domainList = [], placesList = [];
primaryList.forEach(function(item)
( primaryList[item.uri.split(/\/+/g)[1]] ? domainList : placesList ).push(item)
);
// создать функцию сортировки
var sort = function(arr, prop, mod) {
mod = mod || function(arg) arg;
arr.sort(function(a, b) mod(a[prop]).localeCompare(mod(b[prop]), "en"));
}
// отсортировать все массивы по названию и массив с одинаковыми доменам по доменам
sort( foldersList, "title");
sort( placesList, "title");
sort( domainList, "title");
sort( domainList, "uri", function(uri) uri.split(/\/+/g)[1] );
// соединить в нужном порядке все массивы в новом массиве
var newPlacesList = foldersList.concat( placesList ).concat( domainList );
// изменить меню закладок в соответствии с новым массивом
let callback = {
runBatched: function() {
for( let i = 0; i < newPlacesList.length; ++i )
PlacesUtils.bookmarks.setItemIndex( newPlacesList[i].itemId, i );
}
}
PlacesUtils.bookmarks.runInBatchMode( callback, null );
};
// добавить новый пункт во все меню папок закладок ....
function handlePopup(e) {
var node = e.target;
if ( node.id !== 'placesContext' ) return;
var sortByName = node.getElementsByAttribute("id", "placesContext_sortBy:name")[0];
setTimeout(function() { menuitem.setAttribute("disabled", sortByName.disabled ) }, 50 ); // отключать, если 'Сортировать по имени' отключено
if ( node.getElementsByAttribute("id", "placesContext_sortBy:locationAndName")[0] ) return; // блокировать дублирование
node.insertBefore( menuitem, sortByName );
};
addEventListener("popupshowing", handlePopup, true, window );
addDestructor(function() menuitem.parentNode && menuitem.parentNode.removeChild(menuitem) );
// Добавить новый пункт во все меню папок закладок библиотеки ....
function winObs( subject ) {
subject.addEventListener("load", function(e) {
this.removeEventListener( e.type, arguments.callee );
if ( subject.location.href !== 'chrome://browser/content/places/places.xul' ) return; // стоп, если не библиотека
// добавлять и удалять обработчик для добавления в меню папок закладок новый пункт
addEventListener("popupshowing", handlePopup, true, subject );
this.addEventListener("unload", function(e) {
this.removeEventListener(e.type, arguments.callee );
removeEventListener("popupshowing", handlePopup, true, subject );
})
})
};
Services.ww.registerNotification(winObs);
addDestructor(function() { Services.ww.unregisterNotification(winObs) });
})();