mirror of
https://github.com/processwire/processwire.git
synced 2025-08-12 01:34:31 +02:00
Additional updates to ProcessTemplate and InputfieldTextTags
This commit is contained in:
@@ -5,79 +5,72 @@ function InputfieldTextTags($parent) {
|
||||
var $inputs = jQuery('.InputfieldTextTagsInput:not(.selectized)', $parent);
|
||||
var $selects = jQuery('.InputfieldTextTagsSelect:not(.selectized)', $parent);
|
||||
|
||||
if($inputs.length) {
|
||||
$inputs.selectize({
|
||||
plugins: ['remove_button', 'drag_drop'],
|
||||
delimiter: ' ',
|
||||
persist: false,
|
||||
createOnBlur: true,
|
||||
submitOnReturn: false,
|
||||
create: function(input) {
|
||||
return {
|
||||
value: input,
|
||||
text: input
|
||||
}
|
||||
var defaults = {
|
||||
plugins: [ 'remove_button', 'drag_drop' ],
|
||||
delimiter: ' ',
|
||||
persist: true, // If false, items created by the user will not show up as available options once they are unselected.
|
||||
submitOnReturn: false,
|
||||
openOnFocus: true, // Show the dropdown immediately when the control receives focus.
|
||||
closeAfterSelect: true, // If true, the dropdown will be closed after a selection is made.
|
||||
copyClassesToDropdown: false,
|
||||
createOnBlur: true, // If true, when user exits the field (clicks outside of input), a new option is created and selected (if create setting is enabled).
|
||||
selectOnTab: true, // If true, the tab key will choose the currently selected item.
|
||||
maxItems: null, // The max number of items the user can select. 1 makes the control mono-selection, null allows an unlimited number of items.
|
||||
create: function(input) {
|
||||
return {
|
||||
value: input,
|
||||
text: input
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if($inputs.length) {
|
||||
$inputs.each(function() {
|
||||
$input = $(this);
|
||||
var o = JSON.parse($input.attr('data-opts'));
|
||||
var options = defaults;
|
||||
options.delimiter = o.delimiter;
|
||||
options.closeAfterSelect = o.closeAfterSelect;
|
||||
options.persist = false;
|
||||
$input.selectize(options);
|
||||
});
|
||||
}
|
||||
|
||||
if($selects.length) {
|
||||
$selects.each(function() {
|
||||
var $select = $(this);
|
||||
var configName = $select.attr('data-cfgname');
|
||||
var allowUserTags = $select.hasClass('InputfieldTextTagsSelectOnly') ? false : true;
|
||||
var tags = [];
|
||||
var o = JSON.parse($select.attr('data-opts'));
|
||||
var cfgName = typeof o.cfgName === "undefined" ? '' : o.cfgName;
|
||||
var tags = cfgName.length ? ProcessWire.config[cfgName] : o.tags;
|
||||
var tagsList = [];
|
||||
var n = 0;
|
||||
if(configName.length) {
|
||||
tags = ProcessWire.config[configName];
|
||||
} else {
|
||||
tags = $select.attr('data-tags');
|
||||
tags = JSON.parse(tags);
|
||||
}
|
||||
|
||||
for(var tag in tags) {
|
||||
var label = tags[tag];
|
||||
tagsList[n] = { value: tag, label: label };
|
||||
n++;
|
||||
}
|
||||
$select.selectize({
|
||||
plugins: ['remove_button', 'drag_drop'],
|
||||
delimiter: ' ',
|
||||
|
||||
var options = jQuery.extend(defaults, {
|
||||
allowUserTags: o.allowUserTags,
|
||||
delimiter: o.delimiter,
|
||||
closeAfterSelect: o.closeAfterSelect,
|
||||
persist: true,
|
||||
submitOnReturn: false,
|
||||
closeAfterSelect: true,
|
||||
copyClassesToDropdown: false,
|
||||
createOnBlur: true,
|
||||
maxItems: null,
|
||||
valueField: 'value',
|
||||
labelField: 'label',
|
||||
searchField: ['value', 'label'],
|
||||
searchField: [ 'value', 'label' ],
|
||||
options: tagsList,
|
||||
create: function(input) {
|
||||
return {
|
||||
value: input,
|
||||
text: input
|
||||
}
|
||||
},
|
||||
createFilter: function(input) {
|
||||
if(allowUserTags) return true;
|
||||
if(o.allowUserTags) return true;
|
||||
allow = false;
|
||||
for(var n = 0; n < tags.length; n++) {
|
||||
if(typeof tagsList[input] !== "undefined") {
|
||||
if(typeof tags[input] !== "undefined") {
|
||||
allow = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return allow;
|
||||
},
|
||||
/*
|
||||
onDropdownOpen: function($dropdown) {
|
||||
$dropdown.closest('li, .InputfieldImageEdit').css('z-index', 100);
|
||||
},
|
||||
onDropdownClose: function($dropdown) {
|
||||
$dropdown.closest('li, .InputfieldImageEdit').css('z-index', 'auto');
|
||||
},
|
||||
*/
|
||||
render: {
|
||||
item: function(item, escape) {
|
||||
if(typeof item.label === "undefined" || !item.label.length) item.label = item.value;
|
||||
@@ -88,7 +81,17 @@ function InputfieldTextTags($parent) {
|
||||
return '<div>' + escape(item.label) + '</div>';
|
||||
}
|
||||
}
|
||||
});
|
||||
/*
|
||||
onDropdownOpen: function($dropdown) {
|
||||
$dropdown.closest('li, .InputfieldImageEdit').css('z-index', 100);
|
||||
},
|
||||
onDropdownClose: function($dropdown) {
|
||||
$dropdown.closest('li, .InputfieldImageEdit').css('z-index', 'auto');
|
||||
},
|
||||
*/
|
||||
});
|
||||
|
||||
$select.selectize(options);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -1 +1 @@
|
||||
function InputfieldTextTags($parent){if(typeof $parent==="undefined")$parent=$(".InputfieldForm");var $inputs=jQuery(".InputfieldTextTagsInput:not(.selectized)",$parent);var $selects=jQuery(".InputfieldTextTagsSelect:not(.selectized)",$parent);if($inputs.length){$inputs.selectize({plugins:["remove_button","drag_drop"],delimiter:" ",persist:false,createOnBlur:true,submitOnReturn:false,create:function(input){return{value:input,text:input}}})}if($selects.length){$selects.each(function(){var $select=$(this);var configName=$select.attr("data-cfgname");var allowUserTags=$select.hasClass("InputfieldTextTagsSelectOnly")?false:true;var tags=[];var tagsList=[];var n=0;if(configName.length){tags=ProcessWire.config[configName]}else{tags=$select.attr("data-tags");tags=JSON.parse(tags)}for(var tag in tags){var label=tags[tag];tagsList[n]={value:tag,label:label};n++}$select.selectize({plugins:["remove_button","drag_drop"],delimiter:" ",persist:true,submitOnReturn:false,closeAfterSelect:true,copyClassesToDropdown:false,createOnBlur:true,maxItems:null,valueField:"value",labelField:"label",searchField:["value","label"],options:tagsList,create:function(input){return{value:input,text:input}},createFilter:function(input){if(allowUserTags)return true;allow=false;for(var n=0;n<tags.length;n++){if(typeof tagsList[input]!=="undefined"){allow=true;break}}return allow},render:{item:function(item,escape){if(typeof item.label==="undefined"||!item.label.length)item.label=item.value;return"<div>"+escape(item.label)+"</div>"},option:function(item,escape){if(typeof item.label==="undefined"||!item.label.length)item.label=item.value;return"<div>"+escape(item.label)+"</div>"}}})})}}jQuery(document).ready(function($){InputfieldTextTags();$(document).on("reloaded",".InputfieldTextTags",function(){InputfieldTextTags($(this))})});
|
||||
function InputfieldTextTags($parent){if(typeof $parent==="undefined")$parent=$(".InputfieldForm");var $inputs=jQuery(".InputfieldTextTagsInput:not(.selectized)",$parent);var $selects=jQuery(".InputfieldTextTagsSelect:not(.selectized)",$parent);var defaults={plugins:["remove_button","drag_drop"],delimiter:" ",persist:true,submitOnReturn:false,openOnFocus:true,closeAfterSelect:true,copyClassesToDropdown:false,createOnBlur:true,selectOnTab:true,maxItems:null,create:function(input){return{value:input,text:input}}};if($inputs.length){$inputs.each(function(){$input=$(this);var o=JSON.parse($input.attr("data-opts"));var options=defaults;options.delimiter=o.delimiter;options.closeAfterSelect=o.closeAfterSelect;options.persist=false;$input.selectize(options)})}if($selects.length){$selects.each(function(){var $select=$(this);var o=JSON.parse($select.attr("data-opts"));var cfgName=typeof o.cfgName==="undefined"?"":o.cfgName;var tags=cfgName.length?ProcessWire.config[cfgName]:o.tags;var tagsList=[];var n=0;for(var tag in tags){var label=tags[tag];tagsList[n]={value:tag,label:label};n++}var options=jQuery.extend(defaults,{allowUserTags:o.allowUserTags,delimiter:o.delimiter,closeAfterSelect:o.closeAfterSelect,persist:true,valueField:"value",labelField:"label",searchField:["value","label"],options:tagsList,createFilter:function(input){if(o.allowUserTags)return true;allow=false;for(var n=0;n<tags.length;n++){if(typeof tags[input]!=="undefined"){allow=true;break}}return allow},render:{item:function(item,escape){if(typeof item.label==="undefined"||!item.label.length)item.label=item.value;return"<div>"+escape(item.label)+"</div>"},option:function(item,escape){if(typeof item.label==="undefined"||!item.label.length)item.label=item.value;return"<div>"+escape(item.label)+"</div>"}}});$select.selectize(options)})}}jQuery(document).ready(function($){InputfieldTextTags();$(document).on("reloaded",".InputfieldTextTags",function(){InputfieldTextTags($(this))})});
|
@@ -22,7 +22,9 @@
|
||||
* ~~~~~
|
||||
*
|
||||
* @property array|string $tagsList Array of tags [ 'tag' => 'label' ], or newline separated string of "tag=label", or use addTag() to populate.
|
||||
* @property int|bool $allowUserTags Allow user-entered tags?
|
||||
* @property int|bool $allowUserTags Allow user-entered tags?
|
||||
* @property int|bool $closeAfterSelect Close select dropdown box after user makes selection?
|
||||
* @property string $delimiter One of 's' (for space ' '), 'p' (for pipe '|') or 'c' (for comma).
|
||||
* @property string $value
|
||||
* @property-read array $arrayValue
|
||||
*
|
||||
@@ -51,6 +53,8 @@ class InputfieldTextTags extends Inputfield
|
||||
public function __construct() {
|
||||
$this->set('tagsList', array());
|
||||
$this->set('allowUserTags', 0);
|
||||
$this->set('closeAfterSelect', 1);
|
||||
$this->set('delimiter', 's');
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
@@ -168,7 +172,7 @@ class InputfieldTextTags extends Inputfield
|
||||
$tagString = trim($tagString);
|
||||
$tagArray = array();
|
||||
if(!strlen($tagString)) return $tagArray;
|
||||
$a = explode(' ', $tagString);
|
||||
$a = explode($this->delimiter(), $tagString);
|
||||
foreach($a as $key => $tag) {
|
||||
$tag = trim("$tag");
|
||||
if(!strlen($tag)) continue;
|
||||
@@ -188,7 +192,7 @@ class InputfieldTextTags extends Inputfield
|
||||
*
|
||||
*/
|
||||
public function tagArrayToString(array $tagArray) {
|
||||
return trim(implode(' ', $tagArray));
|
||||
return trim(implode($this->delimiter(), $tagArray));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -497,20 +501,25 @@ class InputfieldTextTags extends Inputfield
|
||||
|
||||
$config = $this->wire()->config;
|
||||
$class = $this->className();
|
||||
|
||||
$opts = array(
|
||||
'allowUserTags' => $this->allowUserTags,
|
||||
'closeAfterSelect' => $this->closeAfterSelect,
|
||||
'delimiter' => $this->delimiter(),
|
||||
);
|
||||
|
||||
if($this->hasField) {
|
||||
// page editor
|
||||
$name = $class . '_' . $this->hasField->name . '__tags';
|
||||
$data = $config->$name ? $config->$name : array();
|
||||
$cfgName = $class . '_' . $this->hasField->name . '__tags';
|
||||
$data = $config->$cfgName ? $config->$cfgName : array();
|
||||
$data = array_unique(array_merge($data, $tags));
|
||||
$config->js($name, $data);
|
||||
$attrs['data-cfgname'] = $name;
|
||||
$config->js($cfgName, $data);
|
||||
$opts['cfgName'] = $cfgName;
|
||||
} else {
|
||||
// other usages
|
||||
$attrs['data-cfgname'] = '';
|
||||
$attrs['data-tags'] = json_encode($tags, JSON_UNESCAPED_UNICODE);
|
||||
$opts['tags'] = $tags;
|
||||
}
|
||||
|
||||
$attrs['data-opts'] = json_encode($opts, JSON_UNESCAPED_UNICODE);
|
||||
$attrs['class'] = trim(implode(' ', $classes));
|
||||
$attrs['value'] = $this->encodeNumericTags($this->val());
|
||||
if(empty($attrs['type'])) $attrs['type'] = 'text';
|
||||
@@ -565,7 +574,7 @@ class InputfieldTextTags extends Inputfield
|
||||
foreach($tags as $key => $tag) {
|
||||
if(ctype_digit("$tag")) $tags[$key] = "_$tag";
|
||||
}
|
||||
return $getArray ? $tags : implode(' ', $tags);
|
||||
return $getArray ? $tags : implode($this->delimiter(), $tags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -590,7 +599,7 @@ class InputfieldTextTags extends Inputfield
|
||||
}
|
||||
}
|
||||
}
|
||||
return trim(implode(' ', $tags));
|
||||
return trim(implode($this->delimiter(), $tags));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -639,7 +648,7 @@ class InputfieldTextTags extends Inputfield
|
||||
* ~~~~~
|
||||
* $field = $fields->get('tags'); // tags field using FieldtypeText
|
||||
* $tags = $page->get('tags'); // page value (string of tags, i.e. "foo bar baz")
|
||||
* $labels = InputfieldTextTags::tagsLabels($field, $tags);
|
||||
* $labels = InputfieldTextTags::tagsArray($field, $tags);
|
||||
* foreach($labels as $tag => $label) {
|
||||
* echo "<li>$tag: $label</li>";
|
||||
* }
|
||||
@@ -652,7 +661,7 @@ class InputfieldTextTags extends Inputfield
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public static function tagsLabels(Field $field, $tags = null) {
|
||||
public static function tagsArray(Field $field, $tags = null) {
|
||||
if(is_string($tags) && !strlen($tags)) return array();
|
||||
/** @var InputfieldTextTags $inputfield */
|
||||
$inputfield = $field->wire()->modules->getModule('InputfieldTextTags', array('noInit' => true));
|
||||
@@ -689,6 +698,21 @@ class InputfieldTextTags extends Inputfield
|
||||
return $labels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or set delimiter
|
||||
*
|
||||
* @param bool $getName
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
protected function delimiter($getName = false) {
|
||||
$ds = array('s' => ' ', 'c' => ',', 'p' => '|');
|
||||
$d = $this->delimiter;
|
||||
if($getName) return $d;
|
||||
if(isset($ds[$d])) return $ds[$d];
|
||||
if(in_array($d, $ds)) return $d;
|
||||
return ' ';
|
||||
}
|
||||
|
||||
/**
|
||||
* Config
|
||||
@@ -717,19 +741,12 @@ class InputfieldTextTags extends Inputfield
|
||||
return $inputfields;
|
||||
}
|
||||
|
||||
/** @var InputfieldToggle $f */
|
||||
$f = $modules->get('InputfieldToggle');
|
||||
$f->attr('name', 'allowUserTags');
|
||||
$f->label = $this->_('Allow user to enter their own tags?');
|
||||
$f->val($this->allowUserTags);
|
||||
$fieldset->add($f);
|
||||
|
||||
/** @var InputfieldTextarea $f */
|
||||
$f = $modules->get('InputfieldTextarea');
|
||||
$f->attr('name', 'tagsList');
|
||||
$f->label = $this->label = $this->_('Predefined tags');
|
||||
$f->description = $this->_('Enter predefined tags, 1 per line. To define separate tag and label, specify `tag=label` on the line.');
|
||||
$f->notes = $this->_('Tags may not contain whitespace but labels can.');
|
||||
$f->notes = $this->_('Tags may not contain the delimiter selected below but labels can.');
|
||||
$f->val($this->tagsListArrayToString($this->tagsList));
|
||||
if($languages) {
|
||||
$f->description .= ' ' . $this->_('To define separate labels per-language, re-enter each tag (with label) for each language.');
|
||||
@@ -740,6 +757,34 @@ class InputfieldTextTags extends Inputfield
|
||||
}
|
||||
$fieldset->add($f);
|
||||
|
||||
/** @var InputfieldToggle $f */
|
||||
$f = $modules->get('InputfieldToggle');
|
||||
$f->attr('name', 'allowUserTags');
|
||||
$f->label = $this->_('Allow user to enter their own tags?');
|
||||
$f->val($this->allowUserTags);
|
||||
$f->columnWidth = 33;
|
||||
$fieldset->add($f);
|
||||
|
||||
/** @var InputfieldToggle $f */
|
||||
$f = $modules->get('InputfieldToggle');
|
||||
$f->attr('name', 'closeAfterSelect');
|
||||
$f->label = $this->_('Close dropdown after each selection is made');
|
||||
$f->columnWidth = 34;
|
||||
$f->val($this->closeAfterSelect);
|
||||
$fieldset->add($f);
|
||||
|
||||
/** @var InputfieldRadios $f */
|
||||
$f = $modules->get('InputfieldRadios');
|
||||
$f->attr('name', 'delimiter');
|
||||
$f->label = $this->_('Tag delimiter');
|
||||
$f->addOption('s', $this->_('Space'));
|
||||
$f->addOption('c', $this->_('Comma'));
|
||||
$f->addOption('p', $this->_('Pipe'));
|
||||
$f->optionColumns = 1;
|
||||
$f->columnWidth = 33;
|
||||
$f->val($this->delimiter(true));
|
||||
$fieldset->add($f);
|
||||
|
||||
return $inputfields;
|
||||
}
|
||||
|
||||
|
@@ -23,7 +23,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
class ProcessTemplate extends Process {
|
||||
class ProcessTemplate extends Process implements ConfigurableModule {
|
||||
|
||||
/** @var InputfieldForm */
|
||||
protected $form;
|
||||
@@ -179,6 +179,9 @@ class ProcessTemplate extends Process {
|
||||
$caseTags = array(); // indexed by lowercase version of tag
|
||||
$collapsedTags = $this->wire()->modules->getConfig($this, 'collapsedTags');
|
||||
if(!is_array($collapsedTags)) $collapsedTags = array();
|
||||
foreach($collapsedTags as $key => $tag) {
|
||||
$collapsedTags[$key] = strtolower($tag);
|
||||
}
|
||||
|
||||
if(!$hasFilters) foreach($this->templates as $template) {
|
||||
if($showSystem && ($template->flags & Template::flagSystem)) {
|
||||
@@ -205,7 +208,6 @@ class ProcessTemplate extends Process {
|
||||
if(!isset($caseTags[$tag])) $caseTags[$tag] = $caseTag;
|
||||
}
|
||||
}
|
||||
|
||||
$tagCnt = count($templatesByTag);
|
||||
if($tagCnt > 1) {
|
||||
/** @var InputfieldWrapper $form */
|
||||
@@ -239,6 +241,13 @@ class ProcessTemplate extends Process {
|
||||
$button->addClass('add_template_button');
|
||||
$button->showInHeader();
|
||||
$out .= $button->render();
|
||||
|
||||
$button = $this->modules->get('InputfieldButton');
|
||||
$button->id = 'tags_button';
|
||||
$button->href = './tags/';
|
||||
$button->icon = 'tags';
|
||||
$button->value = $this->labels['manageTags'];
|
||||
$out .= $button->render();
|
||||
|
||||
$button = $this->modules->get('InputfieldButton');
|
||||
$button->id = 'import_button';
|
||||
@@ -3509,6 +3518,14 @@ class ProcessTemplate extends Process {
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a form allowing configuration of this Module
|
||||
*
|
||||
* @param InputfieldWrapper $inputfields
|
||||
*
|
||||
*/
|
||||
public function getModuleConfigInputfields(InputfieldWrapper $inputfields) { }
|
||||
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user