📜 ⬆️ ⬇️

Creating and publishing an extension

image

In my previous topic Bexf - Framework for creating extensions, I promised that I would write a sequel. My extension, written in Bexf, was published and in honor of this, I decided to continue the theme of extensions for Opera.

The article: architecture extensions, interesting points in the process of writing the Habra Meter (hereinafter HM) on Bexf, the publication of the extension.

Architecture


Studying the topic of extensions, I looked at a dozen sources, and in each, as usual, a different architecture. Architecture is definitely a matter of each; below I give my version (HM file architecture):
/ images/ //  ,   font.png icon-18.png icon-64.png includes/ //  . ,      vendors/ //    Bexf.js jquery-1.4.4.min.js jquery.flot-0.6.min.js css/ //  CSS style.css js/ //  JS options.js popup.js Widget.js config.xml //  . .   index.html //  . .   options.html //  .  popup.html //   

Standard files and folders

The includes / folder includes .js / .css files that connect to certain pages of the Opera and can interact with extensions. Each script is a Greasemonkey UserScript
// ==UserScript==
// @name --
// @namespace --
// @description --
// @author --
// @include mediafire.com*
// @include http://*.mediafire.com/*
// ==/UserScript==

//
HM has no plugin scripts.
')
config.xml - extension settings. On the description of the format, I will not dwell on everything and so well stated here www.opera.com/docs/apis/extensions/configxmlresourceguide
index.html - index file that initializes the extension (you can change the name)
options.html - options, if available, Opera activates the Extension Settings. Options is the html page of any content, like popup.

Writing extension


Then I will not describe every little thing, only the main points. The code is open , so you can all have a look.

Index

This file has no view, so it makes no sense to insert something into the body and include CSS. In my case, the script will connect Bexf.js and Widget.js (the main script of HM). Widget initializes the extension through the init method.
  init: function () { var self = this; this.font = new global.Image(); this.font.src = "images/font.png"; this.icon = new global.Image(); this.icon.src = "images/icon-18.png"; this.icon.onload = function () { self.button = $.createButton(self._buttonInitOptions) .addToPanel(); self.requestUpdates(); self.initTimer(); }; } 

The method connects the necessary resources: sprite font (font.png) and a button template (icon-18.png) about them further. Initializes the button, immediately updates it, starts the update timer.

In the project, I needed to dynamically change the image on the button to display karma and rating, moreover, the image had to be created on the canvas. There was a problem: a picture of a maximum of 18x18 and therefore any standard font would be completely unreadable (in principle, what is now too much does not shine) - created sprite font 3x5: 0-9, AF and comma / dot all the parameters of the letters painted in fontDemensions. Although index.html does not have a view, it does have a document, so it turned out to be possible to dynamically generate an icon via canvas and retrieve its data through canvas.toDataURL (). Below are 2 methods that are responsible for rendering:
  _drawText: function (ctx, x, y, text) { text = text.split(''); for (var i = 0, c = text.length, g; i < c; i+= 1) { g = this.fontDemensions[text[i]]; ctx.drawImage(this.font, gx, gy, gw, gh, x, y, gw, gh); x += gw; } }, drawIcon: function (karma, rating) { karma += ''; rating += ''; var canvas = document.createElement('canvas'); // Create an empty canvas element canvas.setAttribute('width', '18px'); canvas.setAttribute('height', '18px'); // Copy the image contents to the canvas var ctx = canvas.getContext("2d"), offset; ctx.drawImage(this.icon, 0, 0); // Draw karma offset = 8 - (2 * karma.length) + (karma.indexOf('.') >= 0 ? 2 : 0) + (karma.indexOf(',') >= 0 ? 2 : 0); this._drawText(ctx, offset, 2, karma); // Draw rating offset = 8 - (2 * rating.length) + (rating.indexOf('.') >= 0 ? 2 : 0) + (rating.indexOf(',') >= 0 ? 2 : 0); this._drawText(ctx, offset, 11, rating); return canvas.toDataURL(); } 
After closing the options window, update the button (mb user changed)
  $.disconnect(function () { Widget.requestUpdates.call(Widget); Widget.initTimer.call(Widget); }); 

Nothing more interesting in Widget.js. All that remains is parsing the habouser page (XHR cross-domain), collecting statistics for the month and other utilitarian methods.

Options

options.html - the usual html file of any content, it is assumed that it will manage widget.preferences (Bexf.opt) - personal data extensions.
The file has a default structure (all fields are marked). And its logic is simple: when initializing it loads values ​​into form fields, when you click the “save” button, it returns data to widget.preferences.

Pop-up window

popup.html - a regular html file of any content (but of a limited size) can be any name, the pop-up button is controlled. The number of popups is unlimited. The popup is initialized every time (executes all the code) when it is opened. In the case of HM, the pop-up contains a graph of changes in user parameters for the last 30 days. The graph is drawn on the canvas using jQuery Flot (in the first version, the Google Chart API was drawn, more I don’t use the GC API). Popup script parses statistics data (because widget.preferences is a DOMStorage object, its values ​​cannot be an object) stored in Bexf.opt ('stat') and converts them into a format that jQuery Flot understands. Nothing more interesting.

Testing


Opera developers thought about us, so testing extensions is very simple: we throw config.xml into the browser and the extension connects in debug mode, you can reload (update code) / Disable / Delete in the Opera extension manager just like a regular extension. As lugansk wrote , “Dragonfly doesn’t know how to work with them (Errors)”, but the opera.postError method works and its result can be viewed in the Error Console (Ctrl + Shift + O). Dragonfly doesn’t know how to work with opera.postError from extensions.

Publication


1. You need to test the extension
2. Create an Opera account (it’s one for all services) - my.opera.com/community/signup
3. Come up with a name, a brief description, a detailed description.
4. Make at least 1 screenshot
5. Draw 64x64 icons (required) 18x18 (if there are buttons)
6. Come up with a version of the extension, for example 1.0
7. Pack the extension in .oex - renamed .zip
Once everything is ready, log in and load the extension, following the instructions of the download wizard addons.opera.com/developer/extensions/upload
As soon as you have downloaded the extension, it will get on moderation (1-2 days) and after that it will be available for download. The updated extension also passes moderation (1-2days). And it is believed that about very frequent version changes, moderators lower the priority of your extension.
Read more about publishing addons.opera.com/developer/guidelines

Read


General topics for extensions www.opera.com/addons/extensions/develop
Format config.xml www.opera.com/docs/apis/extensions/configxmlresourceguide
Development Mode dev.opera.com/articles/view/opera-extensions-developer-workflow
API extensions www.opera.com/docs/apis/extensions
Bexf - a framework that was used when writing HM habrahabr.ru/blogs/opera/111461
Another example of creating the dev.opera.com/articles/view/hands-on-building-an-opera-extension extension
Opera docks translations and examples from hacker SonicGD : Messaging , Windows , UserJS , Your first extension for Opera , Buttons, badges and pop-ups

The official version (moderated) of HM can be found among all extensions of the opera addons.opera.com/addons/extensions/details/habra-meter
The latest version, the architecture presented in this article, can be downloaded here: browser-extensions-framework.googlecode.com/files/habra-meter-1.1.1.oex (this is renamed .zip)

I will be glad to answer your questions. Now, I think, the question of extensions of the Opera is fully disclosed on Habré.

PS Do not put the Habra Meter - constant observations of karma leads to mental illness. This is an extension of the proof of concept of my Bexf framework.

Source: https://habr.com/ru/post/111666/


All Articles