bindify.js (5165B)
1 /*! GPL */ 2 /* bindify JQuery databinding plugin*/ 3 (function ( $ ) { 4 5 $.fn.bindify = function( data={},options={} ) { 6 7 let settings = $.extend({ 8 prefix: 'binding', 9 updateModel: true, 10 updateDOM: true, 11 updateCallback: $.Callbacks(), 12 debug: false, 13 updateEvent: 'input', 14 onUpdate: function(data) {}, 15 }, options ); 16 17 let el = this; 18 19 let updateDOM = function() { 20 21 setTimeout( function() {bind(el,data)} , 0 ); 22 } 23 24 settings.updateCallback.add( updateDOM ); 25 26 let prefix = settings.prefix + '-'; 27 28 // Enable writing back data from the DOM to the model. 29 if ( settings.updateModel) 30 $(el).find('[data-'+prefix+'value]').each( function() { 31 // Change listener for writing back the input to the model 32 // First, remove any other listeners 33 $(this).off(settings.updateEvent); 34 // Now create the listener for new input values. 35 $(this).on(settings.updateEvent, function() { 36 37 if ( settings.debug ) 38 console.log("Input event fired: "+this.value); 39 40 assign(data,$(this).data(prefix+'value'),this.value); 41 settings.onUpdate(data); 42 settings.updateCallback.fire(); 43 } ); 44 }); 45 46 47 48 let assign = function(obj, prop, value) { 49 if (typeof prop === "string") 50 prop = prop.split("."); 51 52 if (prop.length > 1) { 53 var e = prop.shift(); 54 assign(obj[e] = 55 Object.prototype.toString.call(obj[e]) === "[object Object]" 56 ? obj[e] 57 : {}, 58 prop, 59 value); 60 } else 61 obj[prop[0]] = value; 62 } 63 64 let getData = function( key,data ) { 65 function index(obj,i) { 66 return obj[i] 67 } 68 return key.split('.').reduce(index, data); 69 } 70 71 // Lets do the data bind to a DOM element. 72 // This function is called recursively for all DOM children. 73 let bind = function( element,data) { 74 75 // Value binding for input elements 76 // input values are written back to the data model 77 let dataValue = element.data(prefix+'value'); 78 if ( dataValue ) { 79 element.val( getData( dataValue, data ) ); 80 // A change listener is already created. 81 } 82 83 // Binding for the node content. 84 let dataText = element.data(prefix+'text'); 85 if ( dataText ) 86 element.text( getData( dataText, data ) ); 87 88 // Binding for the attributes. 89 let dataAttributes = element.data(prefix+'attributes'); 90 if ( dataAttributes ) { 91 // JQuery is parsing the JSON automatically 92 Object.keys(dataAttributes).forEach(function (key) { 93 element.attr(key, getData(dataAttributes[key],data)) 94 },this); 95 } 96 97 // Binding for a list 98 let dataList = element.data(prefix+'list'); 99 if ( dataList ) { 100 let eachData = getData( dataList, data ); 101 102 let children = $(element).children(); 103 let firstChild = children.first(); 104 let isLength = children.length; 105 let shouldLength = eachData.length; 106 if ( isLength > 0 ) 107 { 108 if ( settings.debug ) 109 console.log("List "+dataList+" has "+isLength+ " entrys, should have "+shouldLength); 110 111 // Add children to force the correct children count 112 for( let i=isLength+1; i<=shouldLength; i++ ) 113 firstChild.clone().appendTo( element ); 114 // Remove children to force the correct children count 115 for( let i=shouldLength+1; i<=isLength; i++ ) 116 element.children().last().remove(); 117 118 let children = $(element).children(); 119 let key = dataList; 120 let dataVar = element.data(prefix+'var'); 121 if ( dataVar ) 122 key = dataVar; 123 124 for( let i=0; i<eachData.length; i++) { 125 let childData = {}; 126 childData[key] = eachData[i]; 127 let computedDataForChild = Object.assign({},data,childData); 128 bind( children.eq(i),computedDataForChild ); 129 }; 130 131 } 132 } 133 else{ 134 $(element).children().each( function() { 135 bind($(this),data ); 136 }); 137 } 138 }; 139 140 // Initial Binding 141 settings.updateCallback.fire(); 142 143 // JQuery should stay chainable. 144 return this; 145 }; 146 147 }( jQuery ));