|
3 | 3 | // Based on a CSS-Tricks Post |
4 | 4 |
|
5 | 5 | var codeInput = { |
6 | | - observedAttributes: [ |
| 6 | + observedAttributes: [ // Doesn't include events, as they are transferred by overriding {add/remove}EventListener |
7 | 7 | "value", |
8 | 8 | "name", |
9 | 9 | "placeholder", |
10 | 10 | "lang", |
11 | | - "template", |
12 | | - "onchange", |
13 | | - "onselectionchange" |
| 11 | + "template" |
14 | 12 | ], |
15 | 13 | // Attributes to monitor - needs to be global and static |
16 | 14 |
|
@@ -50,7 +48,7 @@ var codeInput = { |
50 | 48 | super(); // Element |
51 | 49 | } |
52 | 50 |
|
53 | | - last_events = {}; // Last events applied; removed when changed so can be added to textarea, etc. |
| 51 | + bound_callbacks = {}; // Callback without this context > Callback with forced codeInput elem this |
54 | 52 |
|
55 | 53 | /* Run this event in all plugins with a optional list of arguments */ |
56 | 54 | plugin_evt(id, args) { |
@@ -178,12 +176,6 @@ var codeInput = { |
178 | 176 |
|
179 | 177 | this.plugin_evt("afterElementsAdded"); |
180 | 178 |
|
181 | | - // Events |
182 | | - textarea = this.querySelector("textarea"); |
183 | | - // Add event listeners, bound so `this` can be referenced |
184 | | - this.transfer_event("change", this.querySelector("textarea"), null, this.onchange); |
185 | | - this.transfer_event("selectionchange", this.querySelector("textarea"), null, this.onselectionchange); |
186 | | - |
187 | 179 | /* Add code from value attribute - useful for loading from backend */ |
188 | 180 | this.update(value, this); |
189 | 181 | } |
@@ -261,29 +253,57 @@ var codeInput = { |
261 | 253 | this.update(this.value); |
262 | 254 |
|
263 | 255 | break; |
264 | | - |
265 | | - // Events |
266 | | - case "onchange": |
267 | | - this.transfer_event("change", this.querySelector("textarea"), oldValue, newValue); |
268 | | - break; |
269 | | - case "onselectionchange": |
270 | | - this.transfer_event("selectionchange", this.querySelector("textarea"), oldValue, newValue); |
271 | | - break; |
272 | 256 | } |
273 | 257 | } |
274 | 258 |
|
275 | 259 | } |
276 | 260 |
|
277 | | - /* Transfer an event by name from this to an inner element. */ |
278 | | - transfer_event(evt_name, transfer_to, oldValue, newValue) { |
279 | | - // Doesn't exist |
280 | | - if(oldValue) { |
281 | | - transfer_to.removeEventListener(evt_name, this.last_events[evt_name]); |
| 261 | + // /* Transfer an event by name from this to an inner element. */ |
| 262 | + // transfer_event(evt_name, transfer_to, oldValue, newValue) { |
| 263 | + // if(oldValue) { // Remove old listener |
| 264 | + // transfer_to.removeEventListener(evt_name, this.last_events[evt_name]); |
| 265 | + // } |
| 266 | + // if(newValue) { |
| 267 | + // this.last_events[evt_name] = this[`on${evt_name}`].bind(this); |
| 268 | + // transfer_to.addEventListener(evt_name, this.last_events[evt_name]); |
| 269 | + // this.removeEventListener(evt_name, newValue); |
| 270 | + // } |
| 271 | + // } |
| 272 | + |
| 273 | + /* Override addEventListener so event listener added to necessary child. Returns callback bound to code-input element as `this` */ |
| 274 | + addEventListener(evt_name, callback, thirdParameter=null) { |
| 275 | + let boundCallback = callback.bind(this); |
| 276 | + this.bound_callbacks[callback] = boundCallback; |
| 277 | + if(evt_name == "change") { |
| 278 | + if(thirdParameter === null) { |
| 279 | + this.querySelector("textarea").addEventListener("change", boundCallback); |
| 280 | + } else { |
| 281 | + this.querySelector("textarea").addEventListener("change", boundCallback, thirdParameter); |
| 282 | + } |
| 283 | + } else if(evt_name == "selectionchange") { |
| 284 | + if(thirdParameter === null) { |
| 285 | + this.querySelector("textarea").addEventListener("selectionchange", boundCallback); |
| 286 | + } else { |
| 287 | + this.querySelector("textarea").addEventListener("selectionchange", boundCallback, thirdParameter); |
| 288 | + } |
282 | 289 | } |
283 | | - if(newValue) { |
284 | | - this.last_events[evt_name] = this.onchange.bind(this); |
285 | | - transfer_to.addEventListener(evt_name, this.last_events[evt_name]); |
286 | | - this[`on${evt_name}`] = undefined; // Prevent duplicate |
| 290 | + } |
| 291 | + |
| 292 | + /* Override removeEventListener so event listener removed from necessary child */ |
| 293 | + removeEventListener(evt_name, callback, thirdParameter=null) { |
| 294 | + let boundCallback = this.bound_callbacks[callback]; |
| 295 | + if(evt_name == "change") { |
| 296 | + if(thirdParameter === null) { |
| 297 | + this.querySelector("textarea").removeEventListener("change", boundCallback); |
| 298 | + } else { |
| 299 | + this.querySelector("textarea").removeEventListener("change", boundCallback, thirdParameter); |
| 300 | + } |
| 301 | + } else if(evt_name == "selectionchange") { |
| 302 | + if(thirdParameter === null) { |
| 303 | + this.querySelector("textarea").removeEventListener("selectionchange", boundCallback); |
| 304 | + } else { |
| 305 | + this.querySelector("textarea").removeEventListener("selectionchange", boundCallback, thirdParameter); |
| 306 | + } |
287 | 307 | } |
288 | 308 | } |
289 | 309 |
|
|
0 commit comments