Last active
September 22, 2023 23:58
-
-
Save Shimilbi/34fc68e7c60578a28358c0c69a78c57b to your computer and use it in GitHub Desktop.
Lier un élément du DOM à un objet littéral JS qui se s'synchroniseront dans les deux sens à chaque changement de leur état.
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
class Bind { | |
/* | |
new Bind(_element[, _outputElement[, _makeEqual]]): (JS object) | |
Parameters | |
_element: master DOM element (HTML object) | |
_outputElement: optional slave DOM element (HTML object) | |
_makeEqual: optional (bolean) let all elements change each other; no master slave relation | |
Variables | |
Value | |
Element | |
OutputElement | |
ReciprocatingBind (JS object) | |
Methods | |
MakeEqual() | |
Usage in HTML alone: | |
<input onkeyup="new Bind(this, this.nextElementSibling, true)"/> | |
<p></p> | |
Or: | |
<body onload="new Bind(document.querySelector('#a'), document.querySelector('#b'), true)"> | |
<input id="a" onclick="select()" value="Specific binding to specific tag" /> | |
<p id="b" contenteditable>Specific binding to specific tag</p><hr /><br> | |
Note: <body onload="new Bind(this.firstChild, this.firstChild.nextElementSibling)"> won't work. | |
Or, usage in JS variable | |
In HTML: | |
<input id="UserDataInput"/> | |
Or: <p contenteditable id="UserDataInput"></p> | |
Instanciating in JS: | |
var myVariable = new Bind( document.querySelector('#UserDataInput'), undefined, true ) | |
Reading in JS: consol.log(myVariable.Value) | |
Writing in JS: myVariable.Value = "" | |
Or, usage in JS object | |
In HTML: | |
<input id="UserDataInput"/> | |
Or: <p contenteditable id="UserDataInput"></p> | |
Instanciating in JS: | |
var myLitObject = { | |
datalink: Object.create('Bind(document.querySelector('#UserDataInput')), { handleEvent(event_) { | |
switch (event_.type) | |
{ | |
case 'click': | |
// ... | |
} | |
} }), | |
DefaultValue: 'initial value', | |
get Value() { | |
myLitObject.datalink.Value!==undefined? | |
myLitObject.datalink.Value : | |
myLitObject.DefaultValue | |
}, | |
set Value(value_) { | |
// check all needed tests here | |
if (value_ !== udnefined) | |
{ | |
myLitObject.datalink.Value = value_ | |
} | |
}, | |
History: [], | |
Restore: function (index) { | |
if (typeof myLitObject.History[index] === 'undefined') { | |
console.log('No data found in history at speficied index '+index) | |
return false | |
} | |
myLitObject.datalink.Value = myLitObject.History[index] | |
}, | |
Enable: function () { | |
if (MyDomObject_With_UserData.datalink.disabled) | |
_element.removeAttribute('disabled') | |
return !MyDomObject_With_UserData.datalink.disabled | |
}, | |
Disable: function () { | |
if (!MyDomObject_With_UserData.datalink.disabled) | |
{ | |
let attr = document.createAttribute('disabled') | |
_element.setAttributeNode(attr) | |
} | |
return MyDomObject_With_UserData.datalink.disabled | |
} | |
} | |
Reading in JS: consol.log(myLitObject.Value) | |
Writing in JS: myLitObject.Value = "" | |
*/ | |
get Value () { | |
return this._Value | |
} | |
set Value (value) { | |
this._Value = value | |
if (this.Element.tagName.toLowerCase() === 'input') | |
this.Element.value = value | |
else | |
this.Element.textContent = value | |
if (this.OutputElement !== undefined) { | |
if (this.OutputElement.tagName.toLowerCase() === 'input') | |
this.OutputElement.value = value | |
else | |
this.OutputElement.textContent = value | |
} | |
} | |
constructor (_element, _outputElement, _makeEqual) { | |
if (_element === undefined) { | |
this.Element = undefined | |
this.Value = undefined | |
this.OutputElement = undefined | |
console.log('Bind Constructor: element to bind is undefined') | |
return false | |
} | |
this.Element = _element | |
if (_element.tagName.toLowerCase() === 'input') | |
if (!_element.hasAttribute('value')) | |
_element.setAttributeNode(document.createAttribute('value')) | |
this.Value = this.Element.hasAttribute('value') | |
|| this.Element.tagName.toLowerCase() == 'input' | |
? this.Element.value | |
: this.Element.textContent | |
if (_outputElement !== undefined) | |
if (_outputElement.tagName === 'input') | |
if (!_outputElement.hasAttribute('value')) | |
_outputElement.setAttributeNode(document.createAttribute('value')) | |
this.OutputElement = _outputElement | |
// Public array variable | |
this.ReciprocatingBind = [] | |
// Public method | |
this.MakeEqual = () => this.makeEqual() | |
_element.addEventListener('change', this, false) | |
_element.addEventListener('keyup', this, false) | |
if (_makeEqual) | |
this.makeEqual(_outputElement, _element) | |
} | |
makeEqual (e1, e2) { | |
let ele1 = e1===undefined? this.Element : e1, | |
ele2 = e2===undefined? this.OutputElement : e2 | |
this.ReciprocatingBind = new Bind(ele1, ele2, false) | |
} | |
handleEvent (event) { | |
switch (event.type) { | |
case 'change': case 'keyup': | |
this.Value = this.Element.hasAttribute('value') | |
? this.Element.value | |
: this.Element.textContent | |
} | |
} | |
} | |
class BindAll { | |
/* | |
new BindAll(_element, _outputElements[, _makeEqual]): (JS object) | |
Parameters | |
_element: master DOM element (HTML object) | |
_outputElements: slave DOM elements (HTML objects) | |
_makeEqual: optional (bolean) let all elements change each other; no master slave relation | |
Variables | |
Element | |
OutputElements | |
Value | |
ReciprocatingBinds | |
Methods | |
MakeEqual() | |
Usage in HTML alone: | |
<input onkeyup="new BindAll(this, document.querySelectorAll('[example2]'))"/> | |
<p example2></p> | |
<button example2></button> | |
Or: | |
<input onkeyup="new BindAll(this, [document.querySelector('#example2a'), document.querySelector('#example2b')])"/> | |
<p id="example2a"></p> | |
<button id="example2b"></button> | |
*/ | |
// public variable | |
get Value() { | |
return this._Value | |
} | |
set Value(value) { | |
this._Value = value | |
if (this.Element.hasAttribute('value')) | |
this.Element.value = value | |
else | |
this.Element.textContent = value | |
if (this.OutputElements !== undefined) | |
this.OutputElements.forEach(outputElement => { | |
if (outputElement !== undefined) { | |
if (outputElement.hasAttribute('value')) | |
outputElement.value = value | |
else | |
outputElement.textContent = value | |
} | |
}) | |
} | |
constructor(_element, _outputElements, _makeEqual) { | |
if (_element === undefined) { | |
this.Element = undefined | |
this.Value = undefined | |
this.OutputElements = undefined | |
console.log('Bind Constructor: element to bind is undefined') | |
return false | |
} | |
this.Element = _element | |
if (_element.tagName.toLowerCase() === 'input') | |
if (!_element.hasAttribute('value')) | |
_element.setAttributeNode(document.createAttribute('value')) | |
// For this function, the parameter _outputElements is always required | |
if (_outputElements === undefined) { | |
console.log('BindAll: Parameter _outputElements is undefined. No element found to bind ' + _element + ' to.') | |
return false | |
} | |
if (!Array.isArray(_outputElements)) { | |
const arr = Array.from(_outputElements) | |
if (arr.length < 1) { | |
console.log('BindAll: Parameter _outputElements requires a collection or an array.') | |
return false | |
} | |
this.OutputElements = arr | |
} | |
else | |
this.OutputElements = _outputElements | |
this.OutputElements.forEach(outputElement => { | |
if (outputElement.tagName.toLowerCase() === 'input') | |
if (!outputElement.hasAttribute('value')) | |
outputElement.setAttributeNode(document.createAttribute('value')) | |
}) | |
this.Value = this.Element.hasAttribute('value') | |
? this.Element.value | |
: this.Element.textContent | |
this.MakeEqual = function(){ | |
this.makeEqual() | |
} | |
this.OutputElements.forEach(outputElement => { | |
if (outputElement.tagName.toLowerCase() === 'input') { | |
if (!outputElement.hasAttribute('value')) | |
outputElement.setAttributeNode(document.createAttribute('value')) | |
} | |
this.setPlaceholders() | |
}) | |
this.ReciprocatingBinds = [] | |
_element.addEventListener("change", this, false) | |
_element.addEventListener("keyup", this, false) | |
if (_makeEqual) | |
this.makeEqual() | |
} | |
// private method | |
makeEqual(elements) { | |
let allElements = elements | |
if (allElements==undefined) | |
allElements = [this.Element, ...this.OutputElements] | |
let otherElements | |
this.ReciprocatingBinds = [] | |
allElements.forEach(element => { | |
otherElements = allElements | |
this.ReciprocatingBinds.push( new BindAll(element, otherElements) ) | |
}) | |
} | |
// private method | |
handleEvent(event) { | |
switch (event.type) { | |
case 'input': case 'change': case 'keyup': | |
this.Value = this.Element.hasAttribute('value') | |
? this.Element.value | |
: this.Element.textContent | |
if ('placeholder' in this.Element.dataset && this.Element.textContent == this.Element.getAttribute('data-placeholder')) | |
this.Element.style.color = 'grey' | |
} | |
} | |
setPlaceholders(reset) { | |
// Apply the values of the data-plaeceholder attributes | |
if (reset===undefined) | |
reset = false | |
this.OutputElements.forEach(outputElement => { | |
if (outputElement.hasAttribute('data-placeholder') | |
|| 'placeholder' in outputElement.dataset) | |
outputElement.textContent = outputElement.getAttribute('data-placeholder') | |
else if (reset && outputElement.hasAttribute('placeholder')) { | |
outputElement.value = '' | |
} | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
As package : Link
Made to sync the html display, not to sync an object's state in the code.