1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-17 20:11:46 +02:00

Updates to InputfieldPage behavior of selectors containing keyword 'page' like 'field=page.id', like when using dependent selects or referring to page being edited, by adding the alternative 'field=item.id' (using 'item' rather than 'page') to refer to the repeater item. In cases where the field appears outside of a repeater item then the keyword 'item' behaves the same as 'page'.

This commit is contained in:
Ryan Cramer
2022-05-03 10:19:19 -04:00
parent 634c97aa0f
commit a32c574106
3 changed files with 59 additions and 36 deletions

View File

@@ -118,8 +118,13 @@ function initInputfieldPageDependentSelects($inputfieldPage) {
function initSelector($t) { function initSelector($t) {
var selector = $t.val(); var selector = $t.val();
var selectorHasPage = selector.indexOf('=page.') > -1; // 'page' refers to page being edited
var selectorHasItem = selector.indexOf('=item.') > -1; // 'item' refers to repeater item
// if there is no "=page." present in the selector, then this can't be a dependent select // if there is no "=page." present in the selector, then this can't be a dependent select
if(selector.indexOf('=page.') == -1) return; if(!selectorHasPage && !selectorHasItem) return;
if(selectorHasItem) selector = selector.replaceAll('=item.', '=page.');
var labelFieldName = $t.attr('data-label'); var labelFieldName = $t.attr('data-label');
var formatName = $t.attr('data-formatname'); var formatName = $t.attr('data-formatname');
@@ -140,13 +145,15 @@ function initInputfieldPageDependentSelects($inputfieldPage) {
var name = part.replace('=page.', ''); var name = part.replace('=page.', '');
var $select1 = $('#Inputfield_' + name); // see if available in page editor var $select1 = $('#Inputfield_' + name); // see if available in page editor
if(!$select1.length && $repeaterItems.length) { if((!$select1.length || selectorHasItem) && $repeaterItems.length) {
// if not available in page editor, and we are in a repeater, // if not available in page editor, or we are in a repeater,
// see if available in any of the repeaters we are nested within // see if available in any of the repeaters we are nested within
var $selectInRepeater = '';
$repeaterItems.each(function() { $repeaterItems.each(function() {
if($select1.length) return; if($selectInRepeater.length) return;
$select1 = $('#Inputfield_' + name + '_repeater' + $(this).attr('data-page')); $selectInRepeater = $('#Inputfield_' + name + '_repeater' + $(this).attr('data-page'));
}); });
if($selectInRepeater.length) $select1 = $selectInRepeater;
} }
if($select1.length < 1) continue; if($select1.length < 1) continue;

View File

@@ -1 +1 @@
function initInputfieldPage($this){$this.find("p.InputfieldPageAddButton a").click(function(){var $input=$(this).parent("p").next(".InputfieldPageAddItems");if($input.is(":visible"))$input.slideUp("fast").find(":input").val("");else $input.slideDown("fast").parents(".ui-widget-content").slice(0,1).effect("highlight",{},500);return false});initInputfieldPageDependentSelects($this)}function initInputfieldPageDependentSelects($inputfieldPage){function selectChanged($select1,$select2,selector,formatName,labelFieldName,part,changed){var v=$select1.val();if(v==null){if($select2.children().length){$select2.children().remove();$select2.change()}return}v=v.toString();v=v.replace(/,/g,"|");selector=selector.replace(part,"="+v);selector=selector.replace(/,\s*/g,"&");if(selector.indexOf("_LPID"))selector=selector.replace(/_LPID[0-9]+/g,"");var url=ProcessWire.config.urls.admin+"page/search/for?"+selector+"&limit=9999&get="+labelFieldName;if(formatName.length)url+="&format_name="+formatName;$.getJSON(url,{},function(data){var numSelected=0;$select2.children().addClass("option-tbd");for(var n=0;n<data.matches.length;n++){var selected=false;var page=data.matches[n];var label="";var $option=$select2.children("[value="+page.id+"]");if($option.length>0)selected=$option.is(":selected")||$option.is(":checked");if(selected)numSelected++;$option.remove();if(formatName.length)label=page[formatName];if(!label.length)label=page[labelFieldName];if(!label.length)label=page.name;$option=$("<option value='"+page.id+"'>"+label+"</option>");if(selected)$option.attr("selected","selected");$select2.append($option)}if(!$select2.attr("multiple")){$blankOption=$("<option value=''>&nbsp;</option>");if(!numSelected)$blankOption.attr("selected","selected");$select2.prepend($blankOption)}$select2.children(".option-tbd").remove();if(changed||$select2.closest(".InputfieldAsmSelect").length){$select2.change()}})}function initSelector($t){var selector=$t.val();if(selector.indexOf("=page.")==-1)return;var labelFieldName=$t.attr("data-label");var formatName=$t.attr("data-formatname");var $repeaterItems=$t.parents(".InputfieldRepeaterItem");if(!labelFieldName.length)$labelFieldName="name";var $wrap=$t.parents(".InputfieldPage");var $select2=$("select#"+$wrap.attr("id").replace(/^wrap_/,""));if($select2.length<1)return;var parts=selector.match(/(=page.[_a-zA-Z0-9]+)/g);for(var n=0;n<parts.length;n++){var part=parts[n];var name=part.replace("=page.","");var $select1=$("#Inputfield_"+name);if(!$select1.length&&$repeaterItems.length){$repeaterItems.each(function(){if($select1.length)return;$select1=$("#Inputfield_"+name+"_repeater"+$(this).attr("data-page"))})}if($select1.length<1)continue;$select1.change(function(){selectChanged($select1,$select2,selector,formatName,labelFieldName,part,true)});if($select1.val()&&!$select2.val()&&$select2.children('option[value!=""]').length<1){setTimeout(function(){selectChanged($select1,$select2,selector,formatName,labelFieldName,part,false)},100)}}}$inputfieldPage.find(".findPagesSelector").each(function(){initSelector($(this))})}$(document).ready(function(){$(".InputfieldPage").each(function(){initInputfieldPage($(this))});$(document).on("reloaded",".InputfieldPage",function(){initInputfieldPage($(this))})}); function initInputfieldPage($this){$this.find("p.InputfieldPageAddButton a").click(function(){var $input=$(this).parent("p").next(".InputfieldPageAddItems");if($input.is(":visible"))$input.slideUp("fast").find(":input").val("");else $input.slideDown("fast").parents(".ui-widget-content").slice(0,1).effect("highlight",{},500);return false});initInputfieldPageDependentSelects($this)}function initInputfieldPageDependentSelects($inputfieldPage){function selectChanged($select1,$select2,selector,formatName,labelFieldName,part,changed){var v=$select1.val();if(v==null){if($select2.children().length){$select2.children().remove();$select2.change()}return}v=v.toString();v=v.replace(/,/g,"|");selector=selector.replace(part,"="+v);selector=selector.replace(/,\s*/g,"&");if(selector.indexOf("_LPID"))selector=selector.replace(/_LPID[0-9]+/g,"");var url=ProcessWire.config.urls.admin+"page/search/for?"+selector+"&limit=9999&get="+labelFieldName;if(formatName.length)url+="&format_name="+formatName;$.getJSON(url,{},function(data){var numSelected=0;$select2.children().addClass("option-tbd");for(var n=0;n<data.matches.length;n++){var selected=false;var page=data.matches[n];var label="";var $option=$select2.children("[value="+page.id+"]");if($option.length>0)selected=$option.is(":selected")||$option.is(":checked");if(selected)numSelected++;$option.remove();if(formatName.length)label=page[formatName];if(!label.length)label=page[labelFieldName];if(!label.length)label=page.name;$option=$("<option value='"+page.id+"'>"+label+"</option>");if(selected)$option.attr("selected","selected");$select2.append($option)}if(!$select2.attr("multiple")){$blankOption=$("<option value=''>&nbsp;</option>");if(!numSelected)$blankOption.attr("selected","selected");$select2.prepend($blankOption)}$select2.children(".option-tbd").remove();if(changed||$select2.closest(".InputfieldAsmSelect").length){$select2.change()}})}function initSelector($t){var selector=$t.val();var selectorHasPage=selector.indexOf("=page.")>-1;var selectorHasItem=selector.indexOf("=item.")>-1;if(!selectorHasPage&&!selectorHasItem)return;if(selectorHasItem)selector=selector.replaceAll("=item.","=page.");var labelFieldName=$t.attr("data-label");var formatName=$t.attr("data-formatname");var $repeaterItems=$t.parents(".InputfieldRepeaterItem");if(!labelFieldName.length)$labelFieldName="name";var $wrap=$t.parents(".InputfieldPage");var $select2=$("select#"+$wrap.attr("id").replace(/^wrap_/,""));if($select2.length<1)return;var parts=selector.match(/(=page.[_a-zA-Z0-9]+)/g);for(var n=0;n<parts.length;n++){var part=parts[n];var name=part.replace("=page.","");var $select1=$("#Inputfield_"+name);if((!$select1.length||selectorHasItem)&&$repeaterItems.length){var $selectInRepeater="";$repeaterItems.each(function(){if($selectInRepeater.length)return;$selectInRepeater=$("#Inputfield_"+name+"_repeater"+$(this).attr("data-page"))});if($selectInRepeater.length)$select1=$selectInRepeater}if($select1.length<1)continue;$select1.change(function(){selectChanged($select1,$select2,selector,formatName,labelFieldName,part,true)});if($select1.val()&&!$select2.val()&&$select2.children('option[value!=""]').length<1){setTimeout(function(){selectChanged($select1,$select2,selector,formatName,labelFieldName,part,false)},100)}}}$inputfieldPage.find(".findPagesSelector").each(function(){initSelector($(this))})}$(document).ready(function(){$(".InputfieldPage").each(function(){initInputfieldPage($(this))});$(document).on("reloaded",".InputfieldPage",function(){initInputfieldPage($(this))})});

View File

@@ -36,7 +36,7 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
public static function getModuleInfo() { public static function getModuleInfo() {
return array( return array(
'title' => 'Page', 'title' => 'Page',
'version' => 107, 'version' => 108,
'summary' => 'Select one or more pages', 'summary' => 'Select one or more pages',
'permanent' => true, 'permanent' => true,
); );
@@ -365,7 +365,13 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
} else if($findPagesSelector) { } else if($findPagesSelector) {
// a find() selector // a find() selector
$instance = $this->processInputMode || strpos($findPagesSelector, '=page.') ? $this : null; if($this->processInputMode) {
$instance = $this;
} else if(strpos($findPagesSelector, '=page.') || strpos($findPagesSelector, '=item.')) {
$instance = $this;
} else {
$instance = null;
}
$selector = self::populateFindPagesSelector($page, $findPagesSelector, $instance); $selector = self::populateFindPagesSelector($page, $findPagesSelector, $instance);
$children = $pages->find($selector); $children = $pages->find($selector);
@@ -422,40 +428,42 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
*/ */
protected static function populateFindPagesSelector(Page $page, $selector, $inputfield = null) { protected static function populateFindPagesSelector(Page $page, $selector, $inputfield = null) {
// if an $inputfield is passed in, then we want to retrieve dependent values directly
// from the form, rather than from the $page
$repeaterWrappers = array(); // 0, 1, or 2+ if nested repeaters
/** @var InputfieldWrapper $form */
if($inputfield) {
// locate the $form
$n = 0;
$form = $inputfield;
do {
if($form instanceof InputfieldWrapper && $form->hasClass('InputfieldRepeaterItem')) {
$repeaterWrappers[] = $form;
}
$f = $form->getParent();
if($f) $form = $f;
if(++$n > 10) break;
} while($f && $f->className() != 'InputfieldForm');
} else {
$form = null;
}
// find variables identified by: page.field or page.field.subfield // find variables identified by: page.field or page.field.subfield
if(strpos($selector, '=page.') !== false) { if(strpos($selector, '=page.') !== false || strpos($selector, '=item.') !== false) {
preg_match_all('/=page\.([_.a-zA-Z0-9]+)/', $selector, $matches);
// if an $inputfield is passed in, then we want to retrieve dependent values directly
// from the form, rather than from the $page
$repeaterWrappers = array(); // 0, 1, or 2+ if nested repeaters
/** @var InputfieldWrapper $form */
if($inputfield) {
// locate the $form
$n = 0;
$form = $inputfield;
do {
if($form instanceof InputfieldWrapper && $form->hasClass('InputfieldRepeaterItem')) {
$repeaterWrappers[] = $form;
}
$f = $form->getParent();
if($f) $form = $f;
if(++$n > 10) break;
} while($f && !wireInstanceOf($f, 'InputfieldForm'));
} else {
$form = null;
}
preg_match_all('/=(page|item)\.([_.a-zA-Z0-9]+)/', $selector, $matches);
foreach($matches[0] as $key => $tag) { foreach($matches[0] as $key => $tag) {
$field = $matches[1][$key]; $type = $matches[1][$key]; // page or item
$field = $matches[2][$key];
$subfield = ''; $subfield = '';
if(strpos($field, '.')) list($field, $subfield) = explode('.', $field); if(strpos($field, '.')) list($field, $subfield) = explode('.', $field);
$value = null; $value = null;
if($form && (!$subfield || $subfield == 'id')) { if($form && (!$subfield || $subfield == 'id')) {
// attempt to get value from the form, to account for ajax changes that would not yet be reflected on the page // attempt to get value from the form, to account for ajax changes that would not yet be reflected on the page
$in = $form instanceof InputfieldWrapper ? $form->getChildByName($field) : null; $in = $form instanceof InputfieldWrapper ? $form->getChildByName($field) : null;
if($in) { if($type === 'item' && count($repeaterWrappers)) {
$value = $in->attr('value');
} else if(count($repeaterWrappers)) {
// fields in repeaters use a namespaced name attribute so match by hasField instead // fields in repeaters use a namespaced name attribute so match by hasField instead
foreach($repeaterWrappers as $repeaterWrapper) { foreach($repeaterWrappers as $repeaterWrapper) {
/** @var InputfieldWrapper $repeaterWrapper */ /** @var InputfieldWrapper $repeaterWrapper */
@@ -467,9 +475,17 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
} }
if($value !== null) break; if($value !== null) break;
} }
} else if($in) {
$value = $in->attr('value');
}
}
if(is_null($value)) {
if($type === 'page' && $page instanceof RepeaterPage) {
$value = $page->getForPageRoot()->get($field);
} else {
$value = $page->get($field);
} }
} }
if(is_null($value)) $value = $page->get($field);
if(is_object($value) && $subfield) $value = $value->$subfield; if(is_object($value) && $subfield) $value = $value->$subfield;
if(is_array($value)) $value = implode('|', $value); if(is_array($value)) $value = implode('|', $value);
if(!strlen("$value") && (!$subfield || $subfield == 'id')) $value = '-1'; // force fail if(!strlen("$value") && (!$subfield || $subfield == 'id')) $value = '-1'; // force fail