commit 90f46db39579f1d8c956a00096d2778bf45054bf
parent cdade069cdd051ae405d5f411518a6ffb83fb827
Author: Jan Dankert <jan.dankert@hansemerkur.de>
Date: Tue, 28 Jan 2020 17:10:19 +0100
The first running implementation.
Diffstat:
3 files changed, 152 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
@@ -4,7 +4,7 @@ This is a lightweight javascript 2-way-data-binding framework, implemented as a
## Advantages
-- Really lightweight
+- Really lightweight, ~ 1kB (minified and gzipped)
- does not need any [CSP](https://en.wikipedia.org/wiki/Content_Security_Policy) permissions.
- 2-way-binding
diff --git a/bindify.js b/bindify.js
@@ -1,2 +1,135 @@
-/*! GPLv3 */
+/*! GPL */
/* bindify JQuery databinding plugin*/
+(function ( $ ) {
+
+ $.fn.bindify = function( data={},options={} ) {
+
+ let settings = $.extend({
+ prefix: 'binding',
+ updateModel: true,
+ updateDOM: true,
+ updateCallback: $.Callbacks(),
+ debug: false,
+ updateEvent: 'input',
+ onUpdate: function(data) {},
+ }, options );
+
+ let el = this;
+
+ let updateDOM = function() {
+
+ setTimeout( function() {bind(el,data)} , 0 );
+ }
+
+ settings.updateCallback.add( updateDOM );
+
+ let prefix = settings.prefix + '-';
+
+ // Enable writing back data from the DOM to the model.
+ if ( settings.updateModel)
+ $(el).find('[data-'+prefix+'value]').each( function() {
+ $(this).off(settings.updateEvent);
+ $(this).on(settings.updateEvent, function() {
+
+ if ( settings.debug )
+ console.log("Input event fired: "+this.value);
+
+ assign(data,$(this).data(prefix+'value'),this.value);
+ settings.onUpdate(data);
+ settings.updateCallback.fire();
+ } );
+ });
+
+
+
+ let assign = function(obj, prop, value) {
+ if (typeof prop === "string")
+ prop = prop.split(".");
+
+ if (prop.length > 1) {
+ var e = prop.shift();
+ assign(obj[e] =
+ Object.prototype.toString.call(obj[e]) === "[object Object]"
+ ? obj[e]
+ : {},
+ prop,
+ value);
+ } else
+ obj[prop[0]] = value;
+ }
+
+ let getData = function( key,data ) {
+ function index(obj,i) {
+ return obj[i]
+ }
+ return key.split('.').reduce(index, data);
+ }
+
+ // Lets do the data bind to a DOM element.
+ // This function is called recursively for all DOM children.
+ let bind = function( element,data) {
+
+ let dataValue = element.data(prefix+'value');
+ if ( dataValue ) {
+ element.val( getData( dataValue, data ) );
+ // Change listener for writing back the input to the model
+ }
+
+ let dataText = element.data(prefix+'text');
+ if ( dataText )
+ element.text( getData( dataText, data ) );
+
+ let dataAttributes = element.data(prefix+'attributes');
+ if ( dataAttributes ) {
+ // JQuery is parsing the JSON automatically
+ Object.keys(dataAttributes).forEach(function (key) {
+ element.attr(key, getData(dataAttributes[key],data))
+ },this);
+ }
+
+ let dataList = element.data(prefix+'list');
+ if ( dataList ) {
+ let eachData = getData( dataList, data );
+
+ let children = $(element).children();
+ let firstChild = children.first();
+ let isLength = children.length;
+ let shouldLength = eachData.length;
+ if ( isLength > 0 )
+ {
+ // Add children to force the correct children count
+ for( let i=isLength+1; i<=shouldLength; i++ )
+ firstChild.clone().appendTo( element );
+ // Remove children to force the correct children count
+ for( let i=shouldLength+1; i<=isLength; i++ )
+ element.children().last().remove();
+
+ let key = dataList;
+ let dataVar = element.data(prefix+'var');
+ if ( dataVar )
+ key = dataVar;
+
+ for( let i=0; i<eachData.length; i++) {
+ let childData = {};
+ childData[key] = eachData[i];
+ let computedDataForChild = Object.assign({},data,childData);
+ bind( children.eq(i),computedDataForChild );
+ };
+
+ }
+ }
+ else{
+ $(element).children().each( function() {
+ bind($(this),data );
+ });
+ }
+ };
+
+ // Initial Binding
+ settings.updateCallback.fire();
+
+ // JQuery should stay chainable.
+ return this;
+ };
+
+}( jQuery ));
diff --git a/bindify.min.js b/bindify.min.js
@@ -1 +1,16 @@
-/*! GPLv3 */
+(function($){$.fn.bindify=function(data={},options={}){let settings=$.extend({prefix:'binding',updateModel:!0,updateDOM:!0,updateCallback:$.Callbacks(),debug:!1,updateEvent:'input',onUpdate:function(data){},},options);let el=this;let updateDOM=function(){setTimeout(function(){bind(el,data)},0)}
+ settings.updateCallback.add(updateDOM);let prefix=settings.prefix+'-';if(settings.updateModel)
+ $(el).find('[data-'+prefix+'value]').each(function(){$(this).off(settings.updateEvent);$(this).on(settings.updateEvent,function(){if(settings.debug)
+ console.log("Input event fired: "+this.value);assign(data,$(this).data(prefix+'value'),this.value);settings.onUpdate(data);settings.updateCallback.fire()})});let assign=function(obj,prop,value){if(typeof prop==="string")
+ prop=prop.split(".");if(prop.length>1){var e=prop.shift();assign(obj[e]=Object.prototype.toString.call(obj[e])==="[object Object]"?obj[e]:{},prop,value)}else obj[prop[0]]=value}
+ let getData=function(key,data){function index(obj,i){return obj[i]}
+ return key.split('.').reduce(index,data)}
+ let bind=function(element,data){let dataValue=element.data(prefix+'value');if(dataValue){element.val(getData(dataValue,data))}
+ let dataText=element.data(prefix+'text');if(dataText)
+ element.text(getData(dataText,data));let dataAttributes=element.data(prefix+'attributes');if(dataAttributes){Object.keys(dataAttributes).forEach(function(key){element.attr(key,getData(dataAttributes[key],data))},this)}
+ let dataList=element.data(prefix+'list');if(dataList){let eachData=getData(dataList,data);let children=$(element).children();let firstChild=children.first();let isLength=children.length;let shouldLength=eachData.length;if(isLength>0)
+ {for(let i=isLength+1;i<=shouldLength;i++)
+ firstChild.clone().appendTo(element);for(let i=shouldLength+1;i<=isLength;i++)
+ element.children().last().remove();let key=dataList;let dataVar=element.data(prefix+'var');if(dataVar)
+ key=dataVar;for(let i=0;i<eachData.length;i++){let childData={};childData[key]=eachData[i];let computedDataForChild=Object.assign({},data,childData);bind(children.eq(i),computedDataForChild)}}}
+ else{$(element).children().each(function(){bind($(this),data)})}};settings.updateCallback.fire();return this}}(jQuery))+
\ No newline at end of file