KiberInfinity edited this page Oct 15, 2016 · 41 revisions

Оглавление

Сборка расширения из исходников

  • Запустить _build.bat (Windows) или _build.sh (Linux/Mac).
    Скрипты из папки source/ скопируются в папку builds/[браузер]/
  • запустить сборку для нужного браузера:
    • Если у вас установлен Python, запускаем builds/_[браузер]_pack.bat
    • Если нет, но установлен WinRAR - то тогда builds/_winrar_[браузер].bat

Cобранное расширение появится в папке builds/.

Расширенные настройки

Для целей отладки расширения существуют дополнительные настройки, которые скрыты. См. страницу Расширенные настройки.

Принцип организации работы расширения

VkOpt состоит из двух вспомогательных скриптов, исполняемых в песочницах браузеров: background.js и content_script.js - далее "загрузчик".

Их можно считать одним целым. Их основная задача - инъектировать нужные скрипты в страницы. Загрузчик срабатывает в каждой странице vk.com и в каждом фрейме на ней.

Скрипты инъектируются в контекст страницы, а не исполняются в песочнице расширения, потому что они тесно взаимодействуют со скриптами самого сайта, которые, очевидно, видно только в контексте страницы.

Есть всего два варианта набора скриптов, которые инъектирует загрузчик:

  • для основной страницы (для window.top)
  • для фрейма (запускаются в каждом фрейме)

Конкретные списки скриптов можно посмотреть в начале background.js:

   packed_scripts:[
      // Набор для основной страницы.
      {
         // 1 - для window.top, 0 - для фреймов. Кто-нибудь, назовите это адекватнее!
         "in_frames":1,

         // Отвечает за время инъектирования - до или после DOMContentLoaded/Load.
         "run_at":0,

         // Можно смело сжимать эти файлы в таком порядке.
         "files":[
            "vkopt.js",
            "vk_face.js",
            "vk_lib.js",
            "vk_main.js",
            "vk_media.js",
            "vk_page.js",
            "vk_resources.js",
            "vk_settings.js",
            "vk_skinman.js",
            "vk_txtedit.js",
            "vk_users.js",
            "vklang.js"
         ],

         // Инфа для загрузчика. Назначение вполне очевидно, хотя тоже можно рефакторить.
         "domain":"vkontakte\\.ru|vk\\.com",
         "exclude":"|notifier\\.php|im_frame\\.php|about:blank|i",
         "api_enabled":true
      },

      // Набор для фреймов.
      {
         // in_frames не указано, значит, нестрого равно 0 - для фреймов.
         // Всего один файл.
         "files":["vk_lib.js"],

         "domain":"vkontakte\\.ru|vk\\.com|vk\\.me|userapi\\.com",
         "exclude":"|notifier\\.php|im_frame\\.php|about:blank|i"
      }
   ]

Механизм плагинов

Чтобы по всякой мелочи не править код вкопта для подключения к часто используемым местам в 2.х версии был реализован механизм плагинов.
Текущая версия вкопта 3.x полностью состоит из отдельных модулей, напрямую не взаимодействующих между собой (за некоторыми исключениями), и помещаемых в объект vkopt примерно так:

vkopt['myModuleName'] = {
  обработчик1: function(...){ ... },
  handler2: function(...){ 
     vkopt.myModuleName.mega_func( ... )
  },
  ...
  mega_func: function(...){ ... },
}

Опрос интересующего обработчика у всех модулей производится подобным вызовом

var result_array = vkopt_core.plugins.call_modules('названиеОбработчика', аргумент1, агрумент2, ..., аргументN);

На выходе получаем массив с результатами выполнения обработчиков модулей, если обработчики с там названием были у них обнаружены. В обработчик в модуль передаются аргументы переданные после названия обработчика, если же в качестве обработчика у модуля указана не функция, то в result_array попадёт то, что указано вместо функции (строка, объект и т.д) Т.е существуют обработчики вызываемые как и ядром вкопта, так и другими модулями. Это нужно например в том случае, если мы добавили своим модулем какую-то менюшку, в которую, возможно, какой-то другой модуль захочет добавить и свои пункты тоже. В этом случае наш модуль при генерации меню вызывает нечто такое:

var additional_items = vkopt_core.plugins.call_modules('onMyCoolMenuItems', 'id1'); // в текущем примере additional_items = [['item1','item2','item3'],['item4_id1','item5_id1']];

А в другие модули выглядят как-то так:

vkopt['extend_cool_menu'] = {
  onMyCoolMenuItems: function(user_id){
     return ['item1','item2','item3']
  }
}

vkopt['menu_extender'] = {
  onMyCoolMenuItems: function(user_id){
     return ['item4_'+user_id,'item5_'+user_id]
  }
}

Пример кода подключения модуля к существующим обработчикам вкопта (если код располагается в файлах расширения, то вызов vkopt_core.plugins.delayed_run не обязателен):

   var m = {
      id: 'vkopt_any_plugin',
      // <core>
      onInit:                 function(){},                                // выполняется один раз после загрузки страницы
      onLibFiles:             function(file_name){},                       // место для инъекций - срабатывает при подключении нового js-файла c именем file_name движком контакта через stManager.
      onLocation:             function(nav_obj,cur_module_name){},         // вызывается при переходе между страницами, nav_obj - распарсенный в объект URL страницы
      onRequestQuery:         function(url, query, options){}              // вызывается перед выполнением запроса через ajax.post. Если функция вернёт false, то запрос выполнен не будет. Можно изменять поля объектов query и options
      onResponseAnswer:       function(answer,url,params){},               // перехват ответов на ajax-запросы выполняемые скриптами vk. answer - массив аргументов передаваемых потом в коллбек аякс-запроса, для модификации изменять только его элементы, url и объект params позволяют понять, куда был направлен запрос. 
      onCmd :                 function(command_obj){},          // слушает сообщения отосланные из других вкладок вк через vkopt.cmd(command_obj)
      processNode:            function(node, params){}                     // обработка элемента
      processLinks:           function(link, params){},                    // обработка элемента ссылки <a>
      onModuleDelayedInit:    function(plugin_id){},                       // реакция нашего модуля на то, что подключился какой-то другой модуля, опоздавший появиться до полной загрузки страницы.
      onElementTooltipFirstTimeShow: function(ett, ett_options)            // реакция на первый показ ElementTooltip, при создании его контента. На момент вызова в элементе ett._ttel уже есть контент. По ett._opts.id можно определить к чему тултип относится. Например через это реализовано подсовывание доп. пунктов в "Ещё" просмотрщика фото
      
      // <settings>
      onSettings:             function(){} || {}                           // возвращаем объект с перечисленными по категориям настройками этого модуля
      onOptionChanged:        function(option_id, val, option_data){},     // реакция на изменение опции
      firstRun:               function(){}                                 // вызывается при первом запуске (не найдены ранее прописанные настройки vkopt'a), 
                                                                           // P.S. вкопт из хранилища расширения восстанавливает только данные из своего конфига, если они были сохранены,
                                                                           // тогда это первым запуском не считается, но в локальном хранилище могут отсутствовать данные от других модулей, 
                                                                           // хранящих инфу не через vkopt.settings.get | vkopt.settings.set
      
      // <audio>
      onAudioRowMenuItems: function(audio_info_obj){},                     // вернуть массив из строк с пунктами-ссылками "<a>..</a>"
      
      // <wall>
      onDatepickerCreate: function(args){},                                // вызывается при создании селектора даты new Datepicker(), args - массив аргументов переданных в конструктор
   };
   window.vkopt = (window.vkopt || {});
   window.vkopt[m.id] = m;
   if (window.vkopt_core_ready) vkopt_core.plugins.delayed_run(m.id);      // запускает модуль, если мы опоздали к загрузке страницы, провоцирует вызов события onModuleDelayedInit

Возвращаемая для обработчика onSettings структура выглядит так:

   onSettings:{
      "Категория":{  // Название категории подставляется как ID строки из vk_lang.js. По умолчанию используются такие категории: Media, Users, vkInterface, Messages, Others, Extra
         "[id_опции]":{
            title: 'ID строки из ленга, либо текст без локализации',
            class_toggler: true // указывает, что при включенной опции нужно добавлять к тегу <html> css-класс с именем "vk_[id_опции]",
            info: '', // TODO: будет использоваться для пометок опций предупреждениями
            need_reload: true // TODO: будет показывать пользователям, что для применения этой опции нужно обновить страницу
            
         }
      }
   },

[Пример модуля](Примеры модулей) для выбора кастомного цвета фона сайта

Функции, доступные в VkOpt-e

VkOpt предоставляет публичный API для плагинов VkOpt и сторонних расширений. См. страницу Публичный API расширения.

AMO

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.