From 35cbb1cf50e1eb001eb007e886faa4961c995ded Mon Sep 17 00:00:00 2001 From: Fedir Zinchuk Date: Sun, 15 Oct 2017 18:58:15 +0300 Subject: [PATCH] Fix for: Field subform (multiple) produces wrong id (#16480) * Fix for: Field subform (multiple) produces wrong id * Fix subform-repeatable.js test --- .../js/subform-repeatable-uncompressed.js | 73 ++++++++++--------- media/system/js/subform-repeatable.js | 2 +- .../subform-repeatable/fixtures/fixture.html | 16 ++-- tests/javascript/subform-repeatable/spec.js | 30 ++++---- 4 files changed, 62 insertions(+), 59 deletions(-) diff --git a/media/system/js/subform-repeatable-uncompressed.js b/media/system/js/subform-repeatable-uncompressed.js index cb5df969d1cf0..ec6e78640bb0b 100644 --- a/media/system/js/subform-repeatable-uncompressed.js +++ b/media/system/js/subform-repeatable-uncompressed.js @@ -154,52 +154,55 @@ this.lastRowNum = countnew; $row.attr('data-group', groupnew); - // fix inputs that have a "name" attribute - var haveName = $row.find('*[name]'), - ids = {}; // collect existing id`s for fix checkboxes and radio - for(var i=0, l = haveName.length; i fix - //check if multiple - if(name.match(/\[\]$/)){ - // replace a group label "for" - var groupLbl = $row.find('label[for="' + id + '"]'); - if(groupLbl.length){ - groupLbl.attr('for', idNew); - $el.parents('fieldset.checkboxes').attr('id', idNew); - } - // recount id - var count = ids[id] ? ids[id].length : 0; - forOldAttr = forOldAttr + count; - idNew = idNew + count; + // Fix inputs that have a "name" attribute + var haveName = $row.find('[name]'), + ids = {}; // Collect id for fix checkboxes and radio + + for (var i = 0, l = haveName.length; i < l; i++) { + var $el = $(haveName[i]), + name = $el.attr('name'), + id = name.replace(/(\[\]$)/g, '').replace(/(\]\[)/g, '__').replace(/\[/g, '_').replace(/\]/g, ''), // id from name + nameNew = name.replace('[' + group + '][', '['+ groupnew +']['), // New name + idNew = id.replace(group, groupnew), // Count new id + countMulti = 0, // count for multiple radio/checkboxes + forOldAttr = id; // Fix "for" in the labels + + if ($el.prop('type') === 'checkbox' && name.match(/\[\]$/)) { // fix + // Recount id + countMulti = ids[id] ? ids[id].length : 0; + if (!countMulti) { + // Set the id for fieldset and group label + $el.closest('fieldset.checkboxes').attr('id', idNew); + $row.find('label[for="' + id + '"]').attr('for', idNew).attr('id', idNew + '-lbl'); } + forOldAttr = forOldAttr + countMulti; + idNew = idNew + countMulti; } - else if($el.prop('type') === 'radio'){// fix - // recount id - var count = ids[id] ? ids[id].length : 0; - forOldAttr = forOldAttr + count; - idNew = idNew + count; + else if ($el.prop('type') === 'radio') { // fix + // Recount id + countMulti = ids[id] ? ids[id].length : 0; + if (!countMulti) { + // Set the id for fieldset and group label + $el.closest('fieldset.radio').attr('id', idNew); + $row.find('label[for="' + id + '"]').attr('for', idNew).attr('id', idNew + '-lbl'); + } + forOldAttr = forOldAttr + countMulti; + idNew = idNew + countMulti; } - //cache ids - if(ids[id]){ + // Cache already used id + if (ids[id]) { ids[id].push(true); } else { ids[id] = [true]; } - // replace name to new + // Replace the name to new one $el.attr('name', nameNew); - // set new id + // Set new id $el.attr('id', idNew); - // guess there a label for this input - $row.find('label[for="' + forOldAttr + '"]').attr('for', idNew); + // Guess there a label for this input + $row.find('label[for="' + forOldAttr + '"]').attr('for', idNew).attr('id', idNew + '-lbl'); } }; diff --git a/media/system/js/subform-repeatable.js b/media/system/js/subform-repeatable.js index 9bc3f3ea82751..5410427d14ac1 100644 --- a/media/system/js/subform-repeatable.js +++ b/media/system/js/subform-repeatable.js @@ -1 +1 @@ -(function($){"use strict";$.subformRepeatable=function(container,options){this.$container=$(container);if(this.$container.data("subformRepeatable")){return self}this.$container.data("subformRepeatable",self);this.options=$.extend({},$.subformRepeatable.defaults,options);this.template="";this.prepareTemplate();this.$containerRows=this.options.rowsContainer?this.$container.find(this.options.rowsContainer):this.$container;this.lastRowNum=this.$containerRows.find(this.options.repeatableElement).length;var self=this;this.$container.on("click",this.options.btAdd,function(e){e.preventDefault();var after=$(this).parents(self.options.repeatableElement);if(!after.length){after=null}self.addRow(after)});this.$container.on("click",this.options.btRemove,function(e){e.preventDefault();var $row=$(this).parents(self.options.repeatableElement);self.removeRow($row)});if(this.options.btMove){this.$containerRows.sortable({items:this.options.repeatableElement,handle:this.options.btMove,tolerance:"pointer"})}this.$container.trigger("subform-ready")};$.subformRepeatable.prototype.prepareTemplate=function(){if(this.options.rowTemplateSelector){var tmplElement=this.$container.find(this.options.rowTemplateSelector)[0]||{};this.template=$.trim(tmplElement.text||tmplElement.textContent)}else{var row=this.$container.find(this.options.repeatableElement).get(0),$row=$(row).clone();try{this.clearScripts($row)}catch(e){if(window.console){console.log(e)}}this.template=$row.prop("outerHTML")}};$.subformRepeatable.prototype.addRow=function(after){var count=this.$containerRows.find(this.options.repeatableElement).length;if(count>=this.options.maximum){return null}var row=$.parseHTML(this.template);if(after){$(after).after(row)}else{this.$containerRows.append(row)}var $row=$(row);$row.attr("data-new","true");this.fixUniqueAttributes($row,count);try{this.fixScripts($row)}catch(e){if(window.console){console.log(e)}}this.$container.trigger("subform-row-add",$row);return $row};$.subformRepeatable.prototype.removeRow=function($row){var count=this.$containerRows.find(this.options.repeatableElement).length;if(count<=this.options.minimum){return}this.$container.trigger("subform-row-remove",$row);$row.remove()};$.subformRepeatable.prototype.fixUniqueAttributes=function($row,count){this.lastRowNum++;var group=$row.attr("data-group"),basename=$row.attr("data-base-name"),count=count||0,countnew=Math.max(this.lastRowNum,count+1),groupnew=basename+countnew;this.lastRowNum=countnew;$row.attr("data-group",groupnew);var haveName=$row.find("*[name]"),ids={};for(var i=0,l=haveName.length;i=this.options.maximum){return null}var row=$.parseHTML(this.template);if(after){$(after).after(row)}else{this.$containerRows.append(row)}var $row=$(row);$row.attr("data-new","true");this.fixUniqueAttributes($row,count);try{this.fixScripts($row)}catch(e){if(window.console){console.log(e)}}this.$container.trigger("subform-row-add",$row);return $row};$.subformRepeatable.prototype.removeRow=function($row){var count=this.$containerRows.find(this.options.repeatableElement).length;if(count<=this.options.minimum){return}this.$container.trigger("subform-row-remove",$row);$row.remove()};$.subformRepeatable.prototype.fixUniqueAttributes=function($row,count){this.lastRowNum++;var group=$row.attr("data-group"),basename=$row.attr("data-base-name"),count=count||0,countnew=Math.max(this.lastRowNum,count+1),groupnew=basename+countnew;this.lastRowNum=countnew;$row.attr("data-group",groupnew);var haveName=$row.find("[name]"),ids={};for(var i=0,l=haveName.length;i - +
Data 1 Data 2 - - + + - +
@@ -26,15 +26,15 @@