1 | // Copyright (c) Jupyter Development Team.
|
2 | // Distributed under the terms of the Modified BSD License.
|
3 | /*
|
4 | This file contains substantial portions of https://github.com/akre54/Backbone.NativeView/blob/521188d9554b53d95d70ed34f878d8ac9fc10df2/backbone.nativeview.js, which has the following license:
|
5 |
|
6 | (c) 2015 Adam Krebs, Jimmy Yuen Ho Wong
|
7 | Backbone.NativeView may be freely distributed under the MIT license.
|
8 |
|
9 | Copyright (c) 2014 Adam Krebs
|
10 |
|
11 | Permission is hereby granted, free of charge, to any person
|
12 | obtaining a copy of this software and associated documentation
|
13 | files (the "Software"), to deal in the Software without
|
14 | restriction, including without limitation the rights to use,
|
15 | copy, modify, merge, publish, distribute, sublicense, and/or sell
|
16 | copies of the Software, and to permit persons to whom the
|
17 | Software is furnished to do so, subject to the following
|
18 | conditions:
|
19 |
|
20 | The above copyright notice and this permission notice shall be
|
21 | included in all copies or substantial portions of the Software.
|
22 |
|
23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
25 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
27 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
28 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
29 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
30 | OTHER DEALINGS IN THE SOFTWARE.
|
31 |
|
32 | */
|
33 | import * as Backbone from 'backbone';
|
34 | // Caches a local reference to `Element.prototype` for faster access.
|
35 | const ElementProto = typeof Element !== 'undefined' ? Element.prototype : undefined;
|
36 | // Find the right `Element#matches` for IE>=9 and modern browsers.
|
37 | function matchesFallback(selector) {
|
38 | const matches = (this.document || this.ownerDocument).querySelectorAll(selector);
|
39 | let i = matches.length;
|
40 | while (--i >= 0 && matches.item(i) !== this) {
|
41 | continue;
|
42 | }
|
43 | return i > -1;
|
44 | }
|
45 | const matchesSelector = ElementProto
|
46 | ? ElementProto.matches ||
|
47 | ElementProto['webkitMatchesSelector'] ||
|
48 | ElementProto['mozMatchesSelector'] ||
|
49 | ElementProto['msMatchesSelector'] ||
|
50 | ElementProto['oMatchesSelector'] ||
|
51 | matchesFallback
|
52 | : matchesFallback;
|
53 | export class NativeView extends Backbone.View {
|
54 | _removeElement() {
|
55 | this.undelegateEvents();
|
56 | if (this.el.parentNode) {
|
57 | this.el.parentNode.removeChild(this.el);
|
58 | }
|
59 | }
|
60 | // Apply the `element` to the view.
|
61 | _setElement(element) {
|
62 | this.el = element;
|
63 | }
|
64 | // Set a hash of attributes to the view's `el`. We use the "prop" version
|
65 | // if available, falling back to `setAttribute` for the catch-all.
|
66 | _setAttributes(attrs) {
|
67 | for (const attr in attrs) {
|
68 | attr in this.el
|
69 | ? (this.el[attr] = attrs[attr])
|
70 | : this.el.setAttribute(attr, attrs[attr]);
|
71 | }
|
72 | }
|
73 | delegate(eventName, selector, listener) {
|
74 | if (typeof selector !== 'string') {
|
75 | listener = selector;
|
76 | selector = null;
|
77 | }
|
78 | // We have to initialize this here, instead of in the constructor, because the
|
79 | // super constructor eventually calls this method before we get a chance to initialize
|
80 | // this._domEvents to an empty list.
|
81 | if (this._domEvents === void 0) {
|
82 | this._domEvents = [];
|
83 | }
|
84 | const root = this.el;
|
85 | const handler = selector
|
86 | ? function (e) {
|
87 | let node = e.target || e.srcElement;
|
88 | for (; node && node !== root; node = node.parentNode) {
|
89 | if (matchesSelector.call(node, selector)) {
|
90 | e.delegateTarget = node;
|
91 | if (listener.handleEvent) {
|
92 | return listener.handleEvent(e);
|
93 | }
|
94 | else {
|
95 | return listener(e);
|
96 | }
|
97 | }
|
98 | }
|
99 | }
|
100 | : listener;
|
101 | this.el.addEventListener(eventName, handler, false);
|
102 | this._domEvents.push({ eventName, handler, listener, selector });
|
103 | return handler;
|
104 | }
|
105 | undelegate(eventName, selector, listener) {
|
106 | if (typeof selector === 'function') {
|
107 | listener = selector;
|
108 | selector = null;
|
109 | }
|
110 | if (this.el && this._domEvents) {
|
111 | const handlers = this._domEvents.slice();
|
112 | let i = handlers.length;
|
113 | while (i--) {
|
114 | const item = handlers[i];
|
115 | const match = item.eventName === eventName &&
|
116 | (listener ? item.listener === listener : true) &&
|
117 | (selector ? item.selector === selector : true);
|
118 | if (!match) {
|
119 | continue;
|
120 | }
|
121 | this.el.removeEventListener(item.eventName, item.handler, false);
|
122 | this._domEvents.splice(i, 1);
|
123 | }
|
124 | }
|
125 | return this;
|
126 | }
|
127 | // Remove all events created with `delegate` from `el`
|
128 | undelegateEvents() {
|
129 | if (this.el && this._domEvents) {
|
130 | const len = this._domEvents.length;
|
131 | for (let i = 0; i < len; i++) {
|
132 | const item = this._domEvents[i];
|
133 | this.el.removeEventListener(item.eventName, item.handler, false);
|
134 | }
|
135 | this._domEvents.length = 0;
|
136 | }
|
137 | return this;
|
138 | }
|
139 | }
|
140 | //# sourceMappingURL=nativeview.js.map |
\ | No newline at end of file |