Мультисортировка в OpenCart: Часть 2

В предыдущей части мы рассмотрели добавление дополнительных способов сортировки в каталогах магазина, в этой части будет реализован сам принцип мильтисортировки.

Сразу хочу принести извинения за задержку статьи, к сожалению, в России начинают сбываться опасения правозащитников относительно цензуры в Интернете. Недавно Ростелеком по решению регионального суда вместо выборочной блокировки одного из ресурсов заблокировал всю площадку blogspot.com и ряд других ресурсов Google.

Но вернёмся к статье. Чтобы мультисортировка заработала на уровне модели, необходимо в файле .../catalog/model/catalog/product.php в теле функции getProducts весь код между переменной $sort_data = array( ... ) и условием if (isset($data['start']) || isset($data['limit'])) { ... } заключить в тело оператора else следующей конструкции:

if (isset($data['sort']) && $intersected = array_intersect((array)$data['sort'], $sort_data)) {
 $sql .= " ORDER BY ";
 foreach($intersected as $key => $value) {
  $order = 'ASC';      
  if (isset($data['order'][$key])) {
   $_order = strtoupper($data['order'][$key]);
   if ($_order == 'ASC' || $_order == 'DESC') $order = $_order;   
  } 
  if ($value == 'pd.name' || $value == 'p.model') {
   $sql .= "LCASE($value) $order,"; 
  } else {
   $sql .= $value . " $order,"; 
  }
 }
 $sql = rtrim($sql, ",");
} else {
 // Вырезанный код вставить сюда
}


В файле контроллера .../catalog/controller/product/category.php перед строкой с условием if (isset($this->request->get['page'])) { ... } добавьте следующий код:

if ($config_multisort = $this->config->get('config_multisort')) {
 $sort = explode(';', $sort);
 $order = explode(';', $order);
 $this->data['text_multisort'] = $this->language->get('text_multisort');
 $multisort = array();
 foreach($sort as $key => $type) {
  $direction = isset($order[$key]) ? $order[$key] : 'ASC';
  $multisort[] = "$type-$direction"; 
 }
 $this->data['config_multisort'] = $config_multisort;
 $this->data['multisort'] = $multisort;
}


В этом же файле после заполнения массива переменной $this->data['sorts'] добавить следующий код:

if ($config_multisort) {
 $default = $selected = $unselected = array(); 
  foreach ($this->data['sorts'] as $sorts) {
   $checked = false;   
   preg_match('/^(\w+\.)?(\w+)-(\w+)$/', $sorts['value'], $matches);
   $sorts['group'] = $matches[2];
   foreach($multisort as $key => $sorted) {
   if ($sorted == $sorts['value']) { 
    $this->data['text_sorting'] = $sorts['text'];
    $checked = true; break; 
   }  elseif (strpos($sorted, $sorts['group']) !== false) {
    $checked = true; break; 
    }
   }
   if ($sorts['group'] == 'sort_order') {
    $default[] = $sorts;
   } elseif($checked) { 
    $selected[$key][] = $sorts;
   } else { 
    $unselected[] = $sorts; 
   }
  }       
  $_selected = array();
  for($n=0; $n < count($selected); $n++) {
   $_selected = array_merge($_selected, $selected[$n]);
  }
  $this->data['sorts'] = array_merge($default, $_selected, $unselected);
}


Далее в шаблоне файла .../catalog/view/theme/default/template/product/category.tpl весь код тега <select onchange="location = this.value;"> включите в тело оператора else следующей конструкции:

<?php if ($config_multisort) { ?>
<div class="select"><span><?php if(count($multisort) > 1) { 
 echo sprintf($text_multisort, count($multisort)); } 
 else { echo $text_sorting; } ?>
</span><div class="option">
<?php $counter = 0.5;
 foreach ($sorts as $sorts) { 
 if (in_array($sorts['value'], $multisort)) { ?>
<label<?php if(intval($counter) % 2) { ?> class="group" <?php } ?>>
<input type="radio" name="<?php echo $sorts['group']; ?>" 
     value="<?php echo $sorts['value']; ?>" checked />
<span><?php echo $sorts['text']; ?></span></label>
<?php } else { ?>
<label<?php if(intval($counter) % 2) { ?> class="group" <?php } ?>>
<input type="radio" name="<?php echo $sorts['group']; ?>" 
     value="<?php echo $sorts['value']; ?>" />
<span><?php echo $sorts['text']; ?></span></label>
<?php } $counter += 0.5; } ?>
</div>
<div style="display: none;" id="multisort"><?php echo $text_multisort; ?></div>
</div>
<?php } else { ?>
 // Вырезанный код вставить сюда 
<?php } ?>


Теперь позаботимся о стиле и интерактивности. Для этого в файле стилей .../catalog/view/theme/default/stylesheet/stylesheet.css добавим следующее:

.select {
    display: inline-block; 
    border:solid 1px #CCCCCC;
}
.select > span {
    cursor: default; display: block;
    white-space: nowrap; padding: 2px 20px 2px 2px;
    background: #F8F8F8 url('../image/button-dropdown.png') right center no-repeat;
    line-height: 1.45em; height: 1.45em;
}
.select .option {
    color: black; border:solid 1px #CCCCCC;
    margin-left: -1px; position: absolute; 
    background-color:#F8F8F8;
    z-index: 10; display: none;
}
.select .option label {
    display: table-row;
}
.select .option label span{
    display: table-cell; vertical-align: middle;
    padding-right: 4px; padding-left: 2px;
}
.select .option label.group  {
    background-color:#E9E9E9; 
}
.select .option label:hover {
    color:#fff;
    background-color:#000080;
}


Интерактивность мы реализуем через JavaScript в файле .../catalog/view/javascript/common.js.
После $(document).ready(function() { добавьте следующий код:

$(document).click(function(event) { if ($(event.target).next().attr('class') !='option' && !$(event.target).parents('.option').length) { $('.option').hide(); } });

jQuery.fn.option = function() { 
 var url = 'http://' + location.host + location.pathname; var submitted = false; 
$(this).parent().width($(this).width()); $(this).parent().click(function(event) {
 if ($(this).find('.option').is(":visible")) { 
 var tagName = event.target.tagName.toLowerCase();
 var parentTag = event.target.parentNode.tagName.toLowerCase();
if( parentTag == 'label') { if( tagName == 'span' ) submitted = true;   
if( tagName == 'input' ) {   
 var radioboxes = $(this).find('input:radio'); var group = $(event.target).attr('name');
if(group == 'sort_order') { radioboxes.not('[name="sort_order"]').removeAttr('checked');
} else { radioboxes.filter('[name="sort_order"]').removeAttr('checked');}
var filters = new Array(); var sorts = new Array(); var orders = new Array();
radioboxes.filter(':checked').each(function() {
filters.push($(this).next('span').text()); var sort_order = $(this).val().split('-');
  sorts.push(sort_order[0]); orders.push(sort_order[1]);
});
if (filters.length > 1) {
var multiple = $(this).children('#multisort').text().replace('%s', filters.length);
$(this).children('span').text(multiple);
} else $(this).children('span').text($(event.target).next('span').text());
if(submitted) { var search = location.search.replace(/[?&](sort|order)=((\w+\.?\w+);?)+/ig, '');
 $(this).unbind(); $(this).find('.option').hide();
 if(sorts.length) search += '&sort=' + sorts.join(';');
 if(orders.length) search += '&order=' + orders.join(';');
 location.href = url + search.replace(/^&/,'?');     
}
}} else $(this).find('.option').hide(); } else { $(this).find('.option').show().css('display', 'table'); }});};
$('.option').option();


Стиль выше необходим для реализации элемента управления типа select, а код на языке JavaScript реализует саму работу этого элемента управления. В результате мы получим элемент управления как на рисунке ниже.



Чтобы можно было включать/отключать данный вариант сортировки, в панель администрирования добавлена опция config_multisort.

Не забудьте также определить текстовое значение переменной text_multisort для своего языка. В данном примере в файле .../catalog/language/russian/russian.php оно следующее: "Выбрано %s условия".
Теги:
GETPRODUCTS, MULTISORT, ORDER, СОРТИРОВКА
Добавлено: 26 Февраля 2015 06:03:49 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...