Created
November 29, 2023 23:37
-
-
Save dfkaye/548622151971122110bf4047ae3ac432 to your computer and use it in GitHub Desktop.
onpropertychange signal v.8 -- trying to simplify the prototype stack
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 26 September 2023 | |
// onpropertychange signal v.8 | |
// cont'd from https://gist.github.com/dfkaye/3affad4c43e363a84ac4320eae375129 | |
// Going back to v.1 prototype enhancement/pollution, (see | |
// https://gist.github.com/dfkaye/619c5f31080fce2cd383ac966e132311), trying to | |
// simplify the prototype stack. | |
// The signals and delegate properties are assigned on the target using the | |
// Object.defineProperty API (which I guess I like), but the notify, on, off | |
// parts I'm not so sure about. signal(handler) means use this one handler to | |
// report changes, on(prop) should report changes to that prop only, and | |
// off(prop) should stop watching that prop. | |
// Unfortunately, we still have yet to figure out how to get Array.push() to | |
// report changes to an index and/or the array length, making this solution yet | |
// another hand-waving exercise... | |
// EventTarget.prototype.signal = function (h) { | |
Object.prototype.signal = function (h) { | |
function map(t, f) { | |
return function () { return f.apply(t, [...arguments]); }; | |
} | |
var target = this; | |
(typeof h == "function") | |
|| (h = function (e) { | |
return target instanceof EventTarget | |
? target.dispatchEvent(e) | |
: (new EventTarget).dispatchEvent(e); | |
}); | |
Object.assign(target, { | |
notify: h, | |
off: target.off || function(property) { | |
target.signals.delete(property); | |
return target.proxy; | |
}, | |
on: target.on || function(property) { | |
target.signals.add(property); | |
return target.proxy; | |
} | |
}); | |
var { signals, delegate } = target; | |
!('signals' in target) && ( | |
signals = new Set, | |
Object.defineProperty(target, "signals", { | |
value: signals | |
}) | |
); | |
!('delegate' in target) && ( | |
delegate = {}, | |
Object.defineProperty(target, "delegate", { | |
value: delegate | |
}) | |
); | |
var handler = { | |
get(target, key) { | |
var { delegate } = target; | |
if (typeof delegate[key] == "function") { | |
return delegate[key]; | |
} | |
var value = Reflect.get(target, key); | |
return typeof value == "function" | |
? delegate[key] = map(target, value) | |
: value; | |
}, | |
set(target, key, value) { | |
var previous = Reflect.get(target, key); | |
if (previous === value) { | |
return true; | |
} | |
Reflect.set(target, key, value); | |
var { delegate } = target; | |
if (typeof value == "function" && key in delegate) { | |
delegate[key] = null; | |
} | |
if (!(target.signals.has(key))) { | |
return true; | |
} | |
var event = new CustomEvent("signal", { | |
detail: { propertyName: key, value, previous } | |
}); | |
for (var [name, value] of Object.entries(event.detail)) { | |
Object.defineProperty(event, name, { | |
value, | |
enumerable: true | |
}); | |
} | |
Object.defineProperty(event, 'target', { | |
value: target, | |
enumerable: true | |
}); | |
target.notify(event); | |
return true; | |
// return target.dispatchEvent(event); | |
} | |
}; | |
return new Proxy(this, handler); | |
} | |
/* test it out */ | |
function f(e) { | |
console.log("f") | |
console.log(e); | |
} | |
function h(e) { | |
console.log(e.target.outerHTML); | |
console.warn(e.propertyName); | |
e.propertyName = null; | |
delete e.propertyName; | |
console.log(e.propertyName); | |
} | |
var input = document.createElement('input').signal(h); | |
//input.signal( f ); | |
input.setAttribute("value", "some value") | |
input.on('name'); | |
input.setAttribute("name", "test"); | |
//input.addEventListener("signal", h); | |
input.name = " ... "; | |
input.name = "abc"; | |
input.name = "DEF"; | |
input.on('value'); | |
//input.addEventListener("signal", h); | |
input.value = "ZYX"; | |
input.value = "wvu"; | |
input.value = " ... "; | |
input.on("id"); | |
input.setAttribute("id", "color: red;"); | |
var array = ['a', 'b', 'c'].signal( f ); | |
//array.signal( h ); | |
array.on('length'); | |
// works | |
array.length = 5; | |
// doesn't work | |
array.push('d'); | |
array.join(", "); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment