symfony-collection-js
Advanced tools
Comparing version 4.2.2 to 4.3.0-js-only
@@ -1,1 +0,1 @@ | ||
(function(){return"function"!=typeof window.CustomEvent&&void(window.CustomEvent=function(a,b){b=b||{bubbles:!1,cancelable:!1,detail:null};var c=document.createEvent("CustomEvent");return c.initCustomEvent(a,b.bubbles,b.cancelable,b.detail),c})})();var formCollection=function(a,b,c){var d,e="prototypeModified",f="addMethodCalled",g="deleteMethodCalled",h="clearMethodCalled",j="refreshAttributesMethodCalled",k=function(c,a){for(var b in a)a.hasOwnProperty(b)&&(c[b]=a[b]);return c},l=function(a){if("function"==typeof Event)return new Event(a);var b=document.createEvent("Event");return b.initEvent(a,!0,!0),b};if(b===void 0||"object"==typeof b){var m={max_elems:100,call_post_add_on_init:!1,post_add:function(a,b,c){return!0},post_delete:function(a,b,c){return!0},post_up:function(a,b,c){return!0},post_down:function(a,b,c){return!0},other_btn_add:null,btn_add_selector:".collection-add",btn_delete_selector:".collection-delete",btn_up_selector:".collection-up",btn_down_selector:".collection-down",prototype_name:"__name__"};d=k(m,b)}else if("string"==typeof b){if(-1===["add","delete","clear","refreshAttributes"].indexOf(b))return console.log("Invalid options"),!1;if("delete"===b&&void 0===c)return console.log("Missing index"),!1}a instanceof Node&&(a=[a]);for(var o,p=0;p<a.length;p++){switch(o=a[p],b){case"add":return void o.dispatchEvent(l(f));break;case"delete":return void o.dispatchEvent(new CustomEvent(g,{detail:c}));break;case"clear":return void o.dispatchEvent(l(h));break;case"refreshAttributes":return void o.dispatchEvent(new CustomEvent(j,{detail:c}));}var q=o.getAttribute("data-prototype"),r=o.children.length,s=[];o.addEventListener(e,function(a){a.target!==a.currentTarget||(s=[],q=this.getAttribute("data-prototype"),w(),A(0))}),o.addEventListener(f,function(a){G(formCollection.POST_ADD_CONTEXT.ADD_METHOD)}),o.addEventListener(g,function(a){var b=a.detail,c=o.children[b];H(c),d.post_delete(c,formCollection.POST_DELETE_CONTEXT.DELETE_METHOD,b)}),o.addEventListener(h,function(a){o.textContent="",r=0}),o.addEventListener(j,function(a){var b=a.detail;A(b)});var t=function(a,b){var c={path:a,attributes:b};return c},u=function(a){var b=document.createElement("div");return b.innerHTML=a.trim(),b.firstChild},v=function(a,b){var c=y(a,d.prototype_name);if(0<Object.keys(c).length&&s.push(t(b,c)),!("data-prototype"in c))for(var e=a.children,f=0;f<e.length;f++)v(e[f],b.concat([f]))},w=function(){var a=u(q);v(a,[])},x=function(a){for(var b=a.querySelectorAll(d.btn_add_selector),c=0;c<b.length;c++)b[c].addEventListener("click",function(){var b=F(a);d.post_add(b,formCollection.POST_ADD_CONTEXT.BTN_ADD,C(b))});for(var e=a.querySelectorAll(d.btn_delete_selector),c=0;c<e.length;c++)e[c].addEventListener("click",function(){var b=C(a);H(a),d.post_delete(a,formCollection.POST_DELETE_CONTEXT.BTN_DELETE,b)});for(var f=a.querySelectorAll(d.btn_up_selector),c=0;c<f.length;c++)f[c].addEventListener("click",function(){var b=C(a),c=I(a);c&&d.post_up(a,c,b)});for(var g=a.querySelectorAll(d.btn_down_selector),c=0;c<g.length;c++)g[c].addEventListener("click",function(){var b=C(a),c=J(a);c&&d.post_down(a,c,b)})},y=function(a,b){for(var c,d={},e=0;e<a.attributes.length;e++)c=a.attributes[e],c.value&&-1!==c.value.indexOf(b)&&(d[c.name]=c.value);return d},z=function(a,b){for(var c=new RegExp(d.prototype_name,"g"),f=0;f<s.length;f++){for(var g,h=s[f],k=a,m=0;m<h.path.length;m++)g=h.path[m],k=k.children[g];for(var n=Object.keys(h.attributes),m=0;m<n.length;m++){var o=n[m],p=h.attributes[o];k.setAttribute(o,p.replace(c,b))}"data-prototype"in k.attributes&&k.dispatchEvent(l(e))}},A=function(a){for(var b=o.children,c=a;c<b.length;c++)z(b[c],c)},B=function(a){void 0===a&&(a=r);var b=q,c=new RegExp(d.prototype_name,"g");b=b.replace(c,a);var e=u(b);return x(e),e},C=function(a){for(var b=0;null!=(a=a.previousElementSibling);)b++;return b},D=function(a,b){a.insertAdjacentElement("beforebegin",b)},E=function(a,b){a.insertAdjacentElement("afterend",b)},F=function(a){if(r>=d.max_elems)return!1;var b=B(C(a)+1);return E(a,b),r++,A(C(a)+2),b},G=function(a){if(r>=d.max_elems)return!1;var b=B();o.appendChild(b),r++,d.post_add(b,a,r-1)},H=function(a){var b=C(a);a.parentNode.removeChild(a),r--,A(b)},I=function(a){var b=a.previousElementSibling;if(!b)return!1;var c=C(b);return D(b,a),z(a,c),z(b,c+1),b},J=function(a){var b=a.nextElementSibling;if(!b)return!1;var c=C(b);return E(b,a),z(a,c),z(b,c-1),b},K=function(){for(var a,b=0;b<o.children.length;b++)a=o.children[b],x(a),d.call_post_add_on_init&&d.post_add(a,formCollection.POST_ADD_CONTEXT.INIT,b)};if(K(),w(),d.other_btn_add){var L=null;if("string"==typeof d.other_btn_add?L=document.querySelectorAll(d.other_btn_add):d.other_btn_add instanceof Node?L=[d.other_btn_add]:formCollection.jQuery&&d.other_btn_add instanceof formCollection.jQuery||d.other_btn_add instanceof NodeList?L=d.other_btn_add:console.log("other_btn_add: bad value, can be a selector or nodes, or a jQuery object."),L)for(var p=0;p<L.length;p++)L[p].addEventListener("click",function(){G(formCollection.POST_ADD_CONTEXT.OTHER_BTN_ADD)})}}};formCollection.POST_ADD_CONTEXT={BTN_ADD:4,OTHER_BTN_ADD:8,INIT:15,ADD_METHOD:16},formCollection.POST_DELETE_CONTEXT={BTN_DELETE:23,DELETE_METHOD:42},formCollection.jQuery=null,function(a,b){"function"==typeof define&&define.amd?define(["jquery"],b):"object"==typeof module&&module.exports?module.exports=b(require("jquery")):"undefined"==typeof jQuery?a.returnExports=b():a.returnExports=b(jQuery)}(this,function(a){return"undefined"!=typeof jQuery&&jQuery&&(formCollection.jQuery=a,a.fn.formCollection=function(b,c){for(var d=[],e=0;e<this.length;e++)d.push(this[e]);var f=formCollection(d,b,c);return Array.isArray(f)?a(this):f}),formCollection}); | ||
(function(){return"function"!=typeof window.CustomEvent&&void(window.CustomEvent=function(a,b){b=b||{bubbles:!1,cancelable:!1,detail:null};let c=document.createEvent("CustomEvent");return c.initCustomEvent(a,b.bubbles,b.cancelable,b.detail),c})})();let formCollection=function(a,b,c){let d,e="prototypeModified",f="addMethodCalled",g="deleteMethodCalled",h="clearMethodCalled",j="refreshAttributesMethodCalled",k=function(c,a){for(let b in a)a.hasOwnProperty(b)&&(c[b]=a[b]);return c},l=function(a){if("function"==typeof Event)return new Event(a);let b=document.createEvent("Event");return b.initEvent(a,!0,!0),b};if(b===void 0||"object"==typeof b){d=k({max_elems:100,call_pre_add_on_init:!1,call_post_add_on_init:!1,pre_add:function(){return!0},post_add:function(){return!0},pre_delete:function(){return!0},post_delete:function(){return!0},pre_up:function(){return!0},post_up:function(){return!0},pre_down:function(){return!0},post_down:function(){return!0},other_btn_add:null,btn_add_selector:".collection-add",btn_delete_selector:".collection-delete",btn_up_selector:".collection-up",btn_down_selector:".collection-down",prototype_name:"__name__"},b)}else if("string"==typeof b){if(-1===["add","delete","clear","refreshAttributes"].indexOf(b))return console.error("Invalid options"),!1;if("delete"===b&&void 0===c)return console.error("Missing index"),!1}a instanceof Node&&(a=[a]);for(let k,m=0;m<a.length;m++){switch(k=a[m],b){case"add":return void k.dispatchEvent(l(f));break;case"delete":return void k.dispatchEvent(new CustomEvent(g,{detail:c}));break;case"clear":return void k.dispatchEvent(l(h));break;case"refreshAttributes":return void k.dispatchEvent(new CustomEvent(j,{detail:c}));}let i=k.getAttribute("data-prototype"),o=k.children.length,n=[];k.addEventListener(e,function(a){a.target!==a.currentTarget||(n=[],i=this.getAttribute("data-prototype"),s(),w(0))}),k.addEventListener(f,function(a){C(formCollection.ADD_CONTEXT.ADD_METHOD)}),k.addEventListener(g,function(a){let b=a.detail,c=k.children[b];!1===d.pre_delete(c,formCollection.DELETE_CONTEXT.DELETE_METHOD,b)||(D(c),d.post_delete(c,formCollection.DELETE_CONTEXT.DELETE_METHOD,b))}),k.addEventListener(h,function(a){k.textContent="",o=0}),k.addEventListener(j,function(a){let b=a.detail;w(b)});let p=function(a,b){let c={path:a,attributes:b};return c},q=function(a){let b=document.createElement("div");return b.innerHTML=a.trim(),b.firstChild},r=function(a,b){let c=u(a,d.prototype_name);if(0<Object.keys(c).length&&n.push(p(b,c)),!("data-prototype"in c)){let c=a.children;for(let a=0;a<c.length;a++)r(c[a],b.concat([a]))}},s=function(){let a=q(i);r(a,[])},t=function(a){let b=a.querySelectorAll(d.btn_add_selector);for(let c=0;c<b.length;c++)b[c].addEventListener("click",function(){let b=y(a)+1;if(!1!==d.pre_add(formCollection.ADD_CONTEXT.BTN_ADD,b)){let c=B(a);d.post_add(c,formCollection.ADD_CONTEXT.BTN_ADD,b)}});let c=a.querySelectorAll(d.btn_delete_selector);for(let b=0;b<c.length;b++)c[b].addEventListener("click",function(){let b=y(a);!1===d.pre_delete(a,formCollection.DELETE_CONTEXT.BTN_DELETE,b)||(D(a),d.post_delete(a,formCollection.DELETE_CONTEXT.BTN_DELETE,b))});let e=a.querySelectorAll(d.btn_up_selector);for(let b=0;b<e.length;b++)e[b].addEventListener("click",function(){let b=y(a),c=a.previousElementSibling;c&&!1!==d.pre_up(a,c,b)&&(c=E(a),c&&d.post_up(a,c,b))});let f=a.querySelectorAll(d.btn_down_selector);for(let b=0;b<f.length;b++)f[b].addEventListener("click",function(){let b=y(a),c=a.nextElementSibling;c&&!1!==d.pre_down(a,c,b)&&(c=F(a),c&&d.post_down(a,c,b))})},u=function(a,b){let c={};for(let d,e=0;e<a.attributes.length;e++)d=a.attributes[e],d.value&&-1!==d.value.indexOf(b)&&(c[d.name]=d.value);return c},v=function(a,b){let c=new RegExp(d.prototype_name,"g");for(let d=0;d<n.length;d++){let f=n[d],g=a;for(let a,b=0;b<f.path.length;b++)a=f.path[b],g=g.children[a];let h=Object.keys(f.attributes);for(let a=0;a<h.length;a++){let d=h[a],e=f.attributes[d];g.setAttribute(d,e.replace(c,b))}"data-prototype"in g.attributes&&g.dispatchEvent(l(e))}},w=function(a){let b=k.children;for(let c=a;c<b.length;c++)v(b[c],c)},x=function(a){void 0===a&&(a=o);let b=i,c=new RegExp(d.prototype_name,"g");b=b.replace(c,a);let e=q(b);return t(e),e},y=function(a){let b=0;for(;null!=(a=a.previousElementSibling);)b++;return b},z=function(a,b){a.insertAdjacentElement("beforebegin",b)},A=function(a,b){a.insertAdjacentElement("afterend",b)},B=function(a){if(o>=d.max_elems)return!1;let b=x(y(a)+1);return A(a,b),o++,w(y(a)+2),b},C=function(a){if(o>=d.max_elems)return!1;if(!1!==d.pre_add(a,o)){let b=x();k.appendChild(b),o++,d.post_add(b,a,o-1)}},D=function(a){let b=y(a);a.parentNode.removeChild(a),o--,w(b)},E=function(a){let b=a.previousElementSibling;if(!b)return!1;let c=y(b);return z(b,a),v(a,c),v(b,c+1),b},F=function(a){let b=a.nextElementSibling;if(!b)return!1;let c=y(b);return A(b,a),v(a,c),v(b,c-1),b},G=function(){for(let a=0;a<k.children.length;a++){d.call_pre_add_on_init&&d.pre_add(formCollection.ADD_CONTEXT.INIT,a);let b=k.children[a];t(b),d.call_post_add_on_init&&d.post_add(b,formCollection.ADD_CONTEXT.INIT,a)}};if(G(),s(),d.other_btn_add){let a=null;if("string"==typeof d.other_btn_add?a=document.querySelectorAll(d.other_btn_add):d.other_btn_add instanceof Node?a=[d.other_btn_add]:formCollection.jQuery&&d.other_btn_add instanceof formCollection.jQuery||d.other_btn_add instanceof NodeList?a=d.other_btn_add:console.error("other_btn_add: bad value, can be a selector or nodes, or a jQuery object."),a)for(let b=0;b<a.length;b++)a[b].addEventListener("click",function(){C(formCollection.ADD_CONTEXT.OTHER_BTN_ADD)})}}};formCollection.ADD_CONTEXT={BTN_ADD:4,OTHER_BTN_ADD:8,INIT:15,ADD_METHOD:16},formCollection.DELETE_CONTEXT={BTN_DELETE:23,DELETE_METHOD:42},formCollection.POST_ADD_CONTEXT=formCollection.ADD_CONTEXT,formCollection.POST_DELETE_CONTEXT=formCollection.DELETE_CONTEXT,function(a,b){"function"==typeof define&&define.amd?define([],b):"object"==typeof module&&module.exports?module.exports=b():a.returnExports=b()}(this,function(){return formCollection}); |
@@ -44,2 +44,3 @@ // Karma configuration | ||
coverageReporter: { | ||
type : 'html', | ||
dir : 'coverage/without_jquery/', | ||
@@ -102,2 +103,2 @@ reporters: [ | ||
}) | ||
} | ||
} |
{ | ||
"name": "symfony-collection-js", | ||
"version": "4.2.2", | ||
"version": "4.3.0-js-only", | ||
"description": "A plugin working with and without jquery to dynamically create elements of a symfony form collection.", | ||
@@ -5,0 +5,0 @@ "main": "symfonyCollectionJs.js", |
@@ -1,2 +0,2 @@ | ||
# symfonyCollectionJs ![GitHub](https://img.shields.io/github/license/ruano-a/symfonyCollectionJs) ![Maintenance](https://img.shields.io/maintenance/yes/2022) ![GitHub last commit](https://img.shields.io/github/last-commit/ruano-a/symfonyCollectionJs) ![npm](https://img.shields.io/npm/dm/symfony-collection-js?label=npm%20downloads) [![](https://data.jsdelivr.com/v1/package/npm/symfony-collection-js/badge)](https://www.jsdelivr.com/package/npm/symfony-collection-js) [![codecov](https://codecov.io/gh/ruano-a/symfonyCollectionJs/branch/master/graph/badge.svg?token=Z93Y3NTP1Q)](https://codecov.io/gh/ruano-a/symfonyCollectionJs) ![npm bundle size](https://img.shields.io/bundlephobia/min/symfony-collection-js) ![Dependencies](https://badgen.net/bundlephobia/dependency-count/symfony-collection-js) ![Badge count](https://img.shields.io/badge/badge%20count-enough%20%3C3-blue) | ||
# symfonyCollectionJs ![GitHub](https://img.shields.io/github/license/ruano-a/symfonyCollectionJs) ![Maintenance](https://img.shields.io/maintenance/yes/2022) ![GitHub last commit](https://img.shields.io/github/last-commit/ruano-a/symfonyCollectionJs) ![npm](https://img.shields.io/npm/dm/symfony-collection-js?label=npm%20downloads) [![](https://data.jsdelivr.com/v1/package/npm/symfony-collection-js/badge)](https://www.jsdelivr.com/package/npm/symfony-collection-js) [![codecov](https://codecov.io/gh/ruano-a/symfonyCollectionJs/branch/master-js-only/graph/badge.svg?token=Z93Y3NTP1Q)](https://codecov.io/gh/ruano-a/symfonyCollectionJs) ![npm bundle size](https://img.shields.io/bundlephobia/min/symfony-collection-js) ![Dependencies](https://badgen.net/bundlephobia/dependency-count/symfony-collection-js) ![Badge count](https://img.shields.io/badge/badge%20count-enough%20%3C3-blue) | ||
A plugin working with and without jquery to dynamically create elements of a symfony form collection. | ||
@@ -19,10 +19,10 @@ | ||
```html | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/symfonyCollectionJs/4.2.2/symfonyCollectionJs.min.js" integrity="sha512-qpIx6aHqQROnCNHHFS+Iy/XwPltKFouhUaCkmV6ezBx9BDn0hEKNZ/MOxiDbh/DV+YO5y213L+3Yy3ELuS1pFw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/symfonyCollectionJs/4.2.2-js-only/symfonyCollectionJs.min.js" integrity="sha512-n4/PStbGMF9UgqPuBeV0rWFP4A2pniUXzanDcxKYXe0oYeokYIK7wkoYcG/KoDDrXjGqX24LgTNPD5lzck74QQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> | ||
``` | ||
jsDelivr | ||
```html | ||
<script src="https://cdn.jsdelivr.net/npm/symfony-collection-js@4.2.2/symfonyCollectionJs.js" integrity="sha256-TqiIwHEuIWW+oaCkji48jcRSk9//MR0xMkku7jr47rg=" crossorigin="anonymous"></script> | ||
<script src="https://cdn.jsdelivr.net/npm/symfony-collection-js@4.2.2-js-only/dist/symfonyCollectionJs.js" integrity="sha256-9TfQnYOT8TpalGxz6TzhiggYuWade7TlqqhKBMTs2IE=" crossorigin="anonymous"></script> | ||
``` | ||
# Basic usage (Check [here](#can-i-use-this-package-without-symfony) to use without symfony) | ||
# Basic usage (Check [here](#can-i-use-this-package-without-symfony-) to use without symfony) | ||
@@ -53,6 +53,11 @@ Your collection container should have the prototype mentioned in the symfony documentation, and an id or a class. So in your form type: | ||
max_elems: 100, | ||
call_pre_add_on_init: false, | ||
call_post_add_on_init: false, | ||
pre_add: function(context, index) { return true; }, | ||
post_add: function(new_elem, context, index) { return true; }, | ||
pre_delete: function(delete_elem, context, index) { return true; }, | ||
post_delete: function(delete_elem, context, index) { return true; }, | ||
pre_up: function(elem, switched_elem, index) { return true; }, | ||
post_up: function(elem, switched_elem, index) { return true; }, | ||
pre_down: function(elem, switched_elem, index) { return true; }, | ||
post_down: function(elem, switched_elem, index) { return true; }, | ||
@@ -67,3 +72,3 @@ other_btn_add: null, | ||
~~~~ | ||
In post_up and post_down, switched_elem is the moved elem that the user didn't click on. | ||
In pre_up, post_up, pre_down and post_down, switched_elem is the moved elem that the user didn't click on. | ||
prototype_name should probably be changed if you use nested collection (in the FormType too, with the same value). | ||
@@ -89,3 +94,3 @@ | ||
Clear every element (doesn't call post_delete): | ||
Clear every element (doesn't call pre_delete nor post_delete): | ||
~~~~ | ||
@@ -104,5 +109,5 @@ $('.collection').formCollection('clear'); // with jQuery | ||
The context argument in post_add and post_delete will have one of these values, depending on how it's called: | ||
The context argument in pre_add, post_add, pre_delete, and post_delete will have one of these values, depending on how it's called: | ||
~~~~ | ||
formCollection.POST_ADD_CONTEXT = { | ||
formCollection.ADD_CONTEXT = { | ||
BTN_ADD: 4, | ||
@@ -113,3 +118,3 @@ OTHER_BTN_ADD: 8, | ||
}; | ||
formCollection.POST_DELETE_CONTEXT = { | ||
formCollection.DELETE_CONTEXT = { | ||
BTN_DELETE: 23, | ||
@@ -120,2 +125,4 @@ DELETE_METHOD: 42 | ||
If pre_add, pre_delete, pre_up, pre_down return false, the operation (add, delete, up, down) isn't executed (for pre_add, the return doesn't affect the initialization of existing elements). | ||
# How to start the tests | ||
@@ -127,9 +134,4 @@ | ||
Yes ! in the example folder, with and without jQuery, with and without loader. | ||
Yes! in the example folder, with and without jQuery, with and without loader. | ||
# Can I use this package without symfony? | ||
Absolutely, you only need to have the data-prototype attribute properly set. | ||
We provide you with [this example](./example/simple_collection_example_without_symfony.php) in php, but you can do this in every language, and most likely with most frameworks. | ||
# Is there a Symfony UX integration? | ||
@@ -143,2 +145,7 @@ | ||
# Can I use this package without symfony? | ||
Absolutely, you only need to have the data-prototype attribute properly set. | ||
We provide you with [this example](./example/simple_collection_example_without_symfony.php) in php, but you can do this in every language, and most likely with most frameworks. | ||
# Notes | ||
@@ -145,0 +152,0 @@ If you're using this without jQuery, but with a loader (AMD, CommonJS, or anything), you MUST use a version on a branch / tag with "js-only" in the name! Otherwise it WILL NOT BUILD! (I didn't want to make several versions but tests ended showing that it was the best choice... Unless you have a better idea?) |
@@ -8,3 +8,3 @@ // Polyfill from https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent | ||
params = params || { bubbles: false, cancelable: false, detail: null }; | ||
var evt = document.createEvent( 'CustomEvent' ); | ||
let evt = document.createEvent( 'CustomEvent' ); | ||
evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail ); | ||
@@ -17,12 +17,12 @@ return evt; | ||
var formCollection = function(nodeList, options, param) { | ||
var settings; | ||
var eventPrototypeModified = 'prototypeModified'; | ||
var eventAddMethodCalled = 'addMethodCalled'; | ||
var eventDeleteMethodCalled = 'deleteMethodCalled'; | ||
var eventClearMethodCalled = 'clearMethodCalled'; | ||
var eventRefreshAttributesMethodCalled = 'refreshAttributesMethodCalled'; | ||
let formCollection = function(nodeList, options, param) { | ||
let settings; | ||
let eventPrototypeModified = 'prototypeModified'; | ||
let eventAddMethodCalled = 'addMethodCalled'; | ||
let eventDeleteMethodCalled = 'deleteMethodCalled'; | ||
let eventClearMethodCalled = 'clearMethodCalled'; | ||
let eventRefreshAttributesMethodCalled = 'refreshAttributesMethodCalled'; | ||
var extend = function (a, b) { | ||
for (var key in b) { | ||
let extend = function (a, b) { | ||
for (let key in b) { | ||
if (b.hasOwnProperty(key)) { | ||
@@ -35,7 +35,7 @@ a[key] = b[key]; | ||
var getEvent = function(eventName) { | ||
let getEvent = function(eventName) { | ||
if (typeof(Event) === 'function') { | ||
return new Event(eventName); | ||
} | ||
var event = document.createEvent('Event'); | ||
let event = document.createEvent('Event'); | ||
event.initEvent(eventName, true, true); | ||
@@ -46,14 +46,27 @@ return event; | ||
if (options === undefined || typeof options === 'object') { | ||
var defaults = { | ||
let defaults = { | ||
max_elems: 100, | ||
call_pre_add_on_init: false, | ||
call_post_add_on_init: false, | ||
pre_add: function(context, index) { | ||
return true; | ||
}, | ||
post_add: function(new_elem, context, index) { | ||
return true; | ||
}, | ||
pre_delete: function(delete_elem, context, index) { | ||
return true; | ||
}, | ||
post_delete: function(delete_elem, context, index) { | ||
return true; | ||
}, | ||
pre_up: function(elem, switched_elem, index) { | ||
return true; | ||
}, | ||
post_up: function(elem, switched_elem, index) { | ||
return true; | ||
}, | ||
pre_down: function(elem, switched_elem, index) { | ||
return true; | ||
}, | ||
post_down: function(elem, switched_elem, index) { | ||
@@ -72,6 +85,6 @@ return true; | ||
if (['add', 'delete', 'clear', 'refreshAttributes'].indexOf(options) === -1) { | ||
console.log('Invalid options'); | ||
console.error('Invalid options'); | ||
return false; | ||
} else if (options === 'delete' && param === undefined) { | ||
console.log('Missing index'); | ||
console.error('Missing index'); | ||
return false; | ||
@@ -83,4 +96,4 @@ } | ||
// at this point nodeList is either a real NodeList, or an array | ||
for (var i = 0; i < nodeList.length; i++) { | ||
var collection_root = nodeList[i]; | ||
for (let i = 0; i < nodeList.length; i++) { | ||
let collection_root = nodeList[i]; | ||
@@ -105,5 +118,5 @@ switch (options) { // particular case, so it's better to have it at the top and forget it | ||
} | ||
var prototype = collection_root.getAttribute('data-prototype'); | ||
var n = collection_root.children.length; | ||
var needed_data_for_update = []; | ||
let prototype = collection_root.getAttribute('data-prototype'); | ||
let n = collection_root.children.length; | ||
let needed_data_for_update = []; | ||
@@ -124,14 +137,16 @@ /* triggered by a parent collection if this collection is a subcollection */ | ||
*/ | ||
collection_root.addEventListener(eventAddMethodCalled, function(e){ | ||
add_elem_bottom(formCollection.POST_ADD_CONTEXT.ADD_METHOD); | ||
collection_root.addEventListener(eventAddMethodCalled, function(e){ | ||
add_elem_bottom(formCollection.ADD_CONTEXT.ADD_METHOD); | ||
}); | ||
collection_root.addEventListener(eventDeleteMethodCalled, function(e){ | ||
var param = e.detail; | ||
var elem = collection_root.children[param]; | ||
collection_root.addEventListener(eventDeleteMethodCalled, function(e){ | ||
let param = e.detail; | ||
let elem = collection_root.children[param]; | ||
if (settings.pre_delete(elem, formCollection.DELETE_CONTEXT.DELETE_METHOD, param) === false) | ||
return; | ||
delete_elem(elem); | ||
settings.post_delete(elem, formCollection.POST_DELETE_CONTEXT.DELETE_METHOD, param); | ||
settings.post_delete(elem, formCollection.DELETE_CONTEXT.DELETE_METHOD, param); | ||
}); | ||
collection_root.addEventListener(eventClearMethodCalled, function(e){ | ||
collection_root.addEventListener(eventClearMethodCalled, function(e){ | ||
collection_root.textContent = ""; //innerHTML has a bug on IE, and is slower anyway | ||
@@ -141,9 +156,9 @@ n = 0; | ||
collection_root.addEventListener(eventRefreshAttributesMethodCalled, function(e){ | ||
var param = e.detail; | ||
collection_root.addEventListener(eventRefreshAttributesMethodCalled, function(e){ | ||
let param = e.detail; | ||
update_indexes_from(param); | ||
}); | ||
var build_node_needed_data_for_update = function(path, attributes) { | ||
var obj = { | ||
let build_node_needed_data_for_update = function(path, attributes) { | ||
let obj = { | ||
path: path, | ||
@@ -155,4 +170,4 @@ attributes: attributes | ||
var createNode = function(html) { // equivalent of JQuery(html) | ||
var div = document.createElement('div'); | ||
let createNode = function(html) { // equivalent of JQuery(html) | ||
let div = document.createElement('div'); | ||
div.innerHTML = html.trim(); | ||
@@ -183,5 +198,5 @@ | ||
*/ | ||
var inspect_model_tree = function(modelNode, currentPath) { | ||
let inspect_model_tree = function(modelNode, currentPath) { | ||
/* First the root, simple (if it's a wrapper there should be nothing, but it can be an input too) */ | ||
var attrs = getAttributesWithThisValue(modelNode, settings.prototype_name); // get attributes with placeholders | ||
let attrs = getAttributesWithThisValue(modelNode, settings.prototype_name); // get attributes with placeholders | ||
if (Object.keys(attrs).length > 0) { | ||
@@ -194,4 +209,4 @@ /* the path is an empty array for the root node */ | ||
/* Then we need to traverse */ | ||
var modelNodeChilds = modelNode.children; | ||
for (var i = 0; i < modelNodeChilds.length; i++) { | ||
let modelNodeChilds = modelNode.children; | ||
for (let i = 0; i < modelNodeChilds.length; i++) { | ||
inspect_model_tree(modelNodeChilds[i], currentPath.concat([i]));//concat creates a new array | ||
@@ -201,4 +216,4 @@ } | ||
var init_needed_data_for_update = function() { | ||
var modelElement = createNode(prototype); | ||
let init_needed_data_for_update = function() { | ||
let modelElement = createNode(prototype); | ||
inspect_model_tree(modelElement, []); | ||
@@ -208,24 +223,32 @@ }; | ||
// note : don't calculate the index outside the listeners | ||
var init_elem_listeners = function(elem) { | ||
var btnAdds = elem.querySelectorAll(settings.btn_add_selector); | ||
for (var i = 0; i < btnAdds.length; i++) { | ||
let init_elem_listeners = function(elem) { | ||
let btnAdds = elem.querySelectorAll(settings.btn_add_selector); | ||
for (let i = 0; i < btnAdds.length; i++) { | ||
btnAdds[i].addEventListener('click', function() { | ||
var new_elem = add_elem_down(elem); | ||
settings.post_add(new_elem, formCollection.POST_ADD_CONTEXT.BTN_ADD, sibling_index(new_elem)); | ||
let index = sibling_index(elem) + 1; | ||
if (settings.pre_add(formCollection.ADD_CONTEXT.BTN_ADD, index) === false) | ||
return; | ||
let new_elem = add_elem_down(elem); | ||
settings.post_add(new_elem, formCollection.ADD_CONTEXT.BTN_ADD, index); | ||
}); | ||
} | ||
var btnDeletes = elem.querySelectorAll(settings.btn_delete_selector); | ||
for (var i = 0; i < btnDeletes.length; i++) { | ||
let btnDeletes = elem.querySelectorAll(settings.btn_delete_selector); | ||
for (let i = 0; i < btnDeletes.length; i++) { | ||
btnDeletes[i].addEventListener('click', function() { | ||
var index = sibling_index(elem); | ||
let index = sibling_index(elem); | ||
if (settings.pre_delete(elem, formCollection.DELETE_CONTEXT.BTN_DELETE, index) === false) | ||
return; | ||
delete_elem(elem); | ||
settings.post_delete(elem, formCollection.POST_DELETE_CONTEXT.BTN_DELETE, index); | ||
settings.post_delete(elem, formCollection.DELETE_CONTEXT.BTN_DELETE, index); | ||
}); | ||
} | ||
var btnUps = elem.querySelectorAll(settings.btn_up_selector); | ||
for (var i = 0; i < btnUps.length; i++) { | ||
let btnUps = elem.querySelectorAll(settings.btn_up_selector); | ||
for (let i = 0; i < btnUps.length; i++) { | ||
btnUps[i].addEventListener('click', function() { | ||
var index = sibling_index(elem); | ||
var switched_elem = move_elem_up(elem); | ||
if (switched_elem) { | ||
let index = sibling_index(elem); | ||
let switched_elem = elem.previousElementSibling; // previousSibling finds some invisible text elements | ||
if (!switched_elem || settings.pre_up(elem, switched_elem, index) === false) | ||
return; | ||
switched_elem = move_elem_up(elem); | ||
if (switched_elem) { // should always be true, but I prefer to keep it | ||
settings.post_up(elem, switched_elem, index); | ||
@@ -235,8 +258,11 @@ } | ||
} | ||
var btnDowns = elem.querySelectorAll(settings.btn_down_selector); | ||
for (var i = 0; i < btnDowns.length; i++) { | ||
let btnDowns = elem.querySelectorAll(settings.btn_down_selector); | ||
for (let i = 0; i < btnDowns.length; i++) { | ||
btnDowns[i].addEventListener('click', function() { | ||
var index = sibling_index(elem); | ||
var switched_elem = move_elem_down(elem); | ||
if (switched_elem) { | ||
let index = sibling_index(elem); | ||
let switched_elem = elem.nextElementSibling; // nextSibling finds some invisible text elements | ||
if (!switched_elem || settings.pre_down(elem, switched_elem, index) === false) | ||
return; | ||
switched_elem = move_elem_down(elem); | ||
if (switched_elem) { // should always be true, but I prefer to keep it | ||
settings.post_down(elem, switched_elem, index); | ||
@@ -248,6 +274,6 @@ } | ||
var getAttributesWithThisValue = function(elem, value) { | ||
var result = {}; | ||
for (var i = 0; i < elem.attributes.length; i++) { | ||
var attr = elem.attributes[i]; | ||
let getAttributesWithThisValue = function(elem, value) { | ||
let result = {}; | ||
for (let i = 0; i < elem.attributes.length; i++) { | ||
let attr = elem.attributes[i]; | ||
if (attr.value && attr.value.indexOf(value) !== -1) { | ||
@@ -260,17 +286,17 @@ result[attr.name] = attr.value; | ||
var update_index = function(elem, index) { | ||
let update_index = function(elem, index) { | ||
/* without regexp, replace only replaces the first occurrence */ | ||
var prototypeNameRegexp = new RegExp(settings.prototype_name, 'g'); | ||
for (var i = 0; i < needed_data_for_update.length; i++) { | ||
var nodeData = needed_data_for_update[i]; | ||
var node = elem; | ||
for (var j = 0; j < nodeData.path.length; j++) { // we follow the path | ||
var childIndex = nodeData.path[j]; | ||
let prototypeNameRegexp = new RegExp(settings.prototype_name, 'g'); | ||
for (let i = 0; i < needed_data_for_update.length; i++) { | ||
let nodeData = needed_data_for_update[i]; | ||
let node = elem; | ||
for (let j = 0; j < nodeData.path.length; j++) { // we follow the path | ||
let childIndex = nodeData.path[j]; | ||
node = node.children[childIndex]; | ||
}; | ||
//now we have the right node | ||
var attributesNames = Object.keys(nodeData.attributes); | ||
for (var j = 0; j < attributesNames.length; j++) { | ||
var name = attributesNames[j]; | ||
var value = nodeData.attributes[name]; //value has a placeholder | ||
let attributesNames = Object.keys(nodeData.attributes); | ||
for (let j = 0; j < attributesNames.length; j++) { | ||
let name = attributesNames[j]; | ||
let value = nodeData.attributes[name]; //value has a placeholder | ||
node.setAttribute(name, value.replace(prototypeNameRegexp, index)); | ||
@@ -284,5 +310,5 @@ }; | ||
// if i > to the max index, it doesn't cause problems | ||
var update_indexes_from = function(i) { | ||
var elements = collection_root.children; | ||
for (var j = i; j < elements.length; j++) { | ||
let update_indexes_from = function(i) { | ||
let elements = collection_root.children; | ||
for (let j = i; j < elements.length; j++) { | ||
update_index(elements[j], j); | ||
@@ -292,10 +318,10 @@ } | ||
var create_elem = function(index) { | ||
let create_elem = function(index) { | ||
if (index === undefined) | ||
index = n; | ||
var newFormHtml = prototype; // we create an elem with the prototype, but placeholders must be replaced | ||
var prototypeNameRegexp = new RegExp(settings.prototype_name, 'g'); | ||
let newFormHtml = prototype; // we create an elem with the prototype, but placeholders must be replaced | ||
let prototypeNameRegexp = new RegExp(settings.prototype_name, 'g'); | ||
//won't replace the ones in data since we put an alias | ||
newFormHtml = newFormHtml.replace(prototypeNameRegexp, index); | ||
var newForm = createNode(newFormHtml); | ||
let newForm = createNode(newFormHtml); | ||
init_elem_listeners(newForm); | ||
@@ -305,4 +331,4 @@ return newForm; | ||
var sibling_index = function(node) { | ||
var i = 0; | ||
let sibling_index = function(node) { | ||
let i = 0; | ||
while ((node = node.previousElementSibling) != null) { //previousSibling finds some invisible text elements | ||
@@ -314,3 +340,3 @@ i++; | ||
var insert_before = function (node, toInsert) { | ||
let insert_before = function (node, toInsert) { | ||
// Only supported for HTMLElement, not all Element objects, such as SVGElement. | ||
@@ -320,3 +346,3 @@ node.insertAdjacentElement('beforebegin', toInsert); | ||
var insert_after = function (node, toInsert) { | ||
let insert_after = function (node, toInsert) { | ||
// Only supported for HTMLElement, not all Element objects, such as SVGElement. | ||
@@ -326,6 +352,6 @@ node.insertAdjacentElement('afterend', toInsert); | ||
var add_elem_down = function(elem) { | ||
let add_elem_down = function(elem) { | ||
if (n >= settings.max_elems) | ||
return false; | ||
var new_elem = create_elem(sibling_index(elem) + 1); | ||
let new_elem = create_elem(sibling_index(elem) + 1); | ||
insert_after(elem, new_elem); | ||
@@ -337,6 +363,8 @@ n++; | ||
var add_elem_bottom = function(context) { | ||
let add_elem_bottom = function(context) { | ||
if (n >= settings.max_elems) | ||
return false; | ||
var new_elem = create_elem(); | ||
if (settings.pre_add(context, n) === false) | ||
return; | ||
let new_elem = create_elem(); | ||
collection_root.appendChild(new_elem); | ||
@@ -347,4 +375,4 @@ n++; | ||
var delete_elem = function(elem) { | ||
var index = sibling_index(elem); | ||
let delete_elem = function(elem) { | ||
let index = sibling_index(elem); | ||
elem.parentNode.removeChild(elem); | ||
@@ -355,7 +383,7 @@ n--; | ||
var move_elem_up = function(elem) { | ||
var prev = elem.previousElementSibling; //previousSibling finds some invisible text elements | ||
let move_elem_up = function(elem) { | ||
let prev = elem.previousElementSibling; //previousSibling finds some invisible text elements | ||
if (!prev) | ||
return false; | ||
var newIndex = sibling_index(prev); | ||
let newIndex = sibling_index(prev); | ||
insert_before(prev, elem); | ||
@@ -368,7 +396,7 @@ update_index(elem, newIndex); | ||
var move_elem_down = function(elem) { | ||
var next = elem.nextElementSibling; //nextSibling finds some invisible text elements | ||
let move_elem_down = function(elem) { | ||
let next = elem.nextElementSibling; //nextSibling finds some invisible text elements | ||
if (!next) | ||
return false; | ||
var newIndex = sibling_index(next); | ||
let newIndex = sibling_index(next); | ||
insert_after(next, elem); | ||
@@ -381,8 +409,14 @@ update_index(elem, newIndex); | ||
var init_existing = function() { | ||
for (var i = 0; i < collection_root.children.length; i++) { | ||
var child = collection_root.children[i]; | ||
let init_existing = function() { | ||
for (let i = 0; i < collection_root.children.length; i++) { | ||
/* | ||
* Doesn't prevent the init if returns false (because it's necessary since the element is there anyway) | ||
* But could remove the element in future development? | ||
*/ | ||
if (settings.call_pre_add_on_init) | ||
settings.pre_add(formCollection.ADD_CONTEXT.INIT, i); | ||
let child = collection_root.children[i]; | ||
init_elem_listeners(child); | ||
if (settings.call_post_add_on_init) | ||
settings.post_add(child, formCollection.POST_ADD_CONTEXT.INIT, i); | ||
settings.post_add(child, formCollection.ADD_CONTEXT.INIT, i); | ||
} | ||
@@ -394,3 +428,3 @@ }; | ||
if (settings.other_btn_add) { | ||
var otherBtnAdds = null; | ||
let otherBtnAdds = null; | ||
if (typeof settings.other_btn_add === 'string') | ||
@@ -403,8 +437,8 @@ otherBtnAdds = document.querySelectorAll(settings.other_btn_add); | ||
else { | ||
console.log('other_btn_add: bad value, can be a selector or nodes, or a jQuery object.'); | ||
console.error('other_btn_add: bad value, can be a selector or nodes, or a jQuery object.'); | ||
} | ||
if (otherBtnAdds) { | ||
for (var i = 0; i < otherBtnAdds.length; i++) { | ||
for (let i = 0; i < otherBtnAdds.length; i++) { | ||
otherBtnAdds[i].addEventListener('click', function() { | ||
add_elem_bottom(formCollection.POST_ADD_CONTEXT.OTHER_BTN_ADD); | ||
add_elem_bottom(formCollection.ADD_CONTEXT.OTHER_BTN_ADD); | ||
}); | ||
@@ -417,3 +451,3 @@ } | ||
formCollection.POST_ADD_CONTEXT = { | ||
formCollection.ADD_CONTEXT = { | ||
BTN_ADD: 4, | ||
@@ -424,37 +458,22 @@ OTHER_BTN_ADD: 8, | ||
}; | ||
formCollection.POST_DELETE_CONTEXT = { | ||
formCollection.DELETE_CONTEXT = { | ||
BTN_DELETE: 23, | ||
DELETE_METHOD: 42 | ||
}; | ||
formCollection.jQuery = null; | ||
// UMD : Uses CommonJS, AMD or browser globals to create a jQuery plugin (if jQuery is there) | ||
formCollection.POST_ADD_CONTEXT = formCollection.ADD_CONTEXT; // to avoid breaking changes, for now | ||
formCollection.POST_DELETE_CONTEXT = formCollection.DELETE_CONTEXT; // to avoid breaking changes, for now | ||
// UMD : Uses CommonJS, AMD or browser globals | ||
(function(root, factory) { | ||
if (typeof define === 'function' && define.amd) { | ||
// AMD. Register as an anonymous module. | ||
define(['jquery'], factory); | ||
define([], factory); | ||
} else if (typeof module === 'object' && module.exports) { | ||
// Node/CommonJS | ||
module.exports = factory(require('jquery')); | ||
module.exports = factory(); | ||
} else { | ||
// Browser globals | ||
if (typeof jQuery !== 'undefined') | ||
root.returnExports = factory(jQuery); | ||
else | ||
root.returnExports = factory(); | ||
root.returnExports = factory(); | ||
} | ||
}(this, function($) { | ||
if (typeof jQuery !== 'undefined' && jQuery) { | ||
formCollection.jQuery = $; // jQuery is not necessarily global so it's better to know easily if it's available | ||
$.fn.formCollection = function (options, param) { | ||
var nodeArray = []; | ||
for (var i = 0; i < this.length; i++) { | ||
nodeArray.push(this[i]); | ||
} | ||
var ret = formCollection(nodeArray, options, param); | ||
if (!Array.isArray(ret)) | ||
return ret; | ||
return $(this); | ||
}; | ||
} | ||
}(this, function() { | ||
return formCollection; | ||
})); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
149
482798
30
8963