Chrome extension 是非常強大的工具,可以做到非常多的事情。
但也因此它提供的執行環境(我稱之為 context) 有非常多種,各有各的用處。為了能夠有效率且順利的在這些 context 內開發,必須了解各個 context 底下應該如何使用 Chrome DevTools 來進行 debug。
本文介紹 如何在各個 context 下讓 Chrome DevTools 為你所用。
Chrome extension 是非常強大的工具,可以做到非常多的事情。
但也因此它提供的執行環境(我稱之為 context) 有非常多種,各有各的用處。為了能夠有效率且順利的在這些 context 內開發,必須了解各個 context 底下應該如何使用 Chrome DevTools 來進行 debug。
本文介紹 如何在各個 context 下讓 Chrome DevTools 為你所用。
續上一篇文章
最後提到為了能夠在提供安裝的頁面展現出我們的誠意(明明上一篇好像不是這樣說的),總得有個辦法來各別針對 未安裝/已安裝 的使用者做頁面的客製化。
其實就是官方文件提供的方法。
Extensions can communicate with the embedding page via content scripts to let it know that they are already installed.
可以歸納出大致兩種基本作法:
window.postMessage
與 content script 對話,基本上只要約定一下傳輸的內容就可以知道 extension 安裝成功<div id="my-awesome-extension"></div>
,檢查的動作只要檢查該 div
是否存在即可這邊選擇第二種做法,節奏明快!
過去我的印象一直是,無論如何一定要跑到 Chrome Web Store 去安裝 Chrome extension,一般來說可能點擊連結之後會導向類似下面這樣的網址:
https://chrome.google.com/webstore/detail/apdfllckaahabafndbhieahigkjlhalf
然後到 Chrome Web Store 之後再透過跳出來的對話框進行安裝。
直到日前我發現 Pocket 的網站上可以直接在頁面內安裝!
而最近進行的 extension 也差不多到了要上架的階段,就研究了一下揪竟怎麼樣可以在 Chrome Web Store 以外的地方直接安裝 extension。(在 Google 官方文件稱做 inline installation
)
步驟如下:
Apparently this is a known issue with Angular and is currently open
app.directive('autoFillSync', function($timeout) {
return {
require: 'ngModel',
link: function(scope, elem, attrs, ngModel) {
var origVal = elem.val();
$timeout(function () {
var newVal = elem.val();
if(ngModel.$pristine && origVal !== newVal) {
ngModel.$setViewValue(newVal);
}
}, 500);
}
}
});
<form name="myForm" ng-submit="login()">
<label for="username">Username</label>
<input type="text" id="username" name="username" ng-model="username" auto-fill-sync/><br/>
<label for="password">Password</label>
<input type="password" id="password" name="password" ng-model="password" auto-fill-sync/><br/>
<button type="submit">Login</button>
</form>
印象中以前查的時候好像還沒有丟出這個 auto-fill-sync
的 directive,所以這次真的碰到要解決這個問題,我很快的想到應該實驗一下 browser 的 autofill 是不是真的會在 <input>
裡 fill 進東西。
如果只是 AngularJS 那邊沒有抓到 autofill 的動作,應該就還算好解決,只要想辦法通知 AngularJS 就好了。
怕是怕 browser 是直到你確定要送出前夕才塞入 autofill 的值,這樣誰也幫不了我了~~~
$('#username').val();
// output: "我的帳號"
好加在實驗結果是後者 (呼)
於是我寫了一個自己的版本(因為沒有先看 stackoverflow 那篇…)
/* file: autocomplete-fix.js */
app.directive('autocompleteFix', ['$timeout', '$log', function ($timeout, $log) {
return {
require: 'ngModel',
restrict: 'A',
link: function postLink(scope, iElm, iAttrs, ctrl) {
/**
* Delay for 450ms works for Chrome on OS X
*/
var _delay = 450;
if (iAttrs.autocompleteFix) {
_delay = parseInt(iAttrs.autocompleteFix, 10);
}
$log.debug('delay', _delay);
$timeout(function () {
ctrl.$setViewValue(iElm.val());
}, _delay);
}
};
}]);
有趣的地方是,_delay
在 300, 400 時,都會有機會沒通知到 AngularJS,所以我自己試的恰當值大約是 450(而 stackoverflow 上的是 500)。
感覺 stackoverflow 上的版本似乎考慮比較周到,所以就留個 gist 存著吧!
<input ng-model="query">
<div ng-repeat="item in (filteredItems = (items | orderBy:'order_prop' | filter:query | limitTo:4))">
{{item}}
</div>
Then
$scope.filteredItems
is accessible.
雖然說第一次看到真心覺得好可怕,但在某些時候真的好用啊…