diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b3b2f04..0000000 --- a/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: node_js -node_js: - - "0.10" - -before_script: - - export DISPLAY=:99.0 - - sh -e /etc/init.d/xvfb start - - npm start > /dev/null & - - npm install -g bower - - bower install - - sleep 1 # give server time to start - -script: - - npm test \ No newline at end of file diff --git a/README.md b/README.md index b9302fd..1b08170 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,45 @@ -# jq-repeat [![Build Status](https://travis-ci.org/wmantly/jq-repeat.svg)](https://travis-ci.org/wmantly/jq-repeat) +# jq-repeat + +Author William Mantly Jr + -[![Join the chat at https://gitter.im/wmantly/jq-repeat](https://badges.gitter.im/wmantly/jq-repeat.svg)](https://gitter.im/wmantly/jq-repeat?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) A simple, yet highly customizable plugin to handle all of you're client-side repetitive DOM needs. Simple, quick and powerful templating. It is modeled after ng-repeat and shares some basic syntax, but is not a clone. -* To do list [demo](http://jsfiddle.net/wmantly/nLj6nr4q/) -* Reddit JSON feed [demo](http://jsfiddle.net/wmantly/sge3zr28/) +- To do list [demo](http://jsfiddle.net/wmantly/nLj6nr4q/) +- Reddit JSON feed [demo](http://jsfiddle.net/wmantly/sge3zr28/) -# Requirements +# Requirements -* __jq-repeat requires [jQuery](http://jquery.com/) 1.x/2.x and [Mustache](https://github.com/janl/mustache.js) 1.x to run__. +- **jq-repeat requires [jQuery](http://jquery.com/) 1.x/2.x/3.x and [Mustache](https://github.com/janl/mustache.js) 1.x/2.x/3.x/4.x to run**. + +## Examples +Some simple examples of each methods that can used. +[examples](https://github.com/wmantly/jq-repeat/tree/master/example) ## Template + To set up a jq-repeat template, write any element tag you wish to repeat once where you want the repeating to start, this will serve as the template and starting point. -Simply add a `jq-repeat` attribute with a unique value for the reference name for that template, in this case `toDo`. +Simply add a `jq-repeat` attribute with a unique value for the reference name for that template, in this case `toDo`. + ```html ``` + Just like mustache, to add variables use double brackets with the name inside. ## Insert + Now that you have a template set up, let's populate the template use $.scope.toDo.push() + ```javaScript $.scope.toDo.push( { item: 'Get milk', done: 'Yes' } ) ``` + You can add any number of objects as arguments you wish and each will create a new element from the template. Values must be supplied as objects with keys corresponding to the variable names used in the template. + ```javaScript $.scope.toDo.push({ item: 'Collect underwear', @@ -41,39 +52,74 @@ $.scope.toDo.push({ done: 'No' }); ``` + ## Methods -The repeat object can take many methods used for arrays, as arrays are the internal data structure. - -* `$.scope.toDo.splice(index [,howMany] [,ToAdd])` functions exactly as a regular array with notable difference. If the index propriety is set a string can be passed as the value of the index. - * **index** *Type: Number or String* - Index of element you wish to manipulate. If the .index property is set, you may pass a string to match to the index array. - * **howMany** *Type: Number* - Number of repeat objects that will be removed. If there are non to be removed, it is not required to use this argument. - * **update** *Type: Array* - This is the array of repeat objects to add. If there are none to this is not required. - * **returns** *Type: Array* - This function will return an array of deleted elements. -* `$.scope.toDo.pop()` Will remove and return the last element in the repeat array -* `$.scope.toDo.reverse()` Will reverse the repeat array by index number.todo: if .index is a number, will use that. Returns the newly formated array. -* `$.scope.toDo.shift()` works the same as regular arrays. -* `$.scope.toDo.loop()` will take the last value and insert in the front. `toDo.loopUp()` does the opposite. Returns the newly formated array. -* `$.scope.toDo.indexOf( key, value )` Returns the array index number of the matching element. Mostly used for internals. - * **key** *Type: String* - The key element to match. - * **value** *Type: String* - The value of the matching element. -* `$.scope.toDo.update( key, [value,] update)` Updates selected value with new data. The selection process is done by matching key, value pairs from the existing objects, - * **key** *Type: String or Number* - The key or index to the matching element to update - * **value** *Type: String* - The value of the matching key to the element to be update.If the index number will be used, must be ommited! - * **update** *Type: Object* - This is the object that will be applied to the matching element. -* `$.scope.toDo.__put` is the function that will run when a element is being inserted. This must be a function and must include this.show(), or some other way of un-hiding 'this'. -* `$.scope.toDo.__take` is the function that will run when an element is being removed. This must be a function and include this.remove() or some other way to remove 'this'. -* `$scope.toDo.__index` is the propriety that defines the object key to use an the index. If this is set, a string can be used in place of a number for any index reference. + +- `$.scope.toDo.push([object])` + - **Description**: The method will just insert object with the relevent key and value pair as used in your template. + - **Parameter**: + - **Type: object**: Object with key and value in the HTML template. +- `$.scope.toDo.pop()` + - **Description**: The method will remove and return the last element in the repeat array. +- `$.scope.toDo.reverse()` + - **Description**: The method will reverse the repeat array and append the array. +- `$.scope.toDo.remove([key] || [index Id])` + - **Description**: The method would use either the key value of the pair to remove or use the index id to remove an array item. + - **Parameters**: + - **key**: The key of the array you wish to remove. + - **Index Id**: The array Id you wish to remove. +- `$.scope.toDo.shift()` + - **Description**: The method works the same as regular arrays. +- `$.scope.toDo.loop()` + - **Description**: The method takes the 0th item of an array and adds it as the last item of the array. +- `$.scope.toDo.loopUp()` + - **Description**: The method does the opposite of loop(). +- `$.scope.toDo.indexOf()` + - **Description**: The method will return the array index number of the matching element or array id. Mostly used for internals usage. + - **Parameters**: + - **key**: The key of the array you wish to get the id of. + - **Value**: The value of the key pair you wish to get the id of. +- `$.scope.toDo.update([key] || [index Id] , [Object])` + - **Description**: The method would use either the key value of the pair to update or use the index id to update the object key value pair. + - **Parameters**: + - **key**: The key of the array you wish to update. + - **Index Id**: The array Id you wish to update. + - **Object**: The object you wish to update the array with. +- `$.scope.toDo.splice()` + - **Description**: The method exactly as a regular array with notable difference. If the index propriety is set a string can be passed as the value of the index. + - **Parameters**: + - **Index**: The key of the array you wish to update or array id. + - **Amount**: TheNumber of repeat objects that will be removed. If there are non to be removed. + - **Object**: The object you wish to add to the array. +- `$.scope.toDo.getByKey([key] || [index Id])` + - **Description**: The method would use either the key value of the pair to get or use the index id to get an array item. + - **Parameters**: + - **key**: The key of the array you wish to get. + - **Index Id**: The array Id you wish to get. +- `$.scope.toDo.__setPut(function($el, item, list){ [logic of your code] })` + - **Description**: The method takes a callback function that will run when a element is being inserted. This must be a function and must include `$el.show()`, or some other way of un-hiding `$el`. + - **Parameters**: + - **$el**: refers to the DOM element or relevent HTML tag. + - **item**: refers to the each of the array key pair. + - **list**: refers to the jq-repeat attribute object array. +- `$.scope.toDo.__setTake(function($el, item, list){ [logic of your code] })` + - **Description**: The method takes a callback function that will run when a element is being remove. This must be a function and must include `$el.show()`, or some other way of un-hiding `$el`. + - **Parameters**: + - **$el**: refers to the DOM element or relevent HTML tag. + - **item**: refers to the each of the array key pair. + - **list**: refers to the jq-repeat attribute object array. +- `$.scope.toDo.__setUpdate(function($el, item, list){ [logic of your code] })` + - **Description**: The method takes a callback function that will run when a element is being updated. This must be a function and must include `$el.show()`, or some other way of un-hiding `$el`. + - **Parameters**: + - **$el**: refers to the DOM element or relevent HTML tag. + - **item**: refers to the each of the array key pair. + - **list**: refers to the jq-repeat attribute object array. ## Credits -* Written by [William Mantly](https://github.com/wmantly) -* Big thanks to [Derek Hu](https://github.com/derek-dchu) for creating NPM and bower package, and other general house keeping. -* Also, thanks to [Raja Kapur](https://github.com/aonic) for advice and guidance. +- Written by [William Mantly](https://github.com/wmantly) +- Big thanks to [Derek Hu](https://github.com/derek-dchu) for creating NPM and bower package, and other general house keeping. +- Thanks to [Ti Seng Lim](https://github.com/Newtbot) for updating the readme documentation and adding examples. +- Also, thanks to [Raja Kapur](https://github.com/aonic) for advice and guidance. + + + diff --git a/example/getByKey.html b/example/getByKey.html new file mode 100644 index 0000000..7d58969 --- /dev/null +++ b/example/getByKey.html @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + Document + + + + + + + + + diff --git a/example/indexOf.html b/example/indexOf.html new file mode 100644 index 0000000..47eea25 --- /dev/null +++ b/example/indexOf.html @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + Document + + + + + + + + + diff --git a/example/insert.html b/example/insert.html new file mode 100644 index 0000000..56eec81 --- /dev/null +++ b/example/insert.html @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + Document + + + + + + + \ No newline at end of file diff --git a/example/loop.html b/example/loop.html new file mode 100644 index 0000000..55d9a0a --- /dev/null +++ b/example/loop.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + Document + + + + + + + + + diff --git a/example/loopUp.html b/example/loopUp.html new file mode 100644 index 0000000..619fdb7 --- /dev/null +++ b/example/loopUp.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + Document + + + + + + + + + diff --git a/example/pop.html b/example/pop.html new file mode 100644 index 0000000..1e01b4e --- /dev/null +++ b/example/pop.html @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + Document + + + + + + + \ No newline at end of file diff --git a/example/remove.html b/example/remove.html new file mode 100644 index 0000000..e4babc7 --- /dev/null +++ b/example/remove.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + Document + + + + + + + + + diff --git a/example/reverse.html b/example/reverse.html new file mode 100644 index 0000000..af9c948 --- /dev/null +++ b/example/reverse.html @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + Document + + + + + + + \ No newline at end of file diff --git a/example/setPut.html b/example/setPut.html new file mode 100644 index 0000000..e23fa39 --- /dev/null +++ b/example/setPut.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + Document + + + + + + + \ No newline at end of file diff --git a/example/setTake.html b/example/setTake.html new file mode 100644 index 0000000..4b9f57e --- /dev/null +++ b/example/setTake.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + Document + + + + + + + \ No newline at end of file diff --git a/example/setUpdate.html b/example/setUpdate.html new file mode 100644 index 0000000..257b768 --- /dev/null +++ b/example/setUpdate.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + Document + + + + + + + \ No newline at end of file diff --git a/example/shift.html b/example/shift.html new file mode 100644 index 0000000..5e8866f --- /dev/null +++ b/example/shift.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + Document + + + + + + + + + diff --git a/example/splice.html b/example/splice.html new file mode 100644 index 0000000..e9532c7 --- /dev/null +++ b/example/splice.html @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + Document + + + + + + + + + diff --git a/example/update.html b/example/update.html new file mode 100644 index 0000000..a76a3dd --- /dev/null +++ b/example/update.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + Document + + + + + + + + + diff --git a/src/jq-repeat.js b/src/jq-repeat.js index 643853f..e30e500 100644 --- a/src/jq-repeat.js +++ b/src/jq-repeat.js @@ -11,255 +11,264 @@ MIT license } var make = function( element ){ + var result = []; - //construct array - function makeArray( input ){ + result.splice = function(inputValue, ...args){ + //splice does all the heavy lifting by interacting with the DOM elements. - var result = []; + var toProto = [...args] - Object.defineProperty( result, "__repeatId", { - value: repeatId, - writable: true, - enumerable: false, - configurable: true - } ); - - Object.defineProperty( result, "__rq_template", { - value: '', - writable: true, - enumerable: false, - configurable: true - } ); - - result.splice = function(inputValue, ...args){ - //splice does all the heavy lifting by interacting with the DOM elements. - - var toProto = [...args] - - var index; - //if a string is submitted as the index, try to match it to index number - if( typeof arguments[0] === 'string' ){ - index = this.indexOf( arguments[0] );//set where to start - if ( index === -1 ) { - return []; - } - }else{ - index = arguments[0]; //set where to start + var index; + //if a string is submitted as the index, try to match it to index number + if( typeof arguments[0] === 'string' ){ + index = this.indexOf( arguments[0] );//set where to start + if ( index === -1 ) { + return []; } + }else{ + index = arguments[0]; //set where to start + } - toProto.unshift(index) - + toProto.unshift(index) - var howMany = arguments[1]; //sets the amount of fields to remove - var args = Array.prototype.slice.call( arguments ); // coverts arguments into array - var toAdd = args.slice(2); // only keeps fields to add to array + var howMany = arguments[1]; //sets the amount of fields to remove + var args = Array.prototype.slice.call( arguments ); // coverts arguments into array + var toAdd = args.slice(2); // only keeps fields to add to array - // if the starting point is higher then the total index count, start at the end - if( index > this.length ) { - index = this.length; - } - // if the starting point is negative, start form the end of the array, minus the start point - if( index < 0 ) { - index = this.length - Math.abs( index ); - } + // if the starting point is higher then the total index count, start at the end + if( index > this.length ) { + index = this.length; + } + // if the starting point is negative, start form the end of the array, minus the start point + if( index < 0 ) { + index = this.length - Math.abs( index ); + } - // if there are things to add, figure out the how many new indexes we need - if( !howMany && howMany !== 0 ) { - howMany = this.length - index; - } - //not sure why i put this here... but it does matter! - if( howMany > this.length - index ) { - howMany = this.length - index; - } + // if there are things to add, figure out the how many new indexes we need + if( !howMany && howMany !== 0 ) { + howMany = this.length - index; + } + //not sure why i put this here... but it does matter! + if( howMany > this.length - index ) { + howMany = this.length - index; + } - //figure out how many positions we need to shift the current elements - var shift = toAdd.length - howMany; + //figure out how many positions we need to shift the current elements + var shift = toAdd.length - howMany; - // figure out how big the new array will be - // var newLength = this.length + shift; + // figure out how big the new array will be + // var newLength = this.length + shift; - //removes fields from array based on howMany needs to be removed - for( var i = index; i < +index+howMany; i++ ) { - this.__take.apply( this[index].__jq_$el ); - // this.__take.apply( $( '.jq-repeat-'+ this.__repeatId +'[jq-repeat-index="'+ ( i + index ) +'"]' ) ); - } + //removes fields from array based on howMany needs to be removed + for( var i = index; i < +index+howMany; i++ ) { + this.__take(this[index].__jq_$el, this[index], this); + // this.__take.apply( $( '.jq-repeat-'+ this.__jqRepeatId +'[jq-repeat-index="'+ ( i + index ) +'"]' ) ); + } - //re-factor element index's - for(var i = 0; i < this.length; i++){ - if( i >= index){ + //re-factor element index's + for(var i = 0; i < this.length; i++){ + if( i >= index){ - this[i].__jq_$el.attr( 'jq-repeat-index', i+shift ); - } + this[i].__jq_$el.attr( 'jq-repeat-index', i+shift ); } + } - //if there are fields to add to the array, add them - if( toAdd.length > 0 ){ - - //$.each( toAdd, function( key, value ){ - for(var I = 0; I < toAdd.length; I++){ - - //figure out new elements index - var key = I + index; - // apply values to template - var render = Mustache.render( this.__rq_template, toAdd[I] ); - - //set call name and index keys to DOM element - var $render = $( render ).addClass( 'jq-repeat-'+ this.__repeatId ).attr( 'jq-repeat-index', key ); - - - //if add new elements in proper stop, or after the place holder. - if( key === 0 ){ - $( '.jq-repeat-'+ this.__repeatId +'[jq-repeat-index="holder"]' ).after( $render ); - }else{ - $( '.jq-repeat-'+ this.__repeatId +'[jq-repeat-index="' + ( key -1 ) + '"]' ).after( $render ); - } - - Object.defineProperty( toAdd[I], "__jq_$el", { - value: $render, - writable: true, - enumerable: false, - configurable: true - } ); - - //animate element - this.__put.apply($render, [toAdd[I]]); + //if there are fields to add to the array, add them + if( toAdd.length > 0 ){ + + //$.each( toAdd, function( key, value ){ + for(var I = 0; I < toAdd.length; I++){ + + //figure out new elements index + var key = I + index; + // apply values to template + var render = Mustache.render(this.__jqTemplate, toAdd[I]); + + //set call name and index keys to DOM element + var $render = $( render ).addClass( 'jq-repeat-'+ this.__jqRepeatId ).attr( 'jq-repeat-index', key ); + + //if add new elements in proper stop, or after the place holder. + if( key === 0 ){ + this.$this.after( $render ); + }else{ + $( '.jq-repeat-'+ this.__jqRepeatId +'[jq-repeat-index="' + ( key -1 ) + '"]' ).after( $render ); } + + Object.defineProperty( toAdd[I], "__jq_$el", { + value: $render, + writable: true, + enumerable: false, + configurable: true + } ); + + //animate element + this.__put($render, toAdd[I], this); } - - //set and return new array - return Array.prototype.splice.apply(this, toProto); - }; - result.push = function(){ - //add one or more objects to the array - - //set the index value, if none is set make it zero - var index = this.length || 0; - - //loop each passed object and pass it to slice - for (var i = 0 ; i < arguments.length; ++i) { - this.splice( ( index + i ), 0, arguments[i] ); - } + } + + //set and return new array + return Array.prototype.splice.apply(this, toProto); + }; + result.push = function(){ + //add one or more objects to the array + + //set the index value, if none is set make it zero + var index = this.length || 0; + + //loop each passed object and pass it to slice + for (var i = 0 ; i < arguments.length; ++i) { + this.splice( ( index + i ), 0, arguments[i] ); + } - //return new array length - return this.length; - }; - result.pop = function(){ - //remove and return array element + //return new array length + return this.length; + }; + result.pop = function(){ + //remove and return array element - return this.splice( -1, 1 )[0]; - }; - result.reverse = function() { - var temp = this.splice( 0 ); - Array.prototype.reverse.apply( temp ); + return this.splice( -1, 1 )[0]; + }; + result.reverse = function() { + var temp = this.splice( 0 ); + Array.prototype.reverse.apply( temp ); - for( var i = 0; i < temp.length; i++ ){ - this.push( temp[i] ); - } + for( var i = 0; i < temp.length; i++ ){ + this.push( temp[i] ); + } - return this; - }; - result.shift = function() { - return this.splice( 0, 1 )[0]; - }; - result.loop = function(){ - var temp = this[0]; - this.splice( 0,1 ); - this.push( temp ); - - return temp; - }; - result.loopUp = function(){ - var temp = this[this.length-1]; - this.splice( -1, 1 ); - this.splice( 0, 0, temp ); - return temp; - }; - result.indexOf = function( key, value ){ - if( typeof value !== 'string' ){ - value = arguments[0]; - key = this.__index; - } - for ( var index = 0; index < this.length; ++index ) { - if( this[index][key] === value ){ + return this; + }; - return index; - } - } - return -1; - }; - result.update = function( key, value, update ){ - //set variables using sting for index - - // If update is called with no index/key, assume its the 0 - if(typeof key === 'object'){ - if(this[0]){ - return this.update(0, key); - } - return this.splice(0, 1, key); - } + result.remove = function(key, value){ + let index = this.indexOf(key, value) + if(index === -1) return; + this.splice(index, 1) + } - if( typeof value !== 'string' ){ - update = arguments[1]; - value = arguments[0]; - key = this.__index; - } - var index = this.indexOf( key, value ); - if(index === -1) { - return []; + result.shift = function() { + return this.splice( 0, 1 )[0]; + }; + + result.loop = function(){ + var temp = this[0]; + this.splice( 0,1 ); + this.push( temp ); + + return temp; + }; + result.loopUp = function(){ + var temp = this[this.length-1]; + this.splice( -1, 1 ); + this.splice( 0, 0, temp ); + return temp; + }; + result.indexOf = function( key, value ){ + if( typeof value !== 'string' ){ + value = arguments[0]; + key = this.__index; + } + for ( var index = 0; index < this.length; ++index ) { + if( this[index][key] === value ){ + + return index; } - var object = $.extend( true, {}, this[index], update ); - return this.splice( index, 1, object )[0]; - }; - result.__put = function(){ - this.show(); - }; - result.__take = function(){ - this.remove(); - }; - - if(!input) { - return result; } - $.each( input, function( key, value ){ - var type = typeof value; - if( type === 'object' ){ - result.push( value ); - }else if( type === 'string' ){ - Object.defineProperty( result, "__index", { - value: value, - writable: true, - enumerable: false, - configurable: true - } ); - } else if ( type === 'function'){ - Object.defineProperty( result, value.name, { - value: value, - writable: true, - enumerable: false, - configurable: true - } ); + return -1; + }; + result.update = function( key, value, update ){ + //set variables using sting for index + + // If update is called with no index/key, assume its the 0 + if(typeof key === 'object'){ + if(this[0]){ + return this.update(0, key); } - } ); + return this.splice(0, 1, key); + } - return result; + if( typeof value !== 'string' ){ + update = arguments[1]; + value = arguments[0]; + key = this.__index; + } + var index = this.indexOf( key, value ); + if(index === -1) { + return []; + } + var object = $.extend( true, {}, this[index], update ); + + var $render = $(Mustache.render(this.__jqTemplate, object)); + $render.attr('jq-repeat-index', index); + this[index].__jq_$el.replaceWith($render); + + this[index].__jq_$el = $render; + this.__update(this[index].__jq_$el, this[index], this); + }; + + result.getByKey = function(key, value){ + return this[this.indexOf(key, value)]; } + result.__put = function($el, item, list){ + $el.show(); + }; - var $this = $( element ); - var repeatId = $this.attr( 'jq-repeat' ); - var tempId = repeatId + 'Template'; - var templateId = $( '#' + tempId ).html(); + result.__take = function($el, item, list){ + $el.remove(); + }; - $this.removeAttr( 'jq-repeat' ); - var template = element.outerHTML + result.__update = function($el, item, list){ + console.log('here', $el) + $el.show(); + }; - $this.replaceWith( '