Skip to content

Instantly share code, notes, and snippets.

@Shimilbi
Last active September 22, 2023 23:58
Show Gist options
  • Save Shimilbi/34fc68e7c60578a28358c0c69a78c57b to your computer and use it in GitHub Desktop.
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.
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 = ''
}
})
}
}
@Shimilbi
Copy link
Author

Shimilbi commented Sep 21, 2023

As package : Link
Made to sync the html display, not to sync an object's state in the code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment