HTML Element の幅と高さ、座標。
幅と高さ
Determining the dimensions of elements | MDN
- HTMLElement.offsetWidth
- content + padding + boarder + scrollbar
- Element.clientWidth
- content + padding
- Element.scrollWidth
- element のコンテンツの幅か、element 自身の幅(clientWidth)のうち大きい方を返す
補足
https://www.w3.org/TR/CSS22/box.html#box-dimensions
座標
-
offsetParent
からの距離
Element.getBoundingClientRect()
- viewport (window) からの座標を返す
-
- element のコンテンツがどのくらいスクロールされたか
補足
offsetParent
The offsetParent property returns the nearest ancestor that has a position other than static. http://www.w3schools.com/jsref/prop_element_offsetparent.asp
ドキュメントからの座標
// https://github.com/oneuijs/You-Dont-Need-jQuery function getOffset (el) { const box = el.getBoundingClientRect(); return { top: box.top + window.pageYOffset - document.documentElement.clientTop, left: box.left + window.pageXOffset - document.documentElement.clientLeft }; }
参考
Promiseの配列を順に処理
reduce
を使い新しいpromiseを作成していく。
const tasks = [ () => $q(resolve => doneAsync(resolve)), () => $q(resolve => doneAsync(resolve)) ]; function doneAsync(resolve) { setTimeout(() => resolve(), 1000); } tasks.reduce((promise, task) => { return promise.then(task); }, $q.resolve()) // $q.resolve()で最初のPromiseを生成 .then(() => { console.log('done'); });
実行結果を保存するrecord
処理を追加。
const tasks = [ (value) => $q(resolve => doneAsync(resolve, value)), (value) => $q(resolve => doneAsync(resolve, value)) ]; const record = (results, value) => { results.push(value); return results; }; // [] に実行結果を保存する const _record = record.bind(null, []); tasks.reduce((promise, task) => { return promise.then(task).then(_record) }, $q.resolve(0)) .then(value => { console.log(value); // -> [1, 2] }); function doneAsync(resolve, value) { setTimeout(() => resolve(++value), 1000); }
背景(領域外)をクリックしたら閉じる、とか
ドロップダウンなどを表示したときに、領域外をクリックしたら閉じたい。 HTMLだと、どのように実装するのが一般的なのかわからなかったのでAngularのUI Bootstrapを参考にしてみたよ。
Dropdown
documentにイベントハンドラを登録。
// https://github.com/angular-ui/bootstrap/blob/v1.1.0/src/dropdown/dropdown.js#L13 $document.on('click', closeDropdown); // ... var closeDropdown = function(evt) { // ... // dropdown内をクリックかつ'outsideClick'が設定されている場合は閉じない var dropdownElement = openScope.getDropdownElement(); if (evt && openScope.getAutoClose() === 'outsideClick' && dropdownElement && dropdownElement[0].contains(evt.target)) { return; } // ... openScope.isOpen = false; // ... };
補足: dropdownは複数開くことができないようになっている。uibDropdownServiceが管理している。
Modal
自身(全領域カバーしている)にイベントハンドラを登録。
// https://github.com/angular-ui/bootstrap/blob/v1.1.0/src/modal/modal.js#L165 element.on('click', scope.close);
documentに登録する方法だとこんな感じでしょうか。
class Controller { closeHandler: () => void; /*@ngInject*/ constructor( private $document: ng.IDocumentService, private $element: ng.IAugmentedJQuery, private $scope: ng.IScope ) { } $onInit() { this.closeHandler = () => { this.close(); this.$scope.$apply(); }; this.$element.on('click', ($event) => { // this.$document.on を無効にするため $event.stopPropagation(); }); } $onDestroy() { this.close(); } open() { // 何かの処理 // ... this.$document.on('click', this.closeHandler); } close() { // 何かの処理 // ... this.$document.off('click', this.closeHandler); } } const components: ng.IComponentOptions = { templateUrl: 'foo.html', controller: Controller, bindings: {} }; export default components;
Angularを1.5から1.6に移行
1.5.6から1.6.1に移行。参考にしたのは
- Angular 1.6 is here, this is what you need to know
- https://docs.angularjs.org/guide/migration#migrating-from-1-5-to-1-6
など。
対応箇所
$onInit
初期化のロジックが変更。(bindings
された変数がconstructor
内では利用できなくなった。)
全てのDirectiveとComponentに$onInit
を用意し、初期化時の処理を$onInit
内に記述。
(この変更は、書き方が統一されるので嬉しい。)
The reasoning behind this change is that it is not idiomatic JavaScript to bind properties to an Object before its constructor has been called ...
$http
$httpのsuccess()
とerror()
がなくなった。then()
とcatch()
に置き換え。
hash-prefix
hash-prefixが!
に変更。
$q
PromiseのRejectionが未処理の場合、警告が出るようになった。
Possibly unhandled rejection:
$uibModalの利用している場合、backdropクリックでモーダルを閉じると警告がでるので、一応以下のように対応。
this.$uibModal .open({ templateUrl: 'demo.html', }) .result.catch(angular.noop);
メモ
errorOnUnhandledRejections
を利用する。
(この方法だとエラーが捕捉できない)
javascript - Possibly unhandled rejection in Angular 1.6 - Stack Overflow
app.config($qProvider => { $qProvider.errorOnUnhandledRejections(false); })
CircleCIのChromeを最新版に
Chromeのバージョンが低いため、E2Eが失敗してしまう。
Linux Package Signing Keysをインストールしてsudo apt-get --only-upgrade install google-chrome-stable
で解決。
- Update Chrome in container image - Feature Requests - CircleCI Community Discussion
- Linux Software Repositories – Google
dependencies: pre - wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - - sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' - sudo apt-get update - sudo apt-get --only-upgrade install google-chrome-stable
ユニットテスト(Karma)もTypeScriptで
別記事 -> ユニットテスト(Karma)もTypeScriptで: karma-webpack編 - ryotah’s blog
preprocessorsに追加すればいいだけだった。
GitHub - sergeyt/karma-typescript-preprocessor: TypeScript preprocessor for karma-runner
// karma.conf.js module.exports = function(config) { config.set({ preprocessors: { '**/*.ts': ['typescript'] }, typescriptPreprocessor: { options: { sourceMap: false, target: 'es5', module: 'commonjs', }, transformPath: function(path) { return path.replace(/\.ts$/, '.js'); } }, plugins: [ 'karma-typescript-preprocessor' ] }); };
Karmaのバージョンは0.13.22。ちょっと古い。