Вывода списка с мультивыбором в фильтре

ЕСТЬ РЕШЕНИЕ ЗАКРЫТО

Как сделать вывод в фильтре не чекбоксами, а обычным списком

#1 10 июня 2015 в 18:33
Приветствую.
Вопрос к знатокам: Как сделать вывод списка с мультивыбором в фильтре в виде обычного списка <select> а не чекбоксов.
Если просто в наглую заменить заменить функции в system/fields/listmultiple на те что содержаться в просто system/fields/list, то по этому полю фильтр работать перестает.
#2 10 июня 2015 в 18:54
Простой заменой одного файла на другой ничего не выйдет.
Если просто поменять все такие списки в нужный вам вид, то достаточно внести правки в файл \system\libs\html.helper.php строка где-то 551
  1. function html_select_multiple($name, $items, $selected=array(), $attributes=array(), $is_tree=false)
или поправить файл вашего шаблона templates\вашшаблон\assets\fields\listmultiple.tpl.php где вместо
  1. html_select_multiple($field->element_name, $items, $value, array('id'=>$field->id));
вставить свою похожую функцию или код самого селекта.
Что касается вывода только в фильтре, то лучше сделать копию поля listmultiple с нужным видом и в нужных типах контента установить тип этого поля вместо стандартного.
#3 10 июня 2015 в 21:02


Простой заменой одного файла на другой ничего не выйдет.
Если просто поменять все такие списки в нужный вам вид, то достаточно внести правки в файл \system\libs\html.helper.php строка где-то 551

  1. function html_select_multiple($name, $items, $selected=array(), $attributes=array(), $is_tree=false)
или поправить файл вашего шаблона templates\вашшаблон\assets\fields\listmultiple.tpl.php где вместо
  1. html_select_multiple($field->element_name, $items, $value, array('id'=>$field->id));
вставить свою похожую функцию или код самого селекта.
Что касается вывода только в фильтре, то лучше сделать копию поля listmultiple с нужным видом и в нужных типах контента установить тип этого поля вместо стандартного.

Loadырь
А можете немного подробнее пояснить?
Файл шаблона как я понимаю отвечает за вывод в момент создания\изменения записи. А вот в фильтр это поле выводится на основе соответствующего файла из system/fields:
  1. return html_select_multiple($this->name, $items, $value);
Вот эту строку я меняю на:
  1. return html_list_multiple($this->name, $items, $value);
html_list_multiple я сделал на в html.helper.php на основе html_select_multiple и она имеет такой вид:
  1. function html_list_multiple($name, $items, $selected='', $attributes=array()){
  2. $attr_str = html_attr_str($attributes);
  3.  
  4. $html = '<select name="'.$name.'" '.$attr_str.'>'."\n".'<option></option>'."\n";
  5.  
  6. foreach ($items as $value=>$title){
  7.  
  8. if ($selected == $value) { $sel = 'selected'; } else { $sel = ''; }
  9.  
  10. $html .= "\t" . '<option value="'.htmlspecialchars($value).'" '.$sel.'>'.htmlspecialchars($title).'</option>' . "\n";
  11.  
  12. }
  13. $html .= '</select>'."\n";
  14. return $html;
  15. }
И вот теперь выводится то оно как надо, но фильтр не работает, выводит пустое значение. Собственно если привести этот файл из system/fields к виду файла отвечающему за вывод простого списка, то все равно фильтр работать отказывается, но это я уже в начале описывал и уже осознал что это не корректный путь😊Куда копать дальше?
#4 10 июня 2015 в 21:13
Iceman, за вывод в фильтре по моему отвечает функция — public function getFilterInput($value) в файлах \system\fields\list.php и \system\fields\listbitmask.php (второй вроде за мультиселект отвечает).
В вашем html_list_multiple я не увидел слова multiple, ни в коде, ни в передаваемых атрибутах. Возможно с этим связана его неработоспособность.
#5 10 июня 2015 в 21:40


Iceman, за вывод в фильтре по моему отвечает функция — public function getFilterInput($value) в файлах \system\fields\list.php и \system\fields\listbitmask.php (второй вроде за мультиселект отвечает).
В вашем html_list_multiple я не увидел слова multiple, ни в коде, ни в передаваемых атрибутах. Возможно с этим связана его неработоспособность.

Loadырь

Насколько смог понять я, именно getFilterInput($value) в указанных Вами файлах и отвечает за вывод, а applyFilter($model, $value) собственно за обработку фильтра. В новом поле вне зависимости от того в какой вид я его привожу (как в listbitmask.php или как в list.php) фильтр работать отказывается.

С multiple я знаком, в html_list_multiple его нет потому, что мне нужен в фильтре простой список, с единственным возможным вариант выбора, возможность выбора нескольких значений нужна только в момент создания/изменения записи. В любом случае установка этого атрибута картину все равно не меняет, фильтр по этому полю работать не начинает.
#6 10 июня 2015 в 21:56
На всякий случай напишу как сейчас выглядит новое поле:
в system/fields/selectmulti.php:

  1. <?php
  2.  
  3. class fieldSelectMulti extends cmsFormField {
  4.  
  5. public $title = "Select Multiple";
  6. public $sql = 'varchar(64) NULL DEFAULT NULL';
  7. public $allow_index = true;
  8. public $filter_type = 'str';
  9.  
  10. public function getFilterInput($value) {
  11.  
  12. $items = $this->getListItems();
  13.  
  14. $value = is_array($value) ? $value : array();
  15. return html_list_multiple($this->name, $items, $value);
  16.  
  17. }
  18.  
  19. public function getRules() {
  20.  
  21. if($this->item){
  22. $this->rules[] = array('array_keys', $this->getListItems());
  23. }
  24.  
  25. return $this->rules;
  26.  
  27. }
  28.  
  29. public function parse($value){
  30.  
  31. if (!$value) { return LANG_NO; }
  32.  
  33. $items = $this->getListItems();
  34.  
  35. $html = '';
  36.  
  37. if ($items) {
  38. $pos = 0;
  39. $html .= '<ul>';
  40. foreach($items as $key => $item){
  41. if (mb_substr($value, $pos, 1) == 1){
  42. $html .= '<li>' . htmlspecialchars($item) . '</li>';
  43. }
  44. $pos++;
  45. if ($pos+1 > mb_strlen($value)) { break; }
  46. }
  47. $html .= '</ul>';
  48. }
  49.  
  50. return $html;
  51.  
  52. }
  53.  
  54. public function getListItems(){
  55.  
  56. $items = array();
  57.  
  58. if (isset($this->items)){
  59.  
  60. $items = $this->items;
  61.  
  62. } else if (isset($this->generator)) {
  63.  
  64. $generator = $this->generator;
  65. $items = $generator($this->item);
  66.  
  67. } else if ($this->hasDefaultValue()) {
  68.  
  69. $items = $this->parseListItems($this->getDefaultValue());
  70.  
  71. }
  72.  
  73. return $items;
  74.  
  75. }
  76.  
  77. public function parseListItems($string){
  78. return string_explode_list($string);
  79. }
  80.  
  81. public function parseValue($values){
  82.  
  83. if (!$values) { return false; }
  84.  
  85. $items = $this->getListItems();
  86. $value = '';
  87.  
  88. if ($items){
  89. foreach($items as $key => $title){
  90. $value .= in_array($key, $values) ? '1' : '0';
  91. }
  92. }
  93.  
  94. return $value;
  95.  
  96. }
  97.  
  98. public function store($value, $is_submitted, $old_value=null){
  99.  
  100. $value = $this->parseValue($value);
  101.  
  102. if (mb_strpos($value, "1") === false){
  103. return "";
  104. }
  105.  
  106. return $value;
  107.  
  108. }
  109.  
  110. public function applyFilter($model, $values) {
  111.  
  112. if (!is_array($values)) { return $model; }
  113.  
  114. $filter = $this->parseValue($values);
  115. $filter = str_replace("0", "_", $filter) . '%';
  116.  
  117. $model->filterLike($this->name, $filter);
  118.  
  119. return $model;
  120.  
  121. }
  122.  
  123. }
в templates/default/assets/fields/selectmulti.tpl.php:

  1. <?php if ($field->title) { ?><label for="<?php echo $field->id; ?>"><?php echo $field->title; ?></label><?php } ?>
  2. <?php
  3.  
  4. $users_model = cmsCore::getModel('users');
  5.  
  6. $items = $field->getListItems();
  7.  
  8. $selected = array();
  9.  
  10. if ($value) {
  11. if (!is_array($value)){
  12. $pos = 0;
  13. foreach($items as $key => $title){
  14. if (mb_substr($value, $pos, 1) == 1){
  15. $selected[] = $key;
  16. }
  17. $pos++;
  18. if ($pos+1 > mb_strlen($value)) { break; }
  19. }
  20. } else {
  21. $selected = $value;
  22. }
  23. }
  24.  
  25. echo html_select_multiple($field->element_name, $items, $selected, array('id'=>$field->id));
  26.  
Собственно эти файлы практически идентичны изначальным файлам списка с мультивыбором из файлов listbitmask
И в libs/html.helper.php:

  1. function html_list_multiple($name, $items, $selected='', $attributes=array()){
  2. $attr_str = html_attr_str($attributes);
  3.  
  4. $html = '<select multiple name="'.$name.'" '.$attr_str.'>'."\n".'<option></option>'."\n";
  5.  
  6. foreach ($items as $value=>$title){
  7.  
  8. if ($selected == $value) { $sel = 'selected'; } else { $sel = ''; }
  9.  
  10. $html .= "\t" . '<option value="'.htmlspecialchars($value).'" '.$sel.'>'.htmlspecialchars($title).'</option>' . "\n";
  11.  
  12. }
  13. $html .= '</select>'."\n";
  14. return $html;
  15. }
#7 11 июня 2015 в 06:32
Iceman, я бы избавился от кода который в libs/html.helper.php и перенёс его в файл поля. Это избавит вас от рутины при обновлении движка и этого файла. В итоге у вас получится свой тип поля независимый от изменения файлов движка.
#8 11 июня 2015 в 08:53


Iceman, я бы избавился от кода который в libs/html.helper.php и перенёс его в файл поля. Это избавит вас от рутины при обновлении движка и этого файла. В итоге у вас получится свой тип поля независимый от изменения файлов движка.

Loadырь

С этим согласен, перенесу. Но все же главный вопрос остался не решенным, как сделать, что бы это поле функционировало, куда копать? :)
#9 11 июня 2015 в 09:52
Если вам нужен мультисписок при создании контента и простой список при выборе в фильтре, тогда так
  1. public function applyFilter($model, $value) {
  2.  
  3. $model->filterEqual($this->name, $value);
  4.  
  5. return $model;
  6.  
  7. }
или так
  1. public function applyFilter($model, $value) {
  2.  
  3. $model->filterLike($this->name, $value);
  4.  
  5. return $model;
  6.  
  7. }
#10 11 июня 2015 в 10:35
Loadырь,
Или лыжи плох едут или даже не знаю😊
Попробовал заменить на написанное Вами, но все равно фильтр не работает, ничего не возвращает. Сейчас поле выглядит так (заменил дополнительно getFilterInput что бы нормально выводилось после применения фильтра и перенес в него функцию html_list_multiple):

  1.  
  2. <?php
  3.  
  4. class fieldSelectMulti extends cmsFormField {
  5.  
  6. public $title = "Select Multiple";
  7. public $sql = 'varchar(64) NULL DEFAULT NULL';
  8. public $allow_index = true;
  9. public $filter_type = 'str';
  10.  
  11. public function html_list_multiple($name, $items, $selected='', $attributes=array()){
  12. $attr_str = html_attr_str($attributes);
  13. $html = '<select name="'.$name.'" '.$attr_str.'>'."\n";
  14.  
  15. foreach ($items as $value=>$title){
  16. if ($selected == $value) { $sel = 'selected'; } else { $sel = ''; }
  17. $html .= "\t" . '<option value="'.htmlspecialchars($value).'" '.$sel.'>'.htmlspecialchars($title).'</option>' . "\n";
  18. }
  19. $html .= '</select>'."\n";
  20. return $html;
  21. }
  22.  
  23. public function getFilterInput($value) {
  24.  
  25. $items = $this->getListItems();
  26. $items = array(''=>'') + $items;
  27.  
  28. return $this->html_list_multiple($this->name, $items, $value);
  29.  
  30. }
  31.  
  32. public function getRules() {
  33.  
  34. if($this->item){
  35. $this->rules[] = array('array_keys', $this->getListItems());
  36. }
  37.  
  38. return $this->rules;
  39.  
  40. }
  41.  
  42. public function parse($value){
  43.  
  44. if (!$value) { return LANG_NO; }
  45.  
  46. $items = $this->getListItems();
  47.  
  48. $html = '';
  49.  
  50. if ($items) {
  51. $pos = 0;
  52. $html .= '<ul>';
  53. foreach($items as $key => $item){
  54. if (mb_substr($value, $pos, 1) == 1){
  55. $html .= '<li>' . htmlspecialchars($item) . '</li>';
  56. }
  57. $pos++;
  58. if ($pos+1 > mb_strlen($value)) { break; }
  59. }
  60. $html .= '</ul>';
  61. }
  62.  
  63. return $html;
  64.  
  65. }
  66.  
  67. public function getListItems(){
  68.  
  69. $items = array();
  70.  
  71. if (isset($this->items)){
  72.  
  73. $items = $this->items;
  74.  
  75. } else if (isset($this->generator)) {
  76.  
  77. $generator = $this->generator;
  78. $items = $generator($this->item);
  79.  
  80. } else if ($this->hasDefaultValue()) {
  81.  
  82. $items = $this->parseListItems($this->getDefaultValue());
  83.  
  84. }
  85.  
  86. return $items;
  87.  
  88. }
  89.  
  90. public function parseListItems($string){
  91. return string_explode_list($string);
  92. }
  93.  
  94. public function parseValue($values){
  95.  
  96. if (!$values) { return false; }
  97.  
  98. $items = $this->getListItems();
  99. $value = '';
  100.  
  101. if ($items){
  102. foreach($items as $key => $title){
  103. $value .= in_array($key, $values) ? '1' : '0';
  104. }
  105. }
  106.  
  107. return $value;
  108.  
  109. }
  110.  
  111. public function store($value, $is_submitted, $old_value=null){
  112.  
  113. $value = $this->parseValue($value);
  114.  
  115. if (mb_strpos($value, "1") === false){
  116. return "";
  117. }
  118.  
  119. return $value;
  120.  
  121. }
  122.  
  123. public function applyFilter($model, $value) {
  124.  
  125. $model->filterLike($this->name, $value);
  126.  
  127. return $model;
  128.  
  129. }
  130.  
  131. }
Может быть в applyFilter чего то не хватает?
#11 15 июня 2015 в 08:28
Loadырь, знатоки, отзовитесь! :)
#12 15 июня 2015 в 09:23

Приветствую.
Вопрос к знатокам: Как сделать вывод списка с мультивыбором в фильтре в виде обычного списка <select> а не чекбоксов.
Если просто в наглую заменить заменить функции в system/fields/listmultiple на те что содержаться в просто system/fields/list, то по этому полю фильтр работать перестает.

Iceman
А если попробовать не трогать движок, а поменять шаблон вывода чекбоксов — стилизовать его под селект? Например как здесь: http://stackoverflow.com/questions/17714705/how-to-use-checkbox-inside-select-option При желании и галочки можно скрыть, но с ними, IMHO, юзабельнее)))
#13 15 июня 2015 в 09:39
Мне тоже интересно! Тоже попробую поковырять
#14 15 июня 2015 в 09:46
Val, Довольно хороший вариант, но в моем случае там очень много вариантов выбора, поэтому придется ещё прикручивать поиск и скролинг, что для списков реализовано уже весьма достойными на мой взгляд скриптами на подобии chosen. А вот сворачивание чекбоксов при помощи jquery в список уже начинает себя вести как и в случае с ковырянием в движке: на вид все хорошо, но фильтр не отрабатывает.

Jestik, Есть подозрение, что в самом фильтре заложена обработка checked состояния чекбоксов и selected списка банально не обрабатывается, хотя на первый взгляд не нашел такого в функции фильтра в model.php.
Используя этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.