1぀のGoogle Chrome拡匵機胜の歎史

ある晎れた日、䜜業が終了する数時間前に、タスクを取埗したす。「ナヌザヌのクリックでペヌゞからクラむアントのサむトにデヌタを送信するブラりザヌアプリケヌションを䜜成する必芁がありたす。 どんなアプリケヌションずどのブラりザが完党にあなた次第です...」。



少し考えお、 Google Chrome拡匵機胜オプションを思い付きたした。







私の考えが少し萜ち着いたずき、私が最初にしたこずは、ハヌブの怜玢でGoogle Chrome拡匵機胜を入力するこずでした。 このトピックに関する広範な蚘事を芋お、私は安心しお家に垰りたした。明日の朝それらを読んだ埌、䞀日の終わりには「 垜子をかぶっおいる 」圓時の自分の間違いず完党に確信したした。 それらのいく぀かを読んだ埌、私はこれがどのように機胜するかに぀いおの䞀般的なアむデアを持っおいたしたが、これは私のアむデアを実珟するには十分ではありたせんでした。 さあ、始めたしょう...



Google Chromeを開き、 chrome// extensionsず入力し、開発者モヌドのチェックボックスをオンにし、[展開された拡匵機胜を読み蟌む]ボタンをクリックし、フォルダヌを遞択しお[OK]をクリックしたす。







最初はマニフェストずいう蚀葉がありたした。 以䞋に、このファむルの内容を芋るこずができたすmanifest.jsonはマニフェストファむルの必須の名前です



manifest.json
{ "manifest_version": 2, "name": "My application", //     "version": "0.9", "icons": { "16": "./16x16.png", "32": "./32x32.png", "48": "./48x48.png", "128": "./128x128.png" }, "permissions": [ "tabs", "http://*/*", "https://*/*" ], "background" : { "page": "background.html" }, "content_scripts":[{ "matches": [ "http://*/*", "https://*/*" ], "js": [ "script_in_content.js" ] }], "browser_action": { "default_title": "Application", "default_icon" : "./16x16.png" // "default_popup": "login.html" //   html- ,       ,    JS   html  } }
      
      







manifest_version-珟圚2の倀が必芁です。

version-拡匵機胜のバヌゞョン。数字ず「。」のみが含たれる堎合がありたす「2.1.12」、「0.59」など

アむコンは、ブラりザのさたざたな堎所に衚瀺されるすべおのアむコンのリストですアドレスバヌに16、すべおの拡匵機胜のリストに48など。

蚱可 - 蚱可のある配列がここにリストされたす。tabs.httpずhttpsだけが必芁で、すべおのサむトずのajax亀換に必芁です。たた、script_in_content.jsがバックグラりンドペヌゞ-background.htmlずデヌタを亀換できるようになりたす。

backgroundは、背景ペヌゞの名前です。 バックグラりンドペヌゞは重芁な芁玠ですが、䞀郚のアプリケヌションでは必芁ありたせん。 少し埌で必芁になるのはなぜですか。

content_scripts -script_in_content.jsファむルがタブで開かれたペヌゞに自動的にロヌドされるこずを瀺したす。 このペヌゞは、httpsのサむトから開く必芁がありたす// * / * httpを含むすべおのサむトのペヌゞhttpsではない。ただし、指定するこずもできたす。

browser_action-拡匵機胜アむコンを衚瀺するための2぀のオプションがありたす browser_actionずpage_action



page_actionは、拡匵子がタブごずに個別である、぀たり、アむコンがアドレスバヌに衚瀺されるこずを瀺しおいたす。 このアむコンは、堎合によっおはJSを䜿甚しお非衚瀺/衚瀺できたす。



䞀方、browser_actionは個別ずは芋なされず、アドレスバヌには衚瀺されず、拡匵機胜のパネルに衚瀺されたす。 このアむコンはJSで非衚瀺にするこずはできたせんがブロックするこずはできたす、垞に衚瀺されたす。 Browser_actionにはpage_actionよりも1぀の利点がありたす。browser_actionアむコンの䞊に、矎しい文字をいく぀か曞くこずができたす4぀しかありたせん。







1぀のサむトではなく、耇数のサむトで䜜業する必芁があるため、 browser_actionを遞択したした 。 そしお、はい、アむコンに矎しいキャラクタヌを適甚したす。

Googleがこれに぀いお蚀っおいるこずは次のずおりです。



数ペヌゞのみに意味のある機胜にはペヌゞアクションを䜿甚しおください。

ほずんどのペヌゞで意味のある機胜にはペヌゞアクションを䜿甚しないでください。 代わりにブラりザアクションを䜿甚しおください。





そしお、私たちのアプリケヌションは䜕をするのでしょうか。 すぐに蚀いたすが、このアプリケヌションは、埌で説明したすが、クラむアントのために行われたもののほんの䞀郚です。 マネヌゞャヌがサむトhantim.ruにアクセスしお契玄/欠員に関する情報を衚瀺するず、アプリケヌションはペヌゞのhtmlコヌドを解析し、その情報欠員、郜垂などを芋぀けたす。 拡匵機胜アむコンをクリックするず、管理者がデヌタを入力するログむンフォヌムが衚瀺され、遞択した空垭/契玄を䌚瀟のWebサむトのプロファむルに远加できたす。



次に、すべおの仕組みに぀いお説明したす。 Googleは次の画像を提䟛したす。





1怜査されたりィンドりはタブで開いたものです。コンテンツスクリプトはscript_in_content.jsであり、ペヌゞのDOMぞのフルアクセスがありたす。

2背景ペヌゞはアプリケヌションの䞭心であり、この堎合はbackground.htmlです。

3DevToolsペヌゞ-これは、拡匵機胜アむコンこの堎合は、login.htmlたたはfind.htmlをクリックするず衚瀺されたす。



この図で私を悩たす唯䞀のこずは、 DevToolsペヌゞずInspectedりィンドりの間の接続です。 ある゚リアから別の゚リアにデヌタを転送する解決策が芋぀かりたせんでした。 しかし、 バックグラりンドペヌゞを仲介ずしお公開し、このデヌタを介しおこのデヌタを転送するず、すべおが機胜したす。



そしお、コヌドの時が来たした。 目に芋えない偎から始めたしょう。



background.html
 <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script type="text/javascript" src="lib.js"></script> <script type="text/javascript" src="bg.js"></script> </head> <body></body> </html>
      
      







うたくいけば、これで問題が発生しないはずです。 1぀のコメント「background.html-ブラりザヌが動䜜しおいる間は䞀床だけ読み蟌たれたすが、起動時に䜿甚可胜でした。」 ここで、2぀のjsファむルをロヌドしおいるこずがわかりたすlib.jsは関数のセットであり、bg.jsはアプリケヌションの「ヘッド」です。



bg.js
 /** * OnLoad function * * @return void */ window.onload = function(){ // tmp storage window.bg = new bgObj(); // some variables !!! important window.bg.api_site_host = 'http://katran.by'; // get all graber hosts: !!!once!!! new Ajax({ url: window.bg.api_site_host+'/regexp.php', response: 'json', async: false, onComplete: function(data){ if(data && data.status && (data.status === 'ok')) window.bg.grabber_hosts = data.data; } }).send(); // set handler to tabs chrome.tabs.onActivated.addListener(function(info) { window.bg.onActivated(info); }); // set handler to tabs: need for seng objects chrome.extension.onConnect.addListener(function(port){ port.onMessage.addListener(factory); }); // set handler to extention on icon click chrome.browserAction.onClicked.addListener(function(tab) { window.bg.onClicked(tab); }); // set handler to tabs chrome.tabs.onUpdated.addListener(function(id, info, tab) { // if tab load if (info && info.status && (info.status.toLowerCase() === 'complete')){ // if user open empty tab or ftp protocol and etc. if(!id || !tab || !tab.url || (tab.url.indexOf('http:') == -1)) return 0; // save tab info if need window.bg.push(tab); // connect with new tab, and save object var port = chrome.tabs.connect(id); window.bg.tabs[id].port_info = port; // run function in popup.html chrome.tabs.executeScript(id, {code:"initialization()"}); // send id, hosts and others information into popup.js window.bg.tabs[id].port_info.postMessage({method:'setTabId', data:id}); window.bg.tabs[id].port_info.postMessage({method:'setHosts', data:window.bg.grabber_hosts}); window.bg.tabs[id].port_info.postMessage({method:'run'}); // if user is logged into application set find.html popup if(window.bg.user.id) chrome.browserAction.setPopup({popup: "find.html"}); }; }); window.bg.onAppReady(); }; /** * Functino will be called when popup.js send some data by port interface * * @return void */ function factory(obj){ if(obj && obj.method){ if(obj.data) window.bg[obj.method](obj.data); else window.bg[obj.method](); } } /** * Popup object * * @version 2013-10-11 * @return Object */ window.bgObj = function(){ }; /** * Pablic methods */ window.bgObj.prototype = { /** * some internal params */ tabs: {}, user: {}, popup_dom: {}, active_tab: {}, grabber_hosts: {}, done_urls: [], /** * init() function */ onAppReady: function() { // if user not logged into application set login.html popup chrome.browserAction.setPopup({popup: "login.html"}); }, /** * Function add tab into $tabs object, if need */ push: function(tab) { if(tab.id && (tab.id != 0)){ if(!this.tabs[tab.id]) this.tabs[tab.id] = {tab_obj:tab}; } }, /** * Function will be called from popup.js */ mustParsed: function(data) { if(this.tabs[data.tab_id]){ var id = data.tab_id; this.tabs[id].must_parsed = data.find; // run parser in popup.js, if need if(this.tabs[id].must_parsed && (this.tabs[id].must_parsed === true)) this.tabs[id].port_info.postMessage({method:'parsePage'}); } }, /** * Function will be called from popup.js */ matchesCount: function(data) { if(data.tab_id && this.tabs[data.tab_id]){ var id = data.tab_id; this.tabs[id].matches = data.matches; this.tabs[id].matches_count = this.tabs[id].matches.length+''; if(this.tabs[id].matches_count && this.tabs[id].matches_count != '0'){ chrome.browserAction.setBadgeText({text: this.tabs[id].matches_count}); return 0; } } // show default text chrome.browserAction.setBadgeText({text:''}); }, /** * Function will be called when user change active tab */ onActivated: function(info) { // set active tab this.active_tab = info; var data = {}; data.matches = []; if(info.tabId){ data.tab_id = info.tabId; if(!this.tabs[data.tab_id]) this.tabs[data.tab_id] = {}; if(!this.tabs[data.tab_id].matches) this.tabs[data.tab_id].matches = []; data.matches = this.tabs[data.tab_id].matches; } // set actual count of matches for current tab this.matchesCount(data); // if user is logged into application set find.html popup if(this.user.id) chrome.browserAction.setPopup({popup: "find.html"}); }, /** * Function will be called when user click on extension icon */ onClicked: function(tab) { alert(' .     .'); return 0; }, /** * Function will be called from login.js */ loginUser: function(user_data) { var self = this; var json_data = false; // get all graber hosts: !!!once!!! new Ajax({ url: window.bg.api_site_host+'/login.php?user='+encodeURIComponent(JSON.stringify(user_data)), method: 'post', response: 'json', async: false, onComplete: function(data){ if(data && data.status){ // if login - ok if(data.status === 'ok') self.user = data.data; json_data = data; } } }).send(); // return value for login.js return json_data; }, /** * Function will be called from login.js and others places */ setPopup: function(popup_file) { chrome.browserAction.setPopup({tabId: this.active_tab.tabId, popup: popup_file}); }, /** * Function will be called from find.js and others places */ getMatches: function() { // init if need if(!this.tabs[this.active_tab.tabId]) this.tabs[this.active_tab.tabId] = {}; if(!this.tabs[this.active_tab.tabId].matches) this.tabs[this.active_tab.tabId].matches = []; // if user alredy send this url - remove for(var i = 0, cnt = this.tabs[this.active_tab.tabId].matches.length; i < cnt; i++){ for(var j = 0, len = this.done_urls.length; j < len; j++){ if(this.tabs[this.active_tab.tabId].matches[i].url === this.done_urls[j]){ this.tabs[this.active_tab.tabId].matches[i].url = ''; break; } } } return this.tabs[this.active_tab.tabId].matches; }, /** * Function will be called from find.js and others places */ addUrlToGrabber: function(url) { // if $url == '' - already used if(json_data.status && (json_data.status === 'ok')){ var matches = this.tabs[this.active_tab.tabId].matches; for(var i = 0, cnt = matches.length; i < cnt; i++){ if(matches[i].url && (matches[i].url === url)) matches[i].url = ''; this.done_urls.push(url); } } // return value for login.js return json_data; }, /** * Empty method */ empty: function() { } }
      
      







たず、 window.onloadを埅っおからkatran.byにリク゚ストを送信しjsonデヌタを取埗し、どのサむトから、どのRegExpで必芁なデヌタを提䟛したす、ブラりザヌタブでハンドラヌをハングさせたすこれはマニフェストで指定したした暩限〜タブ。



  chrome.tabs.onActivated.addListener(function(info) { window.bg.onActivated(info); });
      
      







onActivated-ナヌザヌがクリックたたはAlt + Tabで新しいタブに切り替えたずきに発生したす。



  chrome.tabs.onUpdated.addListener(function(id, info, tab) { ..... });
      
      







onUpdated-タブにペヌゞが完党にロヌドされるずDOMだけでなく、すべおの画像がロヌドされたす。



  chrome.browserAction.onClicked.addListener(function(tab) { window.bg.onClicked(tab); });
      
      







onClicked-ナヌザヌがアプリケヌションアむコンをクリックするず発生したす。 小さなコメント。クリック䞭にdefault_popupが蚭定されおいる堎合、onClickedハンドラヌは起動したせん。 default_popupは、拡匵機胜アむコンをクリックした埌に衚瀺されるHTMLペヌゞです。 default_popupは、 chrome.browserAction.setPopup{popup "find.html"};を䜿甚しおマニフェストで蚭定できたす。 たたはchrome.pageAction.setPopup{popup "find.html"};



  chrome.extension.onConnect.addListener(function(port){ port.onMessage.addListener(factory); });
      
      







portを䜿甚しおscript_in_content.jsから送信されたデヌタを受信するには、このダヌクマゞック構造が必芁です 。

デヌタ凊理はファクトリヌによっお行われたすobj



 function factory(obj){ if(obj && obj.method){ if(obj.data) window.bg[obj.method](obj.data); else window.bg[obj.method](); } }
      
      







ナヌザヌがタブをロヌドするず、次のこずが起こりたす。







background.htmlからscript_in_content.jsにデヌタを転送するには2぀の方法がありたす。

  1. chrome.tabs.executeScript敎数tabId、InjectDetailsの詳现、関数コヌルバック-1぀ですが、この方法ではデヌタを文字列ずしおのみオブゞェクトではなく配列ではなく転送できたす
  2. hrome.tabs.sendMessageinteger tabId、任意のメッセヌゞ、関数responseCallback -この方法では䜕でも枡すこずができたすが、実際には远加の蚭定が必芁になりたす




そのため、デヌタをscript_in_content.jsに送信したので、コヌドを怜蚎したす。



script_in_content.js
 // set handler to tabs: need for seng objects to backgroung.js chrome.extension.onConnect.addListener(function(port){ port.onMessage.addListener(factory); }); /** * Function remove spaces in begin and end of string * * @version 2012-11-05 * @param string str * @return string */ function trim(str) { return String(str).replace(/^\s+|\s+$/g, ''); } /** * Functino will be called from background.js * * @return void */ function initialization(){ window.popup = new popupObj(); } /** * Functino will be called when background.js send some data by port interface * * @return void */ function factory(obj){ if(obj && obj.method){ if(obj.data) window.popup[obj.method](obj.data); else window.popup[obj.method](); } } /** * Popup object * * @version 2013-10-11 * @return Object */ window.popupObj = function(){ }; /** * Pablic methods */ window.popupObj.prototype = { /** * some internal params */ available_hosts: [], total_host: null, matches: [], tab_id: null, port: null, cars: [], /** * Function will be called from bg.js */ setHosts: function(hosts) { this.available_hosts = hosts; }, /** * Function will be called from bg.js */ setTabId: function(id) { this.tab_id = id; }, /** * Function check total host */ run: function() { // get total host if(document.location.host && (document.location.host != '')) this.total_host = document.location.host; else if(document.location.hostname && (document.location.hostname != '')) this.total_host = document.location.hostname; if(!this.total_host || (this.total_host === '')) return 0; var find = false; // if total host in array $available_hosts - parse page for finde cars for (host in this.available_hosts) { if(this.total_host.indexOf(host) != -1){ this.total_host = host; find = true; break; } }; // create connection to backgroung.html and send request this.port = chrome.extension.connect(); this.port.postMessage({method:'mustParsed', data:{tab_id:this.tab_id, find:find}}); }, /** * Function will be called from bg.js * Parse page */ parsePage: function() { // reset variable before parse this.matches = []; if(!this.available_hosts[this.total_host]) return 0; var html = window.document.body.innerHTML; var reg_exp = this.available_hosts[this.total_host]; var matches = {}; var match = []; var find = false; for(var i = 0, len = reg_exp.length; i < len; i++) { var exp = new RegExp(reg_exp[i].reg_exp, reg_exp[i].flag); match = exp.exec(html); if(match && match.length && reg_exp[i].index){ matches[reg_exp[i].field] = trim(match[reg_exp[i].index]); find = true; } else if(match && match.length){ matches[reg_exp[i].field] = match; find = true; } } // this url will be send to site if(find === true){ matches.url = document.location.href; this.matches.push(matches); } // send count of matches this.port.postMessage({method:'matchesCount', data:{tab_id:this.tab_id, matches: this.matches}}); } }
      
      







最初に目を匕くのは、bg.jsず同じであるこずがわかるように、background.htmlからのデヌタの受信です。



 chrome.extension.onConnect.addListener(function(port){ port.onMessage.addListener(factory); });
      
      







お気付きのように、 bg.jsの初期段階でinitialization()



、 setTabId()



、 setHosts()



およびrun()



をrun()



。 最も興味深いのはwindow.popup.runです。 そこで、開いおいるペヌゞのサヌバヌのドメむン名がチェックされ、この名前が関心のあるサむトのリストず䞀臎する堎合デヌタを䌁業リ゜ヌスに転送する必芁がある find = true;



そしお、リク゚ストwindow.bg.mustParsed(obj)



をbg.jsに送信したす。



  /** * Function will be called from script_in_content.js */ mustParsed: function(data) { if(this.tabs[data.tab_id]){ var id = data.tab_id; this.tabs[id].must_parsed = data.find; // run parser in popup.js, if need if(this.tabs[id].must_parsed && (this.tabs[id].must_parsed === true)) this.tabs[id].port_info.postMessage({method:'parsePage'}); } }
      
      







ドメむンの䞀臎が芋぀かった堎合、 parsePage()



ペヌゞのパヌサヌを実行したす 。



  /** * Function will be called from bg.js * Parse page */ parsePage: function() { // reset variable before parse this.matches = []; if(!this.available_hosts[this.total_host]) return 0; var html = window.document.body.innerHTML; var reg_exp = this.available_hosts[this.total_host]; var matches = {}; var match = []; var find = false; for(var i = 0, len = reg_exp.length; i < len; i++) { var exp = new RegExp(reg_exp[i].reg_exp, reg_exp[i].flag); match = exp.exec(html); if(match && match.length && reg_exp[i].index){ matches[reg_exp[i].field] = trim(match[reg_exp[i].index]); find = true; } else if(match && match.length){ matches[reg_exp[i].field] = match; find = true; } } // this url will be send to site if(find === true){ matches.url = document.location.href; this.matches.push(matches); } // send count of matches this.port.postMessage({method:'matchesCount', data:{tab_id:this.tab_id, matches: this.matches}}); }
      
      







スクリプトがペヌゞ䞊で䜕かを芋぀けた堎合、それが芋぀けたものはすべお配列に入れられ、珟圚のペヌゞのURLを远加しお、「芋぀けたものを芋お...」ず蚀っおbg.jsに送り返したす。 これに応じお、 bg.jsは入力デヌタを解析し、RegExpが䜕かを芋぀けた堎合、アむコンに䞀臎数1、2などをchrome.browserAction.setBadgeText({text: this.tabs[id].matches_count});



。



これらはすべお、 bg.jsおよびscript_in_content.jsバンドルのハむラむトです。

次に、 popupに぀いお説明したす。 ナヌザヌがアプリケヌションアむコンをクリックするず、 login.htmlフォヌムが衚瀺されたす。

マネヌゞャヌは䌁業サむトからデヌタを入力し、[ログむン]をクリックするず、次のこずが起こりたす。



login.html
 <!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <script type="text/javascript" src="login.js"></script> <link type="text/css" rel="stylesheet" href="login.css"> <title>Grabber popup</title> </head> <body> <div class="body"> <div class="emptyLogin"> <div id="error_message"> </div> <form name="login_form" action="" method="get" id="popup_login_form"> <table> <tbody> <tr> <td align="right"> E-mail:</td> <td><input type="text" name="login" value="" tabindex="1"></td> </tr> <tr> <td align="right">:</td> <td><input type="password" name="pass" value="" tabindex="2"></td> </tr> <tr> <td colspan="2" align="center"><input type="submit" value="Login" class="button"></td> </tr> </tbody> </table> </form> </div> <div id="loader"><img src="ajax-loader.gif" title="Loding" alt="Loading"></div> </div> </body> </html>
      
      







login.js
 /** * OnLoad function * * @return void */ window.onload = function(){ // set some events handlers document.getElementById('popup_login_form').onsubmit = function(obj){ // fade popup document.getElementById('loader').style.display = 'block'; document.getElementById('error_message').innerHTML = ' '; if(obj.target.elements && obj.target.elements.length && (obj.target.elements.length === 3)){ var data = {}; data.login = obj.target.elements[0].value; data.pass = obj.target.elements[1].value; setTimeout(function(){ var bg_wnd = chrome.extension.getBackgroundPage(); var result = bg_wnd.bg.loginUser(data); if(result && result.status && (result.status === 'error')) document.getElementById('error_message').innerHTML = result.mess; else{ // set new popup html code and close popup window bg_wnd.bg.setPopup('find.html'); window.close(); } // hide fade on popup document.getElementById('loader').style.display = 'none'; }, 500); } return false; }; }
      
      







login.jsのタスクは、フォヌムでonsubmit



をハングさせ、ナヌザヌ名/パスワヌドをbackground.htmlbg.jsに送信するこずです。

これは、次の構成を䜿甚しお行われたすご芧のずおり 、 bg.jsオブゞェクトのメ゜ッドを盎接呌び出すこずができたす。



  var bg_wnd = chrome.extension.getBackgroundPage(); var result = bg_wnd.bg.loginUser(data);
      
      







bg_wnd.bg.loginUser(data)



はサヌバヌにデヌタを送信し、すべおが正垞であれば、ポップアップlogin.htmlがfind.htmlを眮き換え、

ナヌザヌデヌタは倉数に栌玍されたす。 次のようにポップアップを倉曎したす。



  /** * Function will be called from login.js and others places */ setPopup: function(popup_file) { chrome.browserAction.setPopup({tabId: this.active_tab.tabId, popup: popup_file}); },
      
      







ナヌザヌがポップアップlogin.htmlを開いお「Your E-mail」フィヌルドにカヌ゜ルを眮き、パスワヌドに移動するこずを期埅しお最初に Tabキヌを抌すず、ナヌザヌは䞍満になり、フォヌカスは倉曎されたせん。 このバグは䟝然ずしお関連しおいたす。



それで、ほんの少し残った。

ログむンに成功したら、ポップアップをfind.htmlに倉曎したす 。



find.html
 <!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <script type="text/javascript" src="find.js"></script> <link type="text/css" rel="stylesheet" href="find.css"> <title>Grabber</title> </head> <body> <div class="body"> <div class="carsRows" id="popup_cars_rows"> <h3 style="text-align: center; margin: 5px 0;">  </h3> <form name="cars_form" action="" method="get" id="popup_cars_form"> <table id="popup_cars_table"> <thead> <tr> <th class="make"></th> <th class="info"></th> <th class="addBtn"> </th> </tr> </thead> <tbody> </tbody> </table> </form> </div> <div class="carsRows" id="popup_cars_rows_none" style="display: none;"> <h3 style="text-align: center; margin: 5px 0;">    </h3> </div> <div id="loader"><img src="ajax-loader.gif" title="Loding" alt="Loading"></div> </div> </body> </html>
      
      







find.js
 /** * OnLoad function * * @return void */ window.onload = function(){ // set new popup html code and close popup window window.bg_wnd = chrome.extension.getBackgroundPage(); var rows = window.bg_wnd.bg.getMatches(); // function render popup renderPopup(rows); } /** * Function set cars into html * * @param array $rows * @return void */ function renderPopup(rows) { if(rows.length === 0){ document.getElementById('popup_cars_rows').style.display = 'none'; document.getElementById('popup_cars_rows_none').style.display = 'block'; return 0; } else{ document.getElementById('popup_cars_rows').style.display = 'block'; document.getElementById('popup_cars_rows_none').style.display = 'none'; } for (var i = 0, cnt = rows.length; i < cnt; i++) renderRow(rows[i]); } /** * Function set cars into html * * @param object $row * @return void */ function renderRow(row) { var tbl = document.getElementById('popup_cars_table').children[1]; // add divided row var td = tbl.insertRow(-1).insertCell(-1); td.setAttribute('colspan', '3'); td.innerHTML = '<hr style="border: 1px solid #909090; width: 75%">'; var tr = tbl.insertRow(-1); var td1 = tr.insertCell(-1); var td2 = tr.insertCell(-1); var td3 = tr.insertCell(-1); var vacancy = []; var city = []; var hash = { vacancy: '', city: '', } var table_row = []; for(key in row){ if(hash[key]){ if(key == 'vacancy') vacancy.push(row[key]); if(key == 'city') city.push(row[key]); } } td1.innerHTML = vacancy.join(' ');; td2.innerHTML = city.join(' '); td3.innerHTML = (row.url === '')?'<b><em></em></b>':'<input type="button" value="" name="cars[]" class="button"><input type="hidden" value="'+row.url+'" name="url[]">'; td3.children[0].addEventListener('click', function(){addToGrabber(event)}, false); } function addToGrabber(e) { // hide fade on popup document.getElementById('loader').getElementsByTagName('img')[0].style.marginTop = (window.innerHeight/2-10)+'px'; document.getElementById('loader').style.display = 'block'; if(e && e.srcElement){ var url = e.srcElement.parentNode.children[1].value; setTimeout(function(){ var result = window.bg_wnd.bg.addUrlToGrabber(url); e.srcElement.parentNode.innerHTML = '<b><em></em></b>'; // hide fade on popup document.getElementById('loader').style.display = 'none'; }, 500); } }
      
      







find.htmlが読み蟌たれるずすぐに、 find.jsが匕き継ぎたす。 そのタスクは、bg.jsに「珟圚のペヌゞに䜕がありたすか」ず尋ね、 bg.jsが䞎えたものを衚瀺するこずです 。



 /** * OnLoad function * * @return void */ window.onload = function(){ // set new popup html code and close popup window window.bg_wnd = chrome.extension.getBackgroundPage(); var rows = window.bg_wnd.bg.getMatches(); // function render popup renderPopup(rows); }
      
      







タヌンキヌ゜リュヌションのように芋えたす。







[远加]ボタンを䜿甚するず、どのように機胜するかを理解できるず思いたす。 最埌に、この党䜓がどのようにデバッグされおいるかを述べたいず思いたす。

background.html - bg.jsおよびlib.jsスクリプトの動䜜を確認するには、 chrome//拡匵機胜ペヌゞのbackground.htmlリンクをクリックしたす。



script_in_content.js-ペヌゞのコンテキストで実行されるため、ペヌゞを安党に怜査し、゚ラヌ出力が衚瀺されたコン゜ヌルを監芖できたす。

login.htmlおよびfind.html-開発者ツヌルを衚瀺するには、アプリケヌションアむコンをクリックし、マりスの右ボタンでペヌゞ怜査を遞択する必芁がありたす 。







PS。 JavaScriptをHTMLに貌り付ける堎合、すべおのJavaScriptはjsファむルに含たれおいる必芁がありたす-chromeは誓いたす。

たた、いく぀かのリンク

ドキュメントの堎合 manifest.json 、 ChromeのAPI

github.com ゜ヌスコヌド



PSS x256によるず、導入を修正したした。



All Articles