Полезная информация

Многие проблемы быстрее решаются поиском по форуму и чтением FAQ, чем созданием новой темы и томительным ожиданием ответа.

№967619-02-2016 22:31:34

villa7
Участник
 
Группа: Members
Зарегистрирован: 21-07-2012
Сообщений: 2235
UA: Firefox 42.0

Re: Custom Buttons

emlen
Не подтверждаю, после выбора папки меняется и название, попробуйте на чистом профиле.


Лучше спросить у знающих - чем лезть не зная.

Отсутствует

 

№967719-02-2016 23:36:13

bunda1
Moderator
 
Группа: Moderators
Откуда: Латвия
Зарегистрирован: 09-02-2010
Сообщений: 4811
UA: Firefox 24.0

Re: Custom Buttons

emlen пишет

Прошел по ссылке, поменял код, все осталось по прежнему(((

Выделить код

Код:

// Сохранять изображение без запроса в указанную папку из контекстного меню, от 21.02.2016. ...............  
((contextMenu, saveimage) => {
   var mItem = contextMenu.insertBefore(document.createElement("menuitem"), saveimage);
   mItem.setAttribute("label", "Сохранить в папку: " + getPath().split("\\").pop());
   addEventListener("popupshowing", e=> mItem.hidden = saveimage.hidden, false, contextMenu); 
   addDestructor(()=> mItem.remove() );
   
   mItem.onclick =e=> {
      if ( e.button ) { setPath(); return; }
   
      var run = cbu.getPrefs("browser.download.folderList");
      var use = cbu.getPrefs("browser.download.useDownloadDir");
      try { var dir = gPrefService.getComplexValue("browser.download.dir", Ci.nsISupportsString).data } 
      catch(e) { var dir = Services.downloads.defaultDownloadsDirectory.path; };
                
      cbu.setPrefs("browser.download.folderList", 2);
      cbu.setPrefs("browser.download.useDownloadDir", true);
      cbu.setPrefs("browser.download.dir", convertFromUnicode("UTF-8", getPath()) );
      
      saveImageURL(gContextMenu.imageURL, 0, 0, 0, 1, null, content.document);
      
      cbu.setPrefs("browser.download.folderList", run);
      cbu.setPrefs("browser.download.useDownloadDir", use);
      cbu.setPrefs("browser.download.dir", convertFromUnicode("UTF-8", dir) );     
   }
   
   function setPath() { 
      var fp = window.makeFilePicker();
      fp.init( window, "Укажите путь к папке для сохранения изображений", fp.modeGetFolder );
      fp.open( result => result == fp.returnOK 
               && cbu.setPrefs("CB.pathToImageFolder", convertFromUnicode("UTF-8", fp.file.path)) 
               || mItem.setAttribute("label", "Сохранить в папку: " + getPath().split("\\").pop()) );
   };

   function getPath() { 
      try { return gPrefService.getComplexValue("CB.pathToImageFolder", Ci.nsISupportsString).data; } 
      catch(e) { return 'C:\\qwerty'; };
   };
   
})(document.getElementById("contentAreaContextMenu"), document.getElementById("context-saveimage"));

Добавлено 19-02-2016 23:36:33

villa7 пишет

emlen
Не подтверждаю, после выбора папки меняется и название, попробуйте на чистом профиле.

У него SeaMonkey.

Отредактировано bunda1 (19-02-2016 23:36:33)

Отсутствует

 

№967819-02-2016 23:45:22

villa7
Участник
 
Группа: Members
Зарегистрирован: 21-07-2012
Сообщений: 2235
UA: Firefox 42.0

Re: Custom Buttons

bunda1
Так это что получается, код разный для FF и SM?


Лучше спросить у знающих - чем лезть не зная.

Отсутствует

 

№967919-02-2016 23:51:47

bunda1
Moderator
 
Группа: Moderators
Откуда: Латвия
Зарегистрирован: 09-02-2010
Сообщений: 4811
UA: Firefox 24.0

Re: Custom Buttons

villa7 пишет

bunda1
Так это что получается, код разный для FF и SM?

Иногда. Принципе я всё делаю для FF.

Отсутствует

 

№968020-02-2016 00:19:32

emlen
Участник
 
Группа: Members
Зарегистрирован: 22-05-2015
Сообщений: 201
UA: unknown 0.0

Re: Custom Buttons

bunda1, очень Вам благодарен, что не оставляете без внимания "фаната симанки":blush: И конечно же заработало, спасибо!

Добавлено 20-02-2016 00:25:22
Dumby, попробовал код, доволен как слон, лепота!!!:) спасиб еще раз!

Отредактировано emlen (20-02-2016 00:25:22)


SeaMonkey 2.39 forever

Отсутствует

 

№968120-02-2016 00:49:52

emlen
Участник
 
Группа: Members
Зарегистрирован: 22-05-2015
Сообщений: 201
UA: unknown 0.0

Re: Custom Buttons

Dumby, вот эта штука:

Выделить код

Код:

skipPrefixsList.some(prefix => uri.spec.startsWith(prefix))

для чего нужна? И может есть какой метод извлечения из ури доменного имени, или хотябы из ури в урл для

Выделить код

Код:

var chkpoint='/';
var arrayOfStrings = urllink.split(chkpoint);
var site=arrayOfStrings[2];

, чтобы все производные страницы из журнала вычищать тем самым предыдущим рекомендованным Вами методом "removePagesFromHost", а -то остаются "хвосты" к примеру от страниц ВК..? В идеале наверное даже не в этом цикле их чистить, а сначала закрывать все, а потом из закрытых брать все ссылки с историей вкладок и удалять из журнала.. Тока это все так сложно...

Добавлено 20-02-2016 01:07:02
Кнопка "Undo Close Tab" не меняет свое визуальное состояние после выполнения удаления закрытых вкладок из другой кнопки, пока не наведешь на нее мышь, есть какие-то трюки, чтобы она становилась неактивной после зачистки? К примеру, когда эта зачистка идет из кнопки закрывающей все табы после сохранения их адресов в папку, она почему-то сама очищается... видимо реагирует на какой-то ивент при закрытии вкладки или что-то типа того.. а если просто нужно зачистить "закрытые" ничего не закрывая из текущих?

Отредактировано emlen (20-02-2016 02:22:18)


SeaMonkey 2.39 forever

Отсутствует

 

№968220-02-2016 13:08:54

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2255
UA: Firefox 38.0

Re: Custom Buttons

emlen

скрытый текст

для чего нужна?

Ну, не то чтобы нужна, но ведь сам просил
чтоб Speed Start страницы закрывались без занесения в закладки.

И может есть какой метод извлечения из ури доменного имени, или хотябы из ури в урл

У ури есть свойства. Если нужен base domain, используй Services.eTLD.

В идеале наверное даже не в этом цикле их чистить, а сначала закрывать все, а потом из закрытых брать все ссылки с историей вкладок и удалять из журнала..

Только не забудь посетить адрес
about:config?filter=browser.sessionstore.max_tabs_undo;

Отсутствует

 

№968320-02-2016 13:58:49

emlen
Участник
 
Группа: Members
Зарегистрирован: 22-05-2015
Сообщений: 201
UA: unknown 0.0

Re: Custom Buttons

Dumby пишет

Только не забудь посетить адрес
about:config?filter=browser.sessionstore.max_tabs_undo;

ага, то есть тоже не панацея, что какие-то адреса от "замораживаемой" сессии не проскользнут? А по временному интервалу не получится запрос на удаление истории сформировать в контексте текущей задачи?


SeaMonkey 2.39 forever

Отсутствует

 

№968421-02-2016 14:39:25

thrower
Участник
 
Группа: Members
Зарегистрирован: 28-11-2013
Сообщений: 207
UA: Firefox 38.0

Re: Custom Buttons

bunda1,
замечательная кнопка получилась!
Работает и на Firefox, и на Palemoon.
Расширение удалил. Спасибо.

Отсутствует

 

№968522-02-2016 14:03:16

bunda1
Moderator
 
Группа: Moderators
Откуда: Латвия
Зарегистрирован: 09-02-2010
Сообщений: 4811
UA: Firefox 24.0

Re: Custom Buttons

emlen пишет

И встречный вопрос, можно сделать подобное множественным меню? чтобы был выбор из нескольких папок..

Не нужные папки из меню можно удалять по СКМ или ПКМ на папке, пункты меню можно перемещать верх или вниз прокруткой колёсика мыши на пункте меню, для добавления новых папок в меню есть специальный пункт меню:

Выделить код

Код:

// Сохранять изображение без запроса в установленные папки, из контекстного меню, от 22.02.2016. ...............  
((contextMenu, saveimage) => {
   var s = "CB.allPathsToImageFolders";
   var defaultDownFolder = Services.downloads.defaultDownloadsDirectory.path;
   
   
   var menu = contextMenu.insertBefore(document.createElement("menu"), saveimage);
   menu.setAttribute("label", "Сохранить в папку:");
   addEventListener("popupshowing", e=> menu.hidden = saveimage.hidden, false, contextMenu); 
   addDestructor(()=> menu.remove() );
   
      
   var menuPopup = menu.appendChild( document.createElement("menupopup") );
   menuPopup.setAttribute('style', 'overflow: scroll'); 
   function setItemsToMenuPopup() {
      menuPopup.textContent = "";      

      getPaths().split(",").forEach(path=> {
         var mItem = document.createElement("menuitem");
         mItem.setAttribute("tooltiptext", path );
         mItem.setAttribute("label", path.split("\\").pop() );
         mItem.onwheel =e=> moveMenuItem(e, path);
         mItem.onclick =e=> e.button ? deleteFolder(path) : downloadToFolder(path); 
         menuPopup.appendChild( mItem );
      });
      var sep = menuPopup.appendChild( document.createElement("menuseparator") );
      var mItem = menuPopup.appendChild( document.createElement("menuitem") );
      mItem.setAttribute("label", "Добавить папку");
      mItem.onclick =e=> setPaths(); 
   };  
   setItemsToMenuPopup();        


   function downloadToFolder(path) { 
      var run = cbu.getPrefs("browser.download.folderList");
      var use = cbu.getPrefs("browser.download.useDownloadDir");
      try { var dir = Services.prefs.getComplexValue("browser.download.dir", Ci.nsISupportsString).data } 
      catch(e) { var dir = defaultDownFolder };
                
      cbu.setPrefs("browser.download.folderList", 2);
      cbu.setPrefs("browser.download.useDownloadDir", true);
      cbu.setPrefs("browser.download.dir", convertFromUnicode("UTF-8", path) );
      
      saveImageURL(gContextMenu.imageURL, 0, 0, 0, 1, null, content.document);
      
      cbu.setPrefs("browser.download.folderList", run);
      cbu.setPrefs("browser.download.useDownloadDir", use);
      cbu.setPrefs("browser.download.dir", convertFromUnicode("UTF-8", dir) );     
   };
   
   
   function deleteFolder(path) {
      var paths = getPaths().split(",").filter(el=> { return (el !== path) });
      cbu.setPrefs(s, convertFromUnicode("UTF-8", (paths.length ? paths : defaultDownFolder)));
      
      setItemsToMenuPopup();
   };
   
   
   function moveMenuItem(e, path) {
      var arr = getPaths().split(",");
      var pathPos = arr.indexOf(path);
      var index = (e.deltaY < 0 ? -1 : 1);

      if ( (pathPos == 0 && index == -1) || (pathPos+1 == arr.length && index == 1)) return;
      arr[pathPos] = arr[pathPos + index];      
      arr[pathPos + index] = path;      
      cbu.setPrefs(s, convertFromUnicode("UTF-8", arr));
      
      setItemsToMenuPopup();
   };
   
   
   function setPaths() { 
      var fp = window.makeFilePicker();
      fp.init( window, "Укажите путь к папке для сохранения изображений", fp.modeGetFolder );
      if ( fp.show() == fp.returnCancel ) return;
      cbu.setPrefs(s, convertFromUnicode("UTF-8", getPaths() + "," + fp.file.path));
      
      setItemsToMenuPopup();
   };


   function getPaths() { 
      try { return Services.prefs.getComplexValue(s, Ci.nsISupportsString).data; } 
      catch(e) { return defaultDownFolder };
   };   
   
})(document.getElementById("contentAreaContextMenu"), document.getElementById("context-saveimage"));

Отсутствует

 

№968622-02-2016 15:25:52

bunda1
Moderator
 
Группа: Moderators
Откуда: Латвия
Зарегистрирован: 09-02-2010
Сообщений: 4811
UA: Firefox 24.0

Re: Custom Buttons

Вопрос знающим людям: как добавить перетаскивание к пунктам контекстного меню на странице?

Отсутствует

 

№968722-02-2016 19:00:40

Infocatcher
Not found
 
Группа: Extensions
Зарегистрирован: 24-05-2007
Сообщений: 4339
UA: Firefox 44.0

Re: Custom Buttons

bunda1 пишет

Вопрос знающим людям: как добавить перетаскивание к пунктам контекстного меню на странице?

Хм, ну если коротко, то это довольно нетривиально.
Вот пример:
https://github.com/Infocatcher/Custom_B … #L254-L257
И там далее реализация:
https://github.com/Infocatcher/Custom_B … s.js#L1710
Можно искать документацию насчет event.dataTransfer.

Отредактировано Infocatcher (22-02-2016 19:01:04)


Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела

Отсутствует

 

№968822-02-2016 19:08:12

emlen
Участник
 
Группа: Members
Зарегистрирован: 22-05-2015
Сообщений: 201
UA: unknown 0.0

Re: Custom Buttons

Мастер bunda1, Вы великолепны!;)


SeaMonkey 2.39 forever

Отсутствует

 

№968922-02-2016 19:11:07

bunda1
Moderator
 
Группа: Moderators
Откуда: Латвия
Зарегистрирован: 09-02-2010
Сообщений: 4811
UA: Firefox 24.0

Re: Custom Buttons

Infocatcher пишет

Хм, ну если коротко, то это довольно нетривиально.

Мда, сложновато, наверно поищу обходный путь - попробую передвигать пункты меню по меню колёсикам мыши, как то так:

Выделить код

Код:

mItem.onwheel =e=> moveMenuItem(e, path);

function moveMenuItem(e, path) {
   e.deltaY < 0 ? true : false     
.....

Спасибо :)

Добавлено 22-02-2016 19:12:08

emlen пишет

Мастер bunda1, Вы великолепны!;)

Спасибо, приятно когда благодарят :)

Отредактировано bunda1 (22-02-2016 19:12:08)

Отсутствует

 

№969022-02-2016 23:24:21

bunda1
Moderator
 
Группа: Moderators
Откуда: Латвия
Зарегистрирован: 09-02-2010
Сообщений: 4811
UA: Firefox 24.0

Re: Custom Buttons

emlen
Добавил возможность перемещать пункты меню по меню верх или вниз прокруткой колёсика мыши на пункте меню: Сохранять изображение без запроса в установленные папки

Отсутствует

 

№969123-02-2016 00:18:14

difabor
Участник
 
Группа: Members
Зарегистрирован: 21-09-2013
Сообщений: 539
UA: Firefox 28.0
Веб-сайт

Re: Custom Buttons

bunda1 пишет

emlen
Добавил возможность перемещать пункты меню по меню верх или вниз прокруткой колёсика мыши на пункте меню: Сохранять изображение без запроса в установленные папки

А если само меню требует скроллинга?


Хорошо, когда у человека есть выбор, но плохо, когда он перед ним стоит ©

Отсутствует

 

№969223-02-2016 01:55:03

Infocatcher
Not found
 
Группа: Extensions
Зарегистрирован: 24-05-2007
Сообщений: 4339
UA: Firefox 44.0

Re: Custom Buttons

Любители обмазываться e10s'ом тестирования могут попробовать версию с работающими custombutton:// ссылками при включенном мультипроцессном режиме:
http://custombuttons.sourceforge.net/forum/viewtopic.php?p=11477#p11477

Отредактировано Infocatcher (23-02-2016 01:55:58)


Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела

Отсутствует

 

№969323-02-2016 12:10:39

vv07
Участник
 
Группа: Members
Зарегистрирован: 07-11-2007
Сообщений: 689
UA: Firefox 38.0

Re: Custom Buttons

Всех волшебников кнопок С Праздником!
Мучался, мучался с последними версиями лиса и плюнул. Достал меня этот Астралис со своим мультяшным интерфейсом, постоянной анимацией при  переключениях на настройки, аж браузер весь корежит.
Решил вернутся на провереные 16-28,пока не осстановился конкретно. Но не хватает функции одной. Проверенные расширения для текстовых ссылок, либо перестали работать, либо не ставятся на старые версии. Есть тут кнопка http://forum.mozilla-russia.org/viewtop … 97#p562297, все хорошо но работает только по клику на нее. Нельзя ли поправить код, так что бы работала постоянно, делая текстовые ссылки кликабельными и выделяя ее цветным фоном (к примеру желтым). Что бы не кликать ее постоянно.
Буду признателен за помощь.

Отсутствует

 

№969423-02-2016 15:12:53

bunda1
Moderator
 
Группа: Moderators
Откуда: Латвия
Зарегистрирован: 09-02-2010
Сообщений: 4811
UA: Firefox 24.0

Re: Custom Buttons

difabor пишет

А если само меню требует скроллинга?

Выделить код

Код:

menuPopup.setAttribute('style', 'overflow: auto');

overflow | htmlbook.ru

Отсутствует

 

№969523-02-2016 15:55:06

difabor
Участник
 
Группа: Members
Зарегистрирован: 21-09-2013
Сообщений: 539
UA: Firefox 28.0
Веб-сайт

Re: Custom Buttons

bunda1 пишет
difabor пишет

А если само меню требует скроллинга?

Выделить код

Код:

menuPopup.setAttribute('style', 'overflow: auto');

overflow | htmlbook.ru

Да, я понимаю, но что делать, если и меню большое и надо ещё и менюитемы двигать (перемещать)?
У меня есть идея на этот счёт, но не знаю, может это и бред...
Если Х-координата начала меню и ширина меню известны (а этого несложно добиться), то известно и то - в левой или правой половине менюитема делается вращение колёсиком.
Тогда левую половину - отдать под стандартный скроллинг, а правую, через event.preventDefault() и (возможно) event.stopPropagation() - перемещать менюитемы Вашей функцией.
Но если это бред - не ругайте меня сильно :(


Хорошо, когда у человека есть выбор, но плохо, когда он перед ним стоит ©

Отсутствует

 

№969623-02-2016 16:40:03

bunda1
Moderator
 
Группа: Moderators
Откуда: Латвия
Зарегистрирован: 09-02-2010
Сообщений: 4811
UA: Firefox 24.0

Re: Custom Buttons

difabor пишет

Да, я понимаю, но что делать, если и меню большое и надо ещё и менюитемы двигать (перемещать)?

Спасибо, я об этом не подумал. Можно сделать Ctrl+скрол или там ПКМ+скрол, вобщем надо ещё подумать.

Отсутствует

 

№969723-02-2016 17:42:30

fokanik
Участник
 
Группа: Members
Зарегистрирован: 05-02-2014
Сообщений: 268
UA: Seamonkey 2.39

Re: Custom Buttons

Выделить код

Код:

["Rox Player", "C:\\Users\\Home\\AppData\\Local\\ROX Player\\roxplayer.exe", "rox:"],              //http://roxplayer.com/

Смотрим торрент видео в плеере ROX с возможностью перемотки - только видео :)
Параметры запуска не обязательные - "rox:"
Открывает по ссылке из браузера магнитики и торрент ссылки:
54ad42109751.jpg

Отсутствует

 

№969823-02-2016 19:43:08

difabor
Участник
 
Группа: Members
Зарегистрирован: 21-09-2013
Сообщений: 539
UA: Firefox 28.0
Веб-сайт

Re: Custom Buttons

Вопрос к знающим: где-то я читал, что использовать eval(...) нежелательно.
Он что, сильно влияет на производительность или жрёт память?


Хорошо, когда у человека есть выбор, но плохо, когда он перед ним стоит ©

Отсутствует

 

№969923-02-2016 22:06:48

Baron_
Забанен
 
Группа: Members
Зарегистрирован: 13-08-2013
Сообщений: 71
UA: Firefox 44.0

Re: Custom Buttons

fokanik пишет

Смотрим торрент видео в плеере ROX с возможностью перемотки - только видео :).....

А можно подробнее, куда этот код вставлять? Создал кнопку, вставил код в инициализацию, пути поправил на свои. Пункта меню нет. Что не так?

Отсутствует

 

№970023-02-2016 22:35:01

fokanik
Участник
 
Группа: Members
Зарегистрирован: 05-02-2014
Сообщений: 268
UA: Seamonkey 2.39

Re: Custom Buttons

Baron_ пишет

fokanik пишет: Смотрим торрент видео в плеере ROX с возможностью перемотки - только видео .....А можно подробнее, куда этот код вставлять? Создал кнопку, вставил код в инициализацию, пути поправил на свои. Пункта меню нет. Что не так?

Выделить код

Код:

if ( this.hasAttribute("initialized") ) return;
this.setAttribute("context", "");
this.tooltipText="PotPlayer --->\n<--- SMPlayer";

var id = "context-bookmarklink"; // Место врезки

this.onclick = function(e) {
     if ( e.button == 0 ) Play(array[0][1], "-add-to-playlist", "href"); // ПКМ
     if ( e.button == 1 ) gShowPopup(this);                              // Редактировать кнопку
     if ( e.button == 2 ) Play(array[1][1], "/add", "href");             // ЛКМ
}

var contextMenu = document.getElementById("contentAreaContextMenu"); 
var sepOpen = document.getElementById(id);

var array = [
 ["SMPlayer", "C:\\Program Files\\SMPlayer\\smplayer.exe", "-add-to-playlist" ],                    //http://smplayer.sourceforge.net/
 ["PotPlayer", "C:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini.exe", "/add" ],                   //https://potplayer.daum.net/?lang=ru
 ["Video Lan", "C:\\Program Files\\VideoLan\\vlc\\vlc.exe", "-AddToPlaylist" ],                     //http://www.videolan.org/vlc/
 ["Rox Player", "C:\\Users\\Home\\AppData\\Local\\ROX Player\\roxplayer.exe", "rox:"],              //http://roxplayer.com/
 ["Download Master", "P:\\PortableApps\\PortableApps\\Download Master Portable\\dmaster.exe", ""],
 
 ["separator"]
            ]
array.forEach(function(m) {
   if (m == "separator") {
       contextMenu.insertBefore(document.createElement("menuseparator"), sepOpen);
       return;
       };
   var menuitem = contextMenu.insertBefore(document.createElement("menuitem"), sepOpen);
   menuitem.id = "open-in";
   var label = m[0], path = m[1], param = m[2]; 
   menuitem.setAttribute("label", label);
   menuitem.setAttribute("class", "menuitem-iconic");
   menuitem.setAttribute("image", "moz-icon://file://" + path);   
   menuitem.onclick =()=> Play(path, param, "");
});
   
addDestructor(function() {
   [...contextMenu.childNodes].forEach(function(el) {
      if (el.id == "open-in")
          contextMenu.removeChild(el);
   }) 
});

function Play(path, param, link){
   var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
   file.initWithPath(path);
   var process  = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
   process.init(file);
   if (link == "href" || !gContextMenu.onLink) process.run(false, [content.location.href, param], 2);
   else process.run(false, [gContextMenu.getLinkURL(), param], 2);
}

Меню кнопки по - скм (дальше думаю разберетесь сами).

Еще в плеере путь - куда файлы загружаются измените и можно будет фильмы после просмотра вытаскивать из кэша:
5511441c1985.jpg

А можно подробнее, куда этот код вставлять? - в инициализацию, а потом еще нужно браузер перезапустить, чтоб все заработало - если путь к программе верен иконка должна появиться.

Отредактировано fokanik (23-02-2016 22:41:14)

Отсутствует

 

Board footer

Powered by PunBB
Modified by Mozilla Russia
Copyright © 2004–2020 Mozilla Russia GitHub mark
Язык отображения форума: [Русский] [English]