簡単なOpera拡張機能の作成

この記事は、Operaブラウザ用の簡単な拡張機能を記述することについてです。 拡張機能は次のようにプリミティブになります。 その機能はすべて、habrahabr.ruのuser-JSになります。 コメントフィードには、トピック内の新しいコメントの数を表示するブロックと、このフィードを更新できるボタンが装備されています。 そこに矢印を追加して、新しいコメントをナビゲートしましょう。







どこから始めますか?





XMLコンテンツ:

<?xml version="1.0" encoding="UTF-8"?> <widget xmlns="http://www.w3.org/ns/widgets" id="http://faiwer.ru" version="0.9a" defaultlocale="en"> <name xml:lang="en">HabrCommentSwitcher</name> <description xml:lang="en">Habrahabr. New comment switcher</description> <description xml:lang="ru">Habrahabr.   </description> <author href="faiwer.ru" email="faiwer@gmail.com">Faiwer</author> <icon src="icons/64x64.png"/> <icon src="icons/48x48.png"/> <icon src="icons/32x32.png"/> </widget>
      
      





この記事は教育的なものであるため、各項目について詳しく説明するのではなく、 ドキュメントの方がうまくいきます。 最も重要なことについて説明しましょう。



さらに多くのオプションが利用可能です。 しかし、まず第一に、これらの十分な。 config.xmlでは、名前と説明に複数の言語バージョンを一度に指定できることに気づいたと思います。



最後に、index.htmlを作成します。 「オフスクリーン」スクリプトを機能させるために必要です。このスクリプトは、ブラウザーの起動とともに起動され、どのタブにも添付されません。 私たちはそれを必要としませんが、それなしではOperaは「手に入れる」ことを許しません。 ファイルは空白のままにすることができます。 ここで、ドラッグアンドドロップを使用して、config.xmlをブラウザーにドラッグアンドドロップします。 すべてがうまくいけば、インストールされた拡張機能のリストを含むページが開き、「開発者モード」セクションの一番上に表示されます。



Userjs



最初は、将来の拡張で何をすべきかを決定する必要があります。



これらすべてのために、各habrahabrページに対して実行される最初のファイルで十分です。 つまり UserJSは私たちに最適です。 ただし、ChromeがUserJSを拡張機能自体に変換でき、FirefoxがそのためにGreasemonkeyを必要とする場合、Operaの場合、拡張機能として設計するか、手動でインストールできます(F12-サイトの設定-スクリプト)。



includeディレクトリを作成してみましょう。Operaは「埋め込み」スクリプトを検索します。 その中で、habr_comment_switcher.jsファイルを作成します(ここでは任意の名前を選択できます)。 ファイルの先頭に、次を配置します。

 // ==UserScript== // @include http://habrahabr.ru/* // ==/UserScript==
      
      





これらは単なるjsのコメントではなく、これはUserJSの特別なマークアップです。この場合、この埋め込みファイルはhabrahabr.ruでのみ実行されるべきであるとオペラに説明します。



Javascript



このファイルに加えて、jQueryやPrototypeなどのライブラリを導入することもできます。 しかし、これを行うことは強くお勧めしません。 この種のライブラリは非常に重要です。 タブごとに読み込まれるだけでなく、ページ上に多数あるiframeごとにも読み込まれます。これらの拡張機能の5〜10個がブレーキをかける可能性があります。 私たちのタスクは非常に控えめであるため、多くを失うことはありません。



UPD2 。ありがとう、 kns 。 ページがすでに人気のあるライブラリの1つを使用している場合、それを使用できます。 詳細についてはこちらをご覧ください 。 Operaの場合、次のようになります。

 var $ = window.jQuery;
      
      







コードを書き始めましょう。 まず、便宜上、すべてをanon.functionに入れます。 なぜなら 私たちのjavascript環境はサイトのjavascript環境から分離されていますが、これは必要ではありませんが、私の意見では、これは長い間良いルールでした:

 +function( w ) { }( window );
      
      





私はあなたのことは知りませんが、特定のオブジェクト内での作業に慣れているため、次のように定義します。

  var Engine = function(){ this._init(); } Engine.prototype = { _init: function() { } }
      
      





次に、作成の条件を作成する必要があります。

  if( w.location.href.indexOf( 'habrahabr.ru' ) > 0 ) { var engine = false; d.addEventListener( 'DOMContentLoaded', function() { setTimeout( function(){ engine = new Engine(); }, 1500 ); }, false ); }
      
      





ページアドレスの確認は、論理的な引数ではなく、偏執狂によって引き起こされます。 事実、Operaは時々UserJSのルールに対応していないというネットワークで何度か出会いました。 オブジェクトは、ページのDOMツリー全体が構築されてから1.5秒後に起動されます。 なぜ1.5秒ですか? 実際、スライダーはすぐには表示されないため、待機します。 これはよりエレガントに実現することができますが、これまでのところこれは実現します。



延長工事



現在、Operaは最も高度なブラウザではありませんが、その機能はIE6、7、8よりもはるかに優れています。 したがって、通常のWebプログラミングでは使用しないようなことを活用できます。 作業を少し簡素化します。

  var d = w.document, $ = d.querySelector.bind( d ), $$ = d.querySelectorAll.bind( d )
      
      





querySelectorおよびquerySelectorAllメソッドを使用すると、CSSセレクターによってDOMオブジェクトを検索できます。 おそらく、jQueryの経験からこのアプローチを知っているでしょう。 この場合、関数$は要求を満たす要素を1つ探し、$$はリストです。



リストには何がありますか? はい、問題ではありません。必要なCSSをページに埋め込みましょう。

 _cssInject: function() { var style = this._createElem( this.elem.style_inject ), text = ''; for( var i = 0, n = this.css.length; i < n; ++ i ) { text += this.css[ i ]; } style.innerHTML = text; d.head.appendChild( style ); }
      
      





ここでは、新しい<style /> DOMオブジェクトを作成し、必要なCSSコードをコンテンツとして設定します。 なぜなら ページの準備ができましたdocument.headが利用可能になり、タグを配置します。 _createElem関数について:

  _createElem: function( data ) { var item = d.createElement( data.tagName ); if( data.attr ) { for( var rule in data.attr ) { item.setAttribute( rule, data.attr[ rule ] ); } } return item; },
      
      





次のように、設定を使用して作業を整理できます。

 _initConst: function() { this._extend( this, { css: [ '.__hcsc_button { border-top: 1px solid white; line-height: 22px; height: 22px; ' + 'cursor: pointer; }', '.__hcsc_button:hover { color: white; }', '.info.__hcsc_active { outline: 2px solid #222; }', ], elem: { style_inject: { tagName: 'style', attr: { id: '__habr_comment_switcher_css' } } } } ); }, _extend: function( object, extend ) { for( var name in extend ) if( extend.hasOwnProperty( name ) ) { object[ name ] = extend[ name ]; } },
      
      





メインロジックに移りましょう。 スライダーを見つけて、2つのボタンを追加する必要があります。

 _prepareSlider: function() { var slider = $( this.s.slider ); if( !slider ) { return; } this.up_button = this._createElem( this.elem.button ); this.up_button.innerHTML = '▲'; slider.appendChild( this.up_button ); this.down_button = this._createElem( this.elem.button ); this.down_button.innerHTML = '▼'; slider.appendChild( this.down_button ); },
      
      





矢印はテキストで設定できます。 次に、これらのボタンを復活させる必要があります。

 _observe: function() { this.up_button.addEventListener( 'click', this._slideClick.bind( this, -1 ), false ); this.down_button.addEventListener( 'click', this._slideClick.bind( this, +1 ), false ); },
      
      





そして最後に、待望のリーフレット:

 _checkItems: function() { var items = $$( this.s.info_panel ); if( !this.items || !this.items.length || !items.length || ( this.items[ 0 ] !== items[ 0 ] ) ) { this.position = -1; this.items = items; } return this.items; }, _slideClick: function( diff ) { if( this.current ) { this.current.classList.remove( this.c.active ); } if( !this._checkItems().length ) { return; } this.position += diff; if( this.position < 0 ) { this.position = this.items.length - 1; } else if( this.position >= this.items.length ) { this.position = 0; } this.current = this.items[ this.position ]; this.current.scrollIntoView( true ); this.current.classList.add( this.c.active ); }
      
      





彼女の論理は単純です。 this.s.info_panel( ".comment_item> .info.is_new")で指定されたCSSセレクターに関するすべての新しいコメントを探しています。 彼は新しいコメントのすべてのタイトルブロックを見つけました。 次に、クリックしたボタンに応じて、scrollIntoViewを使用してページスクロールを目的のコメントに移動します。 このイベントをより視覚的にするために、暗い境界線(アウトライン)を持つCSSが上で定義されたクラスを追加します。



更新ボタンが利用可能であり、新しいコメントのリストが古くなる可能性があるため、拡張機能は毎回古いリストと現在のリストをチェックし、それらが異なる場合、位置カウンターをリセットします。



それとは別に、DOMオブジェクトのクラスを操作する機能について詳しく説明します。 ラインitem.className、tkを手動で解析する必要はありません。 以下の方法が利用可能です:

 this.current.classList.add( 'my_class' ); this.current.classList.remove( 'my_class' );
      
      







「デバッグ」について少し



最初に、Ctrl + Shift + i(またはマウスの右ボタン-「オブジェクトの検査」)で呼び出されるDragonfly (トンボ)などのツールがあります。 その[スクリプト]タブのドロップダウンリストにhabr_comment_switcher.jsがあります。 これで、ブレークポイントとトレースを使用できます(F8、F10、F11)。 コンソールも使用できますが、スクリプトと同じjs環境で動作するには、まずスクリプトのドロップダウンリストでその番号を確認する必要があります。



エラーを表示するには、インストールされている拡張機能ページの[エラーコンソールを開く]ボタンをクリックします。 拡張機能のコンソールオブジェクトは機能しません。 拡張機能を更新するには、トンボを閉じ、拡張機能ページで「更新」をクリックし、目的のタブでトンボを開き、ブラウザで「更新」をクリックする必要があります。 一般的に、トンボで拡張機能を使用する印象は最悪です。 特に、Chromeの拡張機能を開発した経験の後。



最後のタッチ



すべてが機能しているように見えるので、拡張機能をパックします。 これを行うには、拡張フォルダーの内容を zipアーカイブに圧縮し、ファイル拡張子をoexに変更します。 これで拡張機能の準備は完了です。 使用できます。 拡張機能が破損しているとOperaが誓う場合は、フォルダの内容ではなく、その内容を圧縮したのかもしれません。 config.xmlおよびindex.htmlファイルも確認してください。

画像



エピローグ



ほら! 拡張機能はアルファ段階で準備ができています。 改善し、ChromeとGreasemonkeyのサポートを追加します(そのようにうまくいかないかはわかりませんが)、設定ページを追加します(たとえば、色を設定したり、CSSセレクターを変更したりします)。



ここで完成した拡張機能を見ることができます初めてgitを使用するときは、何か問題がある場合は失礼します。



All Articles