diff --git a/wire/modules/Inputfield/InputfieldSelector/InputfieldSelector.js b/wire/modules/Inputfield/InputfieldSelector/InputfieldSelector.js index db5145ff..23301428 100644 --- a/wire/modules/Inputfield/InputfieldSelector/InputfieldSelector.js +++ b/wire/modules/Inputfield/InputfieldSelector/InputfieldSelector.js @@ -244,6 +244,7 @@ var InputfieldSelector = { //console.log('changeField'); var $select = $(this); + var $option = $select.children('option:selected'); var field = $select.val(); if(!field || field.length == 0) return; if(field == 'toggle-names-labels') return InputfieldSelector.changeFieldToggle($select); @@ -255,9 +256,9 @@ var InputfieldSelector = { var $hiddenInput = $select.parents('.InputfieldSelector').find('.selector-value'); // .selector-value intentional! var name = $hiddenInput.attr('name'); var type = $select.attr('data-type'); - + if(field.match(/\.$/)) { - action = 'subfield'; + action = 'subfield-opval'; if(field.indexOf('@') > -1) field = field.substring(1, field.length-1); else field = field.substring(0, field.length-1); $row.addClass('has-subfield'); @@ -269,32 +270,51 @@ var InputfieldSelector = { $row.children('.subfield').html(''); $row.removeClass('has-subfield'); } + + // subfieldopval action var url = './?InputfieldSelector=' + action + '&field=' + field + '&type=' + type + '&name=' + name; var $spinner = $(InputfieldSelector.spinner); $row.append($spinner); - + $.get(url, function(data) { $spinner.remove(); - var $data = $(data); - $data.hide(); - - if(action == 'opval') { - var $opval = $row.children('.opval'); + + function actionOpval($data) { + $data.hide(); + var $opval = $row.children('.opval'); $opval.html('').append($data); - $opval.children(':not(.input-or)').fadeIn('fast'); + $opval.children(':not(.input-or)').fadeIn('fast'); //$data.fadeIn('fast'); InputfieldSelector.changeAny($select); - var $ac = $opval.find(".input-value-autocomplete"); + var $ac = $opval.find(".input-value-autocomplete"); if($ac.length > 0) InputfieldSelector.setupAutocomplete($ac, field, name); - } else { + } + + function actionSubfield($data) { + $data.hide(); var $subfield = $row.children('.subfield'); - $subfield.html('').append($data); - $data.fadeIn('fast'); + $subfield.html('').append($data); + $data.fadeIn('fast', function() { + // if there is a default selected option, select it now + //var $option = $subfield.find('.select-subfield-default'); + //if($option.length) $option.attr('selected', 'selected').parent('select').change(); + }); //$row.children('.subfield').html(data); } + + if(action == 'subfield-opval') { + data = data.split(''); + actionSubfield($(data[0])); + actionOpval($(data[1])); + + } else if(action == 'opval') { + actionOpval($(data)); + } else { + actionSubfield($(data)); + } InputfieldSelector.normalizeHeightRow($row); @@ -429,13 +449,18 @@ var InputfieldSelector = { if(templateID > 0) templateIDs.push(templateID); } - if($row.is(".has-subfield")) { - var subfield = $row.find(".select-subfield").val(); + if($row.hasClass('has-subfield')) { + var $selectSubfield = $row.find('.select-subfield'); + var $selectOption = $selectSubfield.children('option:selected'); + var subfield = $selectSubfield.val(); if(subfield.length > 0) { if(subfield.indexOf('.') > 0) { // fieldName was already specified with subfield - if(fieldName.indexOf('@') > -1) fieldName = '@' + subfield; - else fieldName = subfield; + if(fieldName.indexOf('@') > -1) fieldName = '@' + subfield; + else fieldName = subfield; + } else if($selectOption.hasClass('select-subfield-default')) { + // indicates subfield IS the fieldName + fieldName = subfield; } else { // subfield needs to be appended to fieldName fieldName += subfield; diff --git a/wire/modules/Inputfield/InputfieldSelector/InputfieldSelector.min.js b/wire/modules/Inputfield/InputfieldSelector/InputfieldSelector.min.js index ba3c9614..bcc4bc46 100644 --- a/wire/modules/Inputfield/InputfieldSelector/InputfieldSelector.min.js +++ b/wire/modules/Inputfield/InputfieldSelector/InputfieldSelector.min.js @@ -1 +1 @@ -var InputfieldSelector={selector:"",spinner:"",borderColor:"#eee",init:function(){$(document).on("change",".InputfieldSelector select.select-field",InputfieldSelector.changeField);$(document).on("change",".InputfieldSelector select.select-subfield",InputfieldSelector.changeField);$(document).on("change",".InputfieldSelector :input:not(.select-field):not(.input-value-autocomplete)",function(){InputfieldSelector.changeAny($(this))});$(document).on("opened",".InputfieldSelector",function(){InputfieldSelector.normalizeHeightRows($(this))});var b=null;$(document).on("keyup",".InputfieldSelector input.input-value",function(){var d=$(this);clearTimeout(b);if(d.hasClass("input-value-subselect")&&InputfieldSelector.valueHasOperator(d.val())){var c=d.closest(".InputfieldContent").find(".selector-preview");c.html('Subselect detected: when done click here to commit your change.');return}b=setTimeout(function(){InputfieldSelector.changeAny(d)},100)});$(document).on("click",".InputfieldSelector .selector-add",function(){InputfieldSelector.addRow($(this));return false});$(document).on("click",".InputfieldSelector a.delete-row",InputfieldSelector.deleteRow);$(".InputfieldSelector .selector-preview").hide();$(document).on("wiretabclick",function(f,d,c){var e=d.find(".InputfieldSelector");if(e.length==0){return}InputfieldSelector.normalizeHeightRows(e)});var a=$(".InputfieldSelector .selector-row");if(a.length>0){a.eq(0).find(".select-field").each(function(){InputfieldSelector.changeAny($(this))});a.eq(1).find(".input-value").change();a.each(function(){var c=$(this);c.css("border-color",InputfieldSelector.borderColor);InputfieldSelector.normalizeHeightRow(c);var f=c.find(".input-value-autocomplete");if(f.length>0){var d=c.find(".select-subfield");var g=d.length?d.val():c.find(".select-field").val();var e=c.parents(".InputfieldSelector").find("input.selector-value").attr("name");InputfieldSelector.setupAutocomplete(f,g,e)}})}$(".InputfieldSelector").each(function(){if($(this).find(".selector-preview-disabled").length>0){return}$(this).find(".input-value:eq(0)").change()})},disableOption:function(a){a.attr("disabled","disabled")},enableOption:function(a){a.removeAttr("disabled")},valueHasOperator:function(b){var a=["=","<",">"];var d=false;for(n=0;n-1&&b.substring(c-1,1)!="\\"){d=true;break}}return d},addRow:function(b){var c=b.parents(".InputfieldSelector").find(".selector-list");var a=c.find(".selector-template-row");var d=a.clone();d.removeClass("selector-template-row");d.find(".opval").html("");d.find(".select-field").val("");d.hide();d.find("option[disabled=disabled]").remove();c.append(d);d.slideDown("fast");InputfieldSelector.normalizeHeightRow(d)},deleteRow:function(){var b=$(this).parents(".selector-row");var a=b.find(".select-field");if(a.val()=="template"){b.parents(".InputfieldSelector").find("select.select-field").each(function(){$(this).find("option[disabled=disabled]").each(function(){InputfieldSelector.enableOption($(this))})})}var c=b.siblings();b.slideUp("fast",function(){b.remove();InputfieldSelector.changeAny(c.eq(0))});return false},changeFieldToggle:function(b){var d=b.parents(".InputfieldSelector");var c=d.hasClass("InputfieldSelector_names")?"names":"labels";var a=(c==="labels"?"names":"labels");d.find(".select-field, .select-subfield").each(function(){$(this).find("option").each(function(){var e=$(this).attr("data-name");if(!e){if($(this).attr("value")=="toggle-names-labels"){$(this).html($(this).attr("data-"+c))}return}if(c=="labels"){$(this).html(e)}else{$(this).html($(this).attr("data-label"))}})});d.removeClass("InputfieldSelector_"+c).addClass("InputfieldSelector_"+a);b.val(b.attr("data-selected"));return false},changeField:function(f){var f=$(this);var i=f.val();if(!i||i.length==0){return}if(i=="toggle-names-labels"){return InputfieldSelector.changeFieldToggle(f)}var g=f.parents(".selector-row");var e="opval";g.children(".opval").html("");f.attr("data-selected",i);var c=f.parents(".InputfieldSelector").find(".selector-value");var a=c.attr("name");var h=f.attr("data-type");if(i.match(/\.$/)){e="subfield";if(i.indexOf("@")>-1){i=i.substring(1,i.length-1)}else{i=i.substring(0,i.length-1)}g.addClass("has-subfield")}else{if(i.match(/\.id$/)){i="id";e="opval";h="selector"}else{if(f.is(".select-field")){g.children(".subfield").html("");g.removeClass("has-subfield")}}}var b="./?InputfieldSelector="+e+"&field="+i+"&type="+h+"&name="+a;var d=$(InputfieldSelector.spinner);g.append(d);$.get(b,function(m){d.remove();var j=$(m);j.hide();if(e=="opval"){var l=g.children(".opval");l.html("").append(j);l.children(":not(.input-or)").fadeIn("fast");InputfieldSelector.changeAny(f);var k=l.find(".input-value-autocomplete");if(k.length>0){InputfieldSelector.setupAutocomplete(k,i,a)}}else{var o=g.children(".subfield");o.html("").append(j);j.fadeIn("fast")}InputfieldSelector.normalizeHeightRow(g);g.closest(".InputfieldContent").find(".hasDatepicker").datepicker("destroy").removeAttr("id").removeClass("hasDatepicker")})},normalizeHeightRow:function(a){InputfieldSelector.normalizeHeight(a.find(":input, i.fa"))},normalizeHeightRows:function(a){a.find(".selector-row").each(function(){InputfieldSelector.normalizeHeightRow($(this))})},normalizeHeight:function(b){var a=0;b.each(function(){$(this).css("margin-top",0);var c=$(this).outerHeight();if(c>a){a=c}});b.each(function(){var d=$(this).outerHeight();if(d0){f.push(C)}}if(E.is(".has-subfield")){var H=E.find(".select-subfield").val();if(H.length>0){if(H.indexOf(".")>0){if(K.indexOf("@")>-1){K="@"+H}else{K=H}}else{K+=H}if(K.indexOf(".data")>0){K=K.replace(/\.data$/,"")}}}var y=z.siblings(".opval").children(".select-operator");var B=y.val();var G=y.next(".input-value");var J=G.val();if(B&&B.indexOf('"')>-1){J=" ";G.attr("disabled","disabled")}else{if(G.is(":disabled")){G.removeAttr("disabled")}}if(typeof J!="undefined"){if(J.length){if(G.hasClass("input-value-subselect")&&InputfieldSelector.valueHasOperator(J)){J="["+J+"]"}else{if(J.indexOf(",")>-1&&K!="_custom"){if(J.indexOf('"')>-1){if(J.indexOf("'")==-1){J="'"+J+"'"}else{J='"'+J.replace(/"/g,"")+'"'}}else{J='"'+J+'"'}}}}}var D=","+K+"~"+B+"~";var F="~"+B+"~"+J+",";var A=J&&J.length>0&&q.indexOf(D)>-1;var x=J&&J.length>0&&q.indexOf(F)>-1;var I=E.find(".input-or");var s=A&&I.is(":checked");var i=x&&I.is(":checked");var w=(i||s)&&K=="_custom";if(s){E.addClass("has-or-value");E.find(".select-field, .select-operator, .select-subfield").attr("disabled","disabled")}else{if(E.is(".has-or-value")){E.removeClass("has-or-value");E.find(".select-field, .select-operator, .select-subfield").removeAttr("disabled")}}if(i){E.addClass("has-or-field");E.find(".input-value, .select-operator").attr("disabled","disabled")}else{if(E.is(".has-or-field")){E.removeClass("has-or-field");E.find(".input-value, .select-operator").removeAttr("disabled")}}c[k++]={field:K,operator:B,value:J,mayOrValue:A,mayOrField:x,useOrValue:s,useOrField:i,isOrGroup:w,checkbox:I};if(x||A){h=true}q+=","+K+"~"+B+"~"+J+",";m+=","+K+B+J});if(f.length>0){var d=null;t.each(function(){var i=$(this);var s=0;i.find("option").each(function(){var x=$(this);var w=x.attr("data-templates");if(typeof w!="undefined"&&w!="*"){InputfieldSelector.enableOption(x);var y=0;for(p=0;p-1){y++}}if(y){InputfieldSelector.enableOption(x)}else{if(!x.is(":selected")){InputfieldSelector.disableOption(x)}s++}}});if(s>0&&!i.parent().is(".selector-template-row")){i.find("option[disabled=disabled]").remove()}})}m="";for(k=0;k0){m+=", "}for(var p=0;p0&&m!=InputfieldSelector.selector){if(!j.is(".selector-preview-disabled")){j.html(""+e+m+"");j.fadeIn()}var u=j.siblings(".selector-counter");if(u.length>0&&!u.is(".selector-counter-disabled")){u.html(InputfieldSelector.spinner).fadeIn("fast");$.post("./?InputfieldSelector=test&name="+o.attr("name"),{selector:m},function(i){u.hide();u.html(i);u.show()})}}if(o.val()!=m){o.val(m);if(m.length==0){j.hide();j.siblings(".selector-counter").html("")}o.change()}InputfieldSelector.selector=m;var a=l.find(".or-notes");if(h){a.fadeIn()}else{a.hide()}}};$(document).ready(function(){InputfieldSelector.init()}); \ No newline at end of file +var InputfieldSelector={selector:"",spinner:"",borderColor:"#eee",init:function(){$(document).on("change",".InputfieldSelector select.select-field",InputfieldSelector.changeField);$(document).on("change",".InputfieldSelector select.select-subfield",InputfieldSelector.changeField);$(document).on("change",".InputfieldSelector :input:not(.select-field):not(.input-value-autocomplete)",function(){InputfieldSelector.changeAny($(this))});$(document).on("opened",".InputfieldSelector",function(){InputfieldSelector.normalizeHeightRows($(this))});var timeout=null;$(document).on("keyup",".InputfieldSelector input.input-value",function(){var $t=$(this);clearTimeout(timeout);if($t.hasClass("input-value-subselect")&&InputfieldSelector.valueHasOperator($t.val())){var $preview=$t.closest(".InputfieldContent").find(".selector-preview");$preview.html('Subselect detected: when done click here to commit your change.');return}timeout=setTimeout(function(){InputfieldSelector.changeAny($t)},100)});$(document).on("click",".InputfieldSelector .selector-add",function(){InputfieldSelector.addRow($(this));return false});$(document).on("click",".InputfieldSelector a.delete-row",InputfieldSelector.deleteRow);$(".InputfieldSelector .selector-preview").hide();$(document).on("wiretabclick",function(event,$newTab,$oldTab){var $inputfield=$newTab.find(".InputfieldSelector");if($inputfield.length==0)return;InputfieldSelector.normalizeHeightRows($inputfield)});var $rows=$(".InputfieldSelector .selector-row");if($rows.length>0){$rows.eq(0).find(".select-field").each(function(){InputfieldSelector.changeAny($(this))});$rows.eq(1).find(".input-value").change();$rows.each(function(){var $row=$(this);$row.css("border-color",InputfieldSelector.borderColor);InputfieldSelector.normalizeHeightRow($row);var $ac=$row.find(".input-value-autocomplete");if($ac.length>0){var subfield=$row.find(".select-subfield");var field=subfield.length?subfield.val():$row.find(".select-field").val();var name=$row.parents(".InputfieldSelector").find("input.selector-value").attr("name");InputfieldSelector.setupAutocomplete($ac,field,name)}})}$(".InputfieldSelector").each(function(){if($(this).find(".selector-preview-disabled").length>0)return;$(this).find(".input-value:eq(0)").change()})},disableOption:function($option){$option.attr("disabled","disabled")},enableOption:function($option){$option.removeAttr("disabled")},valueHasOperator:function(value){var operators=["=","<",">"];var hasOperator=false;for(n=0;n-1&&value.substring(pos-1,1)!="\\"){hasOperator=true;break}}return hasOperator},addRow:function($context){var $list=$context.parents(".InputfieldSelector").find(".selector-list");var $row=$list.find(".selector-template-row");var $newRow=$row.clone();$newRow.removeClass("selector-template-row");$newRow.find(".opval").html("");$newRow.find(".select-field").val("");$newRow.hide();$newRow.find("option[disabled=disabled]").remove();$list.append($newRow);$newRow.slideDown("fast");InputfieldSelector.normalizeHeightRow($newRow)},deleteRow:function(){var $row=$(this).parents(".selector-row");var $selectField=$row.find(".select-field");if($selectField.val()=="template"){$row.parents(".InputfieldSelector").find("select.select-field").each(function(){$(this).find("option[disabled=disabled]").each(function(){InputfieldSelector.enableOption($(this))})})}var $siblings=$row.siblings();$row.slideUp("fast",function(){$row.remove();InputfieldSelector.changeAny($siblings.eq(0))});return false},changeFieldToggle:function($select){var $rootParent=$select.parents(".InputfieldSelector");var currentSetting=$rootParent.hasClass("InputfieldSelector_names")?"names":"labels";var newSetting=currentSetting==="labels"?"names":"labels";$rootParent.find(".select-field, .select-subfield").each(function(){$(this).find("option").each(function(){var name=$(this).attr("data-name");if(!name){if($(this).attr("value")=="toggle-names-labels"){$(this).html($(this).attr("data-"+currentSetting))}return}if(currentSetting=="labels"){$(this).html(name)}else{$(this).html($(this).attr("data-label"))}})});$rootParent.removeClass("InputfieldSelector_"+currentSetting).addClass("InputfieldSelector_"+newSetting);$select.val($select.attr("data-selected"));return false},changeField:function($select){var $select=$(this);var $option=$select.children("option:selected");var field=$select.val();if(!field||field.length==0)return;if(field=="toggle-names-labels")return InputfieldSelector.changeFieldToggle($select);var $row=$select.parents(".selector-row");var action="opval";$row.children(".opval").html("");$select.attr("data-selected",field);var $hiddenInput=$select.parents(".InputfieldSelector").find(".selector-value");var name=$hiddenInput.attr("name");var type=$select.attr("data-type");if(field.match(/\.$/)){action="subfield-opval";if(field.indexOf("@")>-1)field=field.substring(1,field.length-1);else field=field.substring(0,field.length-1);$row.addClass("has-subfield")}else if(field.match(/\.id$/)){field="id";action="opval";type="selector"}else if($select.is(".select-field")){$row.children(".subfield").html("");$row.removeClass("has-subfield")}var url="./?InputfieldSelector="+action+"&field="+field+"&type="+type+"&name="+name;var $spinner=$(InputfieldSelector.spinner);$row.append($spinner);$.get(url,function(data){$spinner.remove();function actionOpval($data){$data.hide();var $opval=$row.children(".opval");$opval.html("").append($data);$opval.children(":not(.input-or)").fadeIn("fast");InputfieldSelector.changeAny($select);var $ac=$opval.find(".input-value-autocomplete");if($ac.length>0)InputfieldSelector.setupAutocomplete($ac,field,name)}function actionSubfield($data){$data.hide();var $subfield=$row.children(".subfield");$subfield.html("").append($data);$data.fadeIn("fast",function(){})}if(action=="subfield-opval"){data=data.split("");actionSubfield($(data[0]));actionOpval($(data[1]))}else if(action=="opval"){actionOpval($(data))}else{actionSubfield($(data))}InputfieldSelector.normalizeHeightRow($row);$row.closest(".InputfieldContent").find(".hasDatepicker").datepicker("destroy").removeAttr("id").removeClass("hasDatepicker")})},normalizeHeightRow:function($row){InputfieldSelector.normalizeHeight($row.find(":input, i.fa"))},normalizeHeightRows:function($parent){$parent.find(".selector-row").each(function(){InputfieldSelector.normalizeHeightRow($(this))})},normalizeHeight:function($items){var maxHeight=0;$items.each(function(){$(this).css("margin-top",0);var h=$(this).outerHeight();if(h>maxHeight)maxHeight=h});$items.each(function(){var h=$(this).outerHeight();if(h0)templateIDs.push(templateID)}if($row.hasClass("has-subfield")){var $selectSubfield=$row.find(".select-subfield");var $selectOption=$selectSubfield.children("option:selected");var subfield=$selectSubfield.val();if(subfield.length>0){if(subfield.indexOf(".")>0){if(fieldName.indexOf("@")>-1)fieldName="@"+subfield;else fieldName=subfield}else if($selectOption.hasClass("select-subfield-default")){fieldName=subfield}else{fieldName+=subfield}if(fieldName.indexOf(".data")>0)fieldName=fieldName.replace(/\.data$/,"")}}var $op=$select.siblings(".opval").children(".select-operator");var op=$op.val();var $value=$op.next(".input-value");var value=$value.val();if(op&&op.indexOf('"')>-1){value=" ";$value.attr("disabled","disabled")}else if($value.is(":disabled")){$value.removeAttr("disabled")}if(typeof value!="undefined")if(value.length){if($value.hasClass("input-value-subselect")&&InputfieldSelector.valueHasOperator(value)){value="["+value+"]"}else if(value.indexOf(",")>-1&&fieldName!="_custom"){if(value.indexOf('"')>-1){if(value.indexOf("'")==-1)value="'"+value+"'";else value='"'+value.replace(/"/g,"")+'"'}else{value='"'+value+'"'}}}var testField=","+fieldName+"~"+op+"~";var testValue="~"+op+"~"+value+",";var mayOrValue=value&&value.length>0&&test.indexOf(testField)>-1;var mayOrField=value&&value.length>0&&test.indexOf(testValue)>-1;var $orCheckbox=$row.find(".input-or");var useOrValue=mayOrValue&&$orCheckbox.is(":checked");var useOrField=mayOrField&&$orCheckbox.is(":checked");var isOrGroup=(useOrField||useOrValue)&&fieldName=="_custom";if(useOrValue){$row.addClass("has-or-value");$row.find(".select-field, .select-operator, .select-subfield").attr("disabled","disabled")}else if($row.is(".has-or-value")){$row.removeClass("has-or-value");$row.find(".select-field, .select-operator, .select-subfield").removeAttr("disabled")}if(useOrField){$row.addClass("has-or-field");$row.find(".input-value, .select-operator").attr("disabled","disabled")}else if($row.is(".has-or-field")){$row.removeClass("has-or-field");$row.find(".input-value, .select-operator").removeAttr("disabled")}selectors[n++]={field:fieldName,operator:op,value:value,mayOrValue:mayOrValue,mayOrField:mayOrField,useOrValue:useOrValue,useOrField:useOrField,isOrGroup:isOrGroup,checkbox:$orCheckbox};if(mayOrField||mayOrValue)showOrNotes=true;test+=","+fieldName+"~"+op+"~"+value+",";selector+=","+fieldName+op+value});if(templateIDs.length>0){var $masterSelect=null;$selectFields.each(function(){var $select=$(this);var numDisabledOptions=0;$select.find("option").each(function(){var $option=$(this);var templates=$option.attr("data-templates");if(typeof templates!="undefined"&&templates!="*"){InputfieldSelector.enableOption($option);var numFound=0;for(i=0;i-1)numFound++}if(numFound){InputfieldSelector.enableOption($option)}else{if(!$option.is(":selected"))InputfieldSelector.disableOption($option);numDisabledOptions++}}});if(numDisabledOptions>0&&!$select.parent().is(".selector-template-row")){$select.find("option[disabled=disabled]").remove()}})}selector="";for(n=0;n0)selector+=", ";for(var i=0;i0&&selector!=InputfieldSelector.selector){if(!$preview.is(".selector-preview-disabled")){$preview.html(""+initValue+selector+"");$preview.fadeIn()}var $counter=$preview.siblings(".selector-counter");if($counter.length>0&&!$counter.is(".selector-counter-disabled")){$counter.html(InputfieldSelector.spinner).fadeIn("fast");$.post("./?InputfieldSelector=test&name="+$hiddenInput.attr("name"),{selector:selector},function(data){$counter.hide();$counter.html(data);$counter.show()})}}if($hiddenInput.val()!=selector){$hiddenInput.val(selector);if(selector.length==0){$preview.hide();$preview.siblings(".selector-counter").html("")}$hiddenInput.change()}InputfieldSelector.selector=selector;var $orNotes=$inputfield.find(".or-notes");if(showOrNotes)$orNotes.fadeIn();else $orNotes.hide()}};$(document).ready(function(){InputfieldSelector.init()}); \ No newline at end of file diff --git a/wire/modules/Inputfield/InputfieldSelector/InputfieldSelector.module b/wire/modules/Inputfield/InputfieldSelector/InputfieldSelector.module index 4b97ea86..bb63d563 100644 --- a/wire/modules/Inputfield/InputfieldSelector/InputfieldSelector.module +++ b/wire/modules/Inputfield/InputfieldSelector/InputfieldSelector.module @@ -53,6 +53,7 @@ * @property string $selectClass * @property string $inputClass * @property string $checkboxClass + * @property string $lastSelector * * */ @@ -62,7 +63,7 @@ class InputfieldSelector extends Inputfield implements ConfigurableModule { public static function getModuleInfo() { return array( 'title' => 'Selector', - 'version' => 27, + 'version' => 28, 'summary' => 'Build a page finding selector visually.', 'author' => 'Avoine + ProcessWire', 'autoload' => "template=admin", @@ -191,6 +192,8 @@ class InputfieldSelector extends Inputfield implements ConfigurableModule { $this->setting('addLabel', $this->_('Add Field')); $this->setting('parseVars', true); // whether variables like [user.id] will be parsed + $this->set('lastSelector', ''); // last created selector + $this->set('subfieldIdentifier', ' …'); $this->set('groupIdentifier', ' ' . $this->_('(1)')); // group identifier @@ -214,6 +217,7 @@ class InputfieldSelector extends Inputfield implements ConfigurableModule { $this->setting('timeFormat', $this->_('H:i')); // time format $this->setting('timePlaceholder', $this->_('hh:mm')); // time format placeholder (what users see) $this->setting('maxUsers', 20); // text input rather than select used when useres qty is greater than this + parent::__construct(); } @@ -294,30 +298,33 @@ class InputfieldSelector extends Inputfield implements ConfigurableModule { } $this->setup(); + + $fieldName = $input->get('field'); + if($fieldName !== null) $fieldName = $sanitizer->name($fieldName); + + $type = $input->get('type'); + if($type !== null) $type = $sanitizer->name($type); + + $q = $input->get('q'); + if($q !== null) $q = $sanitizer->text($q); - if($action == 'field') { + if($action === 'field') { $out = $this->renderSelectField(); - } else if($action == 'subfield' && ($fieldName = $input->get->field)) { - $fieldName = $sanitizer->name($fieldName); - if(strpos($fieldName, '.')) { - list($fieldName, $subfieldName) = explode('.', $fieldName); - if($subfieldName) {} // ignore - } + } else if($action === 'subfield' && $fieldName) { $out = $this->renderSelectSubfield($fieldName); - } else if($action == 'opval' && ($fieldName = $input->get->field)) { - $fieldName = $sanitizer->name($fieldName); - //$subfield = $input->get->subfield ? $sanitizer->name($input->get->subfield) : ''; - //if($subfield) $fieldName = "$fieldName.$subfield"; - $type = $sanitizer->name($input->get->type); - $out = $this->renderOpval($fieldName, $type); + } else if($action === 'opval' && $fieldName) { + $out = $this->renderOpval($fieldName, $type); + + } else if($action === 'subfield-opval') { + $out = $this->renderSelectSubfield($fieldName) . '' . $this->renderOpval($fieldName, $type); - } else if($action == 'test' && ($selector = $input->post->selector)) { + } else if($action === 'test' && ($selector = $input->post('selector'))) { $out = $this->renderTestSelector($selector); - } else if($action == 'autocomplete' && ($fieldName = $input->get('field')) && ($q = $input->get('q'))) { - $out = $this->renderAutocompleteJSON($sanitizer->name($fieldName), $sanitizer->text($q)); + } else if($action === 'autocomplete' && $fieldName && strlen($q)) { + $out = $this->renderAutocompleteJSON($fieldName, $q); } else { $out = "Ajax request missing required info"; @@ -425,55 +432,41 @@ class InputfieldSelector extends Inputfield implements ConfigurableModule { // system fields definitions $this->systemFields = array( - 'template' => array( - 'input' => 'select', - 'label' => $this->_('Template'), - 'options' => $templates, + 'count' => array( + 'input' => 'number', + 'label' => $this->_('Count'), 'sanitizer' => 'integer', - 'operators' => array('=', '!='), - ), - 'title' => array( + ), + 'created' => array( + 'input' => 'datetime', + 'label' => $this->_('Created date'), + 'operators' => $this->operatorsByType['datetime'], + ), + 'created_users_id' => array( + 'input' => $usersInput, + 'label' => $this->_('Created by user'), + 'options' => $users, + 'operators' => $usersOperators + ), + '_custom' => array( 'input' => 'text', - 'label' => ($titleField ? $titleField->getLabel() : 'Title'), - 'operators' => $this->operatorsByType['text'] - ), + 'label' => $this->_('Custom (field=value)'), + 'operators' => array(), + 'placeholder' => $this->_('field=value'), + ), + 'has_parent' => array( + 'input' => 'text', + 'label' => $this->_('Has parent/ancestor'), + 'operators' => array('=', '!='), + ), 'id' => array( 'input' => 'number', 'label' => $this->_('ID'), 'sanitizer' => 'integer', - ), - 'name' => array( - 'input' => 'text', - 'label' => $this->_('Name'), - 'sanitizer' => 'pageNameUTF8', - 'operators' => array('=', '!=', '%='), - ), - 'status' => array( - 'input' => 'select', - 'label' => $this->_('Status'), - 'options' => array( - 'hidden' => $this->_('Hidden'), - 'unpublished' => $this->_('Unpublished'), - 'locked' => $this->_('Locked'), - 'trash' => $this->_('Trash'), - 'temp' => $this->_('Temp'), - ), - 'sanitizer' => 'integer', - 'operators' => array('@=', '@!='), - ), + ), 'modified' => array( 'input' => 'datetime', 'label' => $this->_('Modified date'), - 'operators' => $this->operatorsByType['datetime'], - ), - 'created' => array( - 'input' => 'datetime', - 'label' => $this->_('Created date'), - 'operators' => $this->operatorsByType['datetime'], - ), - 'published' => array( - 'input' => 'datetime', - 'label' => $this->_('Published date'), 'operators' => $this->operatorsByType['datetime'], ), 'modified_users_id' => array( @@ -481,49 +474,63 @@ class InputfieldSelector extends Inputfield implements ConfigurableModule { 'label' => $this->_('Modified by user'), 'options' => $users, 'operators' => $usersOperators - ), - 'created_users_id' => array( - 'input' => $usersInput, - 'label' => $this->_('Created by user'), - 'options' => $users, - 'operators' => $usersOperators - ), + ), + 'name' => array( + 'input' => 'text', + 'label' => $this->_('Name'), + 'sanitizer' => 'pageNameUTF8', + 'operators' => array('=', '!=', '%='), + ), 'num_children' => array( 'input' => 'number', 'label' => $this->_('Number of children'), 'sanitizer' => 'integer', - ), - 'count' => array( - 'input' => 'number', - 'label' => $this->_('Count'), - 'sanitizer' => 'integer', - ), - 'path' => array( - 'input' => 'text', - 'label' => $this->_('Path/URL'), - 'operators' => $this->operatorsByType['text'], - ), + ), 'parent' => array( 'input' => 'number', // select - 'label' => $this->_x('Parent', 'parent-only'), + 'label' => $this->_x('Parent', 'parent-only'), 'operators' => array('=', '!='), // $this->operatorsByType['page'] // 'options' => array(id => label) - ), + ), 'parent.' => array( 'input' => 'subfields', - 'label' => $this->_x('Parent',' parent-with-subfield'), - ), - 'has_parent' => array( - 'input' => 'text', - 'label' => $this->_('Has parent/ancestor'), - 'operators' => array('=', '!='), - ), - '_custom' => array( - 'input' => 'text', - 'label' => $this->_('Custom (field=value)'), - 'operators' => array(), - 'placeholder' => $this->_('field=value'), + 'label' => $this->_x('Parent',' parent-with-subfield'), ), + 'path' => array( + 'input' => 'text', + 'label' => $this->_('Path/URL'), + 'operators' => $this->operatorsByType['text'], + ), + 'published' => array( + 'input' => 'datetime', + 'label' => $this->_('Published date'), + 'operators' => $this->operatorsByType['datetime'], + ), + 'status' => array( + 'input' => 'select', + 'label' => $this->_('Status'), + 'options' => array( + 'hidden' => $this->_('Hidden'), + 'unpublished' => $this->_('Unpublished'), + 'locked' => $this->_('Locked'), + 'trash' => $this->_('Trash'), + 'temp' => $this->_('Temp'), + ), + 'sanitizer' => 'integer', + 'operators' => array('@=', '@!='), + ), + 'template' => array( + 'input' => 'select', + 'label' => $this->_('Template'), + 'options' => $templates, + 'sanitizer' => 'integer', + 'operators' => array('=', '!='), + ), + 'title' => array( + 'input' => 'text', + 'label' => ($titleField ? $titleField->getLabel() : 'Title'), + 'operators' => $this->operatorsByType['text'] + ), //'parent' => $this->_('parent'), ); @@ -549,27 +556,15 @@ class InputfieldSelector extends Inputfield implements ConfigurableModule { // system fields for page references $this->systemPageFields = array( - 'id' => $this->systemFields['id'], - 'name' => $this->systemFields['name'], - 'status' => $this->systemFields['status'], - 'modified' => $this->systemFields['modified'], 'created' => $this->systemFields['created'], + 'id' => $this->systemFields['id'], + 'modified' => $this->systemFields['modified'], + 'name' => $this->systemFields['name'], 'published' => $this->systemFields['published'], - ); + 'status' => $this->systemFields['status'], + ); $this->modifierFields = array( - 'sort' => array( - 'input' => 'select', - 'label' => $this->_('Sort'), - 'sanitizer' => 'fieldName', - 'operators' => array('.=', '.=-'), - 'options' => array() // populated below - ), - 'limit' => array( - 'input' => 'integer', - 'label' => $this->_('Limit'), - 'operators' => array('=') - ), 'include' => array( 'input' => 'select', 'label' => $this->_('Include'), @@ -578,10 +573,22 @@ class InputfieldSelector extends Inputfield implements ConfigurableModule { 'unpublished' => $this->_('Hidden + Unpublished'), 'trash' => $this->_('Hidden + Unpublished + Trash'), 'all' => $this->_('All'), - ), + ), 'operators' => array('=') - ) - ); + ), + 'limit' => array( + 'input' => 'integer', + 'label' => $this->_('Limit'), + 'operators' => array('=') + ), + 'sort' => array( + 'input' => 'select', + 'label' => $this->_('Sort'), + 'sanitizer' => 'fieldName', + 'operators' => array('.=', '.=-'), + 'options' => array() // populated below + ), + ); // populate the sort options $options = array(); @@ -607,7 +614,7 @@ class InputfieldSelector extends Inputfield implements ConfigurableModule { protected function sessionSet($key, $value) { $s = $this->wire('session')->get($this->className()); if(!is_array($s)) $s = array(); - if(count($s) > 30) $s = array_slice($s, -9); // prevent from growing too large + if(count($s) > 100) $s = array_slice($s, -100); // prevent from growing too large $id = 'id' . $this->wire('page')->id . "_" . $this->wire('sanitizer')->fieldName($this->attr('name')); if(!isset($s[$id])) $s[$id] = array(); $s[$id][$key] = $value; @@ -781,11 +788,12 @@ class InputfieldSelector extends Inputfield implements ConfigurableModule { 'showFieldLabels' => $this->showFieldLabels, 'showOptgroups' => $this->showOptgroups, 'customFields' => $this->wire('fields'), - 'prepend' => '', 'exclude' => array('count', 'pass'), 'limitFields' => array(), 'templates' => array(), 'type' => '', + 'prepend' => '', + 'append' => '', ); $settings = array_merge($defaults, $settings); @@ -869,6 +877,7 @@ class InputfieldSelector extends Inputfield implements ConfigurableModule { if($settings['showFieldLabels'] == 2) $label .= " [$name]"; if($hasSubfields) $label .= $this->subfieldIdentifier; $selected = $selectedValue == $name ? ' selected' : ''; + if($name === 'parent' && empty($selected)) continue; // we only show "parent." unless "parent" it was somehow already selected if($_name == '_custom') $_name = strtolower($label); // always use label for _custom $text = $settings['showFieldLabels'] ? $label : $_name; $o = "attr('name') . "__" . $settings['name'] . "[]"; $selectClass = trim("$this->selectClass select-$settings[name]"); - $out = "$settings[prepend]"; if(!$this->showOptgroups) { ksort($outAll); @@ -960,7 +969,7 @@ class InputfieldSelector extends Inputfield implements ConfigurableModule { $out .= "$outSections[$name]"; } - $out .= ""; + $out .= "$settings[append]"; return $out; } @@ -996,36 +1005,42 @@ class InputfieldSelector extends Inputfield implements ConfigurableModule { protected function renderSelectFieldOption(Field $field, array $settings, $selectedValue = '') { if($field->type instanceof FieldtypeFieldsetOpen) return array(); - $out = array('field' => '', 'subfield' => '', 'group' => '', 'all' => array()); - $selected = $field->name == $selectedValue ? ' selected' : ''; + $fieldSelected = $field->name == $selectedValue ? ' selected' : ''; $templatesStr = $this->getTemplateIdsUsingField($field); $selectorInfo = $this->getSelectorInfo($field); if(empty($selectorInfo)) return array(); + $out = array( + 'field' => '', + 'subfield' => '', // no longer used (now replaces 'field') + 'group' => '', + 'all' => array() + ); + $label = $this->wire('sanitizer')->entities($field->getLabel()); if($settings['showFieldLabels'] == 2) $label .= " [$field->name]"; $text = $settings['showFieldLabels'] ? $label : $field->name; if($selectorInfo['input'] != 'none' && count($selectorInfo['operators'])) { - $o = "$text"; - $out['field'] .= $o; + $out['field'] = $o; $out['all']["$field->name 1"] = $o; } if(!empty($settings['showSubfields'])) { $hasSubfields = count($selectorInfo['subfields']) > 0; - $selected = "$field->name." == $selectedValue ? ' selected' : ''; + $subfieldSelected = "$field->name." == $selectedValue || $fieldSelected !== '' ? ' selected' : ''; if($settings['showFieldLabels'] == 2) $label .= " [$field->name]"; - $option = "name 2"] = $option; } @@ -1044,8 +1060,8 @@ class InputfieldSelector extends Inputfield implements ConfigurableModule { $name = $field->name . ' ' . $this->groupIdentifier . $this->subfieldIdentifier; $label .= ' ' . $this->groupIdentifier . $this->subfieldIdentifier; $text .= ' ' . $this->groupIdentifier . $this->subfieldIdentifier; - $selected = "@$field->name." == $selectedValue ? ' selected' : ''; - $o = "message("fieldName: $fieldName"); @@ -1137,39 +1152,54 @@ class InputfieldSelector extends Inputfield implements ConfigurableModule { $this->message("selectedValue: $selectedValue"); $this->message("orChecked: $orChecked"); */ + + /** @var Templates $templates */ + $templates = $this->wire('templates'); + + /** @var Sanitizer $sanitizer */ + $sanitizer = $this->wire('sanitizer'); + if($selector) {} $field = null; $inputName = $this->attr('name') . "__value[]"; $options = array(); $out = ''; - $selectedValueEntities = $this->wire('sanitizer')->entities($selectedValue); + $selectedValueEntities = $sanitizer->entities($selectedValue); $operators = array(); $subfield = ''; $placeholder = ''; $_type = ''; // previous type, if changed $inputfield = null; - if(strpos($fieldName, '.') !== false) list($fieldName, $subfield) = explode('.', $fieldName); + $lastTemplates = $this->initTemplate ? array($this->initTemplate->id) : $this->sessionGet('lastTemplates'); + + if(strpos($fieldName, '.') !== false) list($fieldName, $subfield) = explode('.', $fieldName, 2); if(isset($this->systemFields[$fieldName]) && !$subfield) { // system field $info = $this->systemFields[$fieldName]; - if($fieldName == 'parent' && $this->initTemplate) { + + if($fieldName == 'parent' && !empty($lastTemplates)) { // allow for selection of parent, when the template of items is known //$operators = $this->operatorsByType['page']; $info['input'] = 'select'; $info['options'] = array(); - foreach($this->wire('templates')->getParentPages($this->initTemplate) as $p) { - if(!$this->wire('user')->hasPermission('page-view', $p)) continue; - $info['options'][$p->id] = $p->get('title|path'); + foreach($lastTemplates as $templateID) { + $template = $templates->get($templateID); + if(!$template) continue; + foreach($this->getParentPages($template) as $p) { + if(!$this->wire('user')->hasPermission('page-view', $p)) continue; + $info['options'][$p->id] = $p->get('title|path'); + } } asort($info['options']); + if(empty($info['options'])) unset($info['options']); } $type = $info['input']; if(isset($info['options'])) $options = $info['options']; if(!empty($info['placeholder'])) $placeholder = $info['placeholder']; if($fieldName == 'template' && $selectedValue && !ctype_digit("$selectedValue")) { - $template = $this->wire('templates')->get($this->wire('sanitizer')->name($selectedValue)); + $template = $templates->get($sanitizer->name($selectedValue)); if($template) $selectedValue = $template->id; } @@ -1352,7 +1382,7 @@ class InputfieldSelector extends Inputfield implements ConfigurableModule { $inputfield = $field->getInputfield($this->wire('pages')->newNullPage(), $field); if($inputfield instanceof InputfieldPage) { /** @var InputfieldPage $inputfield */ - $selectedValueTitle = $this->wire('sanitizer')->entities1($inputfield->getPageLabel($selectedValuePage)); + $selectedValueTitle = $sanitizer->entities1($inputfield->getPageLabel($selectedValuePage)); } } } @@ -1425,6 +1455,11 @@ class InputfieldSelector extends Inputfield implements ConfigurableModule { * */ protected function renderSelectSubfield($fieldName, $selectedValue = '', Selector $selector = null) { + + if(strpos($fieldName, '.')) list($fieldName,) = explode('.', $fieldName, 2); + + $valueLabel = $this->_('Value'); + $valueName = strtolower($valueLabel); if($fieldName == 'parent' || $fieldName == 'children') { // for parent or children, use the existing functionality in renderSelectField @@ -1437,8 +1472,12 @@ class InputfieldSelector extends Inputfield implements ConfigurableModule { 'showModifiers' => false, 'showSubfields' => false, 'customFields' => $fields, - 'exclude' => array() // prevent exclusion of 'count' - ), $selectedValue); + 'exclude' => array(), // prevent exclusion of 'count' + 'prepend' => + "", + ), $selectedValue); return $out; } @@ -1458,8 +1497,16 @@ class InputfieldSelector extends Inputfield implements ConfigurableModule { $outSub = ''; // subselector optgroup output $selectClass = trim("$this->selectClass select-subfield"); $out = "