Page MenuHomeIn-Portal Phabricator

modern-store
No OneTemporary

File Metadata

Created
Wed, Feb 12, 3:15 AM

modern-store

Index: branches/1.0.x/inc/js/list_manager.js
===================================================================
--- branches/1.0.x/inc/js/list_manager.js (revision 15091)
+++ branches/1.0.x/inc/js/list_manager.js (revision 15092)
@@ -1,338 +1,344 @@
function ListManager() {}
ListManager.containerSelector = ''; // selector id of container
ListManager.url = ''; // url to template with list contents
ListManager.urlParams = {layout: 'list'};
ListManager.filters = {};
ListManager.xhrRequests = [];
ListManager.reloadTimer = null;
ListManager.reloadTimeout = 1000;
ListManager.firstLoad = true;
ListManager.getUrl = function () {
var $url = this.url;
}
ListManager.cancelXHRRequests = function () {
while ( this.xhrRequests.length > 0 ) {
this.xhrRequests.shift().abort();
}
}
ListManager.reload = function ($now) {
this.cancelXHRRequests();
if ( $now === undefined || $now === false ) {
this.updateAnchor();
return;
}
var $container = $(this.containerSelector);
$container.fadeTo('fast', 0.7);
var $request = $.post(
this.url,
this.urlParams,
function ($data) {
$container.html($data).fadeTo('fast', 1.0);
}
);
this.xhrRequests.push($request);
}
ListManager.scheduleReload = function () {
var $me = this;
clearTimeout(this.reloadTimer);
this.reloadTimer = setTimeout(function() { $me.reload(); }, this.reloadTimeout);
}
ListManager.setParam = function ($name, $value, $reload) {
if ( $value === undefined || $value === '' ) {
// don't pass empty parameters
delete this.urlParams[$name];
}
else {
this.urlParams[$name] = $value;
}
if ( $reload === true ) {
this.reload();
}
}
ListManager.getParam = function ($name) {
return this.urlParams[$name] !== undefined ? this.urlParams[$name] : false;
}
ListManager.updateAnchor = function () {
var $query_string = [],
$url_params = sort_object(this.urlParams);
for (var $param_name in $url_params) {
$query_string.push( $param_name + '=' + encodeURIComponent(this.urlParams[$param_name]) );
}
window.location.hash = '#' + $query_string.join('&');
}
ListManager.parseAnchor = function ($anchor) {
var $query_string = {};
$anchor.replace(
new RegExp('([^?=&]+)(=([^&]*))?', 'g'),
function($0, $1, $2, $3) {
$query_string[$1] = decodeURIComponent($3);
}
);
this.urlParams = $query_string;
// sync values from url params into empty filters on first page with anchor load
this.initFilters();
this.reload(true);
}
ListManager.replaceFilter = function ($form_id, $form_html) {
$('#' + $form_id).replaceWith($form_html);
}
ListManager.replaceCounters = function ($field, $counters) {
// reset all counters in case if we got less, then are displayed right now
$('.filter-counter', '#filter-form-' + $field).text('0');
for (var $option_value in $counters) {
$('#' + jq('filter-counter[' + $field + '][' + $option_value + ']')).text($counters[$option_value]);
}
}
-ListManager.registerFilter = function ($field) {
+ListManager.registerFilter = function ($field, $url_params) {
var $manager = this,
$form = $('#filter-form-' + $field);
$manager.filters[$field] = {'type': $form.attr('filter_type')};
+ if ( $url_params !== undefined ) {
+ for (var $param_name in $url_params) {
+ this.setParam('filter_params[' + $field + '][' + $param_name + ']', $url_params[$param_name]);
+ }
+ }
+
/*$('h2:first a', $form).click(
function ($e) {
var $header = $(this).parent(),
$active = $header.hasClass('active');
$header.toggleClass('active', !$active);
$header.next().toggleClass('noactive', $active);
return false;
}
);*/
$('h2:first .reset-filter', $form).click(
function ($e) {
$manager.resetFilter($field);
return false;
}
);
switch( $manager.filters[$field].type ) {
case 'radio':
$("input[type='radio']", $form).click(
function ($e) {
$manager.updateFilterParams($field);
}
);
break;
case 'checkbox':
$("input[type='checkbox']", $form).click(
function ($e) {
var $checkbox = $(this),
$hidden_id = $checkbox.attr('id').replace(/_([\d\w-=]|)+$/, ''),
$regexp = new RegExp(jq($hidden_id) + '_([\\d\\w-=]+)');
if ( $checkbox.val() == '' ) {
// "All" checkbox
$("input[type='checkbox']", $form).not($checkbox).attr('checked', false);
}
else if ( $checkbox.is(':checked') ) {
$("input[type='checkbox'][value='']", $form).attr('checked', false);
}
update_checkbox_options($regexp, $hidden_id, $form);
$manager.updateFilterParams($field);
}
);
break;
}
}
ListManager.resetFilters = function ($reload) {
for (var $filter_field in this.filters) {
this.resetFilter($filter_field, $reload);
}
}
ListManager.resetFilter = function ($field, $reload) {
var $manager = this,
$form = $('#filter-form-' + $field);
switch( $manager.filters[$field].type ) {
case 'radio':
$("input[type='radio'][value='']", $form).attr('checked', true);
break;
case 'checkbox':
var $checkbox = $("input[type='checkbox'][value='']", $form),
$hidden_id = $checkbox.attr('id').replace(/_([\d\w-=]|)+$/, ''),
$regexp = new RegExp(jq($hidden_id) + '_([\\d\\w-=]+)');
$checkbox.attr('checked', true);
$("input[type='checkbox']", $form).not($checkbox).attr('checked', false);
update_checkbox_options($regexp, $hidden_id, $form);
break;
case 'range':
var $param_name = 'filters[' + $field + ']',
$slider = $('#' + jq($param_name + '_slider') );
$slider.slider('option', 'values', [$slider.slider('option', 'min'), $slider.slider('option', 'max')]);
$('#' + jq($param_name) ).val('');
break;
}
$manager.updateFilterParams($field, $reload);
}
ListManager.initFilters = function () {
if ( !this.firstLoad ) {
return;
}
for (var $filter_field in this.filters) {
this.initFilter($filter_field);
}
this.firstLoad = false;
}
ListManager.toggleFilter = function ($field, $toggle) {
var $form = $('#filter-form-' + $field),
$param_value = this.getParam('filters[' + $field + ']');
if ( $toggle === undefined ) {
$toggle = $param_value !== false && $param_value !== '';
}
$('h2:first', $form).toggleClass('active', $toggle);
$('h2:first .reset-filter', $form).toggle($toggle);
}
ListManager.initFilter = function ($field) {
var $values = '',
$form = $('#filter-form-' + $field),
$param_name = 'filters[' + $field + ']',
$param_value = this.getParam($param_name);
if ( $param_value === false || $param_value === '' ) {
return;
}
this.toggleFilter($field);
switch( this.filters[$field].type ) {
case 'radio':
$('#' + jq($param_name + '_' + $param_value) ).attr('checked', true);
break;
case 'checkbox':
$values = $param_value.substring(1, $param_value.length - 1).split('|');
for (var $i = 0; $i < $values.length; $i++) {
$('#' + jq($param_name + '_' + $values[$i]) ).attr('checked', true);
}
$('#' + jq($param_name + '_') ).attr('checked', false);
$('#' + jq($param_name) ).val($param_value);
break;
case 'range':
var $slider = $('#' + jq($param_name + '_slider') ),
$slider_options = {
min: $slider.slider('option', 'min'),
max: $slider.slider('option', 'max'),
step: $slider.slider('option', 'step')
};
$values = $param_value.split('-');
$values = this.invertRange($slider_options, $values[0], $values[1]);
$slider.slider('option', 'values', $values);
$('#' + jq($param_name) ).val($param_value);
break;
}
this.syncChecked( $("input[type=checkbox], input[type=radio]", '#filter-form-' + $field) );
}
ListManager.invertRange = function ($options, $min, $max) {
var $min_value = $options.min + (($options.max - $max) / $options.step) * $options.step,
$max_value = $options.max - (($min - $options.min) / $options.step) * $options.step;
return [$min_value, $max_value];
}
ListManager.syncChecked = function ($checkboxes) {
$checkboxes.each(
function () {
var $me = $(this),
$checked = $me.is(':checked'),
$dt = $me.parent(),
$dd = $dt.next();
$dt.toggleClass('active', $checked);
$dd.toggleClass('active', $checked);
}
);
}
ListManager.updateFilterParams = function ($current_field, $reload) {
var $form_fields;
for (var $field in this.filters) {
$form_fields = $('#filter-form-' + $field).serializeArray();
for (var $i = 0; $i < $form_fields.length; $i++) {
this.setParam($form_fields[$i].name, $form_fields[$i].value);
}
this.syncChecked( $("input[type=checkbox], input[type=radio]", '#filter-form-' + $field) );
}
if ( $current_field !== undefined ) {
this.toggleFilter($current_field);
this.setParam('exclude_filters', $current_field);
}
if ( $reload === undefined || $reload === true ) {
this.scheduleReload();
}
}
ListManager.init = function () {
var $manager = this;
this.firstLoad = window.location.hash.length > 1;
$('body').bind(
'anchorchanged',
function ($e, $anchor) {
$manager.parseAnchor($anchor);
}
);
}
\ No newline at end of file
Index: branches/1.0.x/elements/filters.elm.tpl
===================================================================
--- branches/1.0.x/elements/filters.elm.tpl (revision 15091)
+++ branches/1.0.x/elements/filters.elm.tpl (revision 15092)
@@ -1,151 +1,207 @@
<inp2:m_DefineElement name="filter_text_block" PrefixSpecial="item-filter" filter_type="text" is_list="0">
<input type="text" name="<inp2:FilterInputName/>" id="<inp2:FilterInputName/>" value="<inp2:FilterField/>"/>
</inp2:m_DefineElement>
<inp2:m_DefineElement name="filter_select_block" PrefixSpecial="item-filter" filter_type="select" is_list="0">
<select name="<inp2:FilterInputName/>" id="<inp2:FilterInputName/>">
</select>
</inp2:m_DefineElement>
<inp2:m_DefineElement name="filter_radio_element">
<dt<inp2:m_if check="m_Param" name="selected"> class="active"</inp2:m_if>>
<input type="radio"<inp2:m_if check="m_Param" name="selected"> checked</inp2:m_if> name="<inp2:FilterInputName/>" id="<inp2:FilterInputName/>_<inp2:m_param name='key'/>" value="<inp2:m_param name='key'/>"/>&nbsp;<label for="<inp2:FilterInputName/>_<inp2:m_param name='key'/>"><inp2:m_Param name="title"/></label>
</dt>
<dd<inp2:m_if check="m_Param" name="selected"> class="active"</inp2:m_if>>(<span id="filter-counter[<inp2:m_Param name='filter_field'/>][<inp2:m_param name='key'/>]" class="filter-counter"><inp2:m_Param name="count"/></span>)</dd>
</inp2:m_DefineElement>
<inp2:m_DefineElement name="filter_radio_block" PrefixSpecial="item-filter" filter_type="radio" is_list="0">
<dl class="manufacturer">
<inp2:ListFilterOptions render_as="filter_radio_element" pass_params="1"/>
</dl>
<div class="clear"></div>
</inp2:m_DefineElement>
<inp2:m_DefineElement name="filter_checkbox_element" form_id="">
<dt<inp2:m_if check="m_Param" name="selected"> class="active"</inp2:m_if>>
<input type="checkbox"<inp2:m_if check="m_Param" name="selected"> checked</inp2:m_if> id="<inp2:FilterInputName/>_<inp2:m_param name='key'/>" value="<inp2:m_param name='key'/>"/>&nbsp;<label for="<inp2:FilterInputName/>_<inp2:m_param name='key'/>"><inp2:m_Param name="title"/></label>
</dt>
<dd<inp2:m_if check="m_Param" name="selected"> class="active"</inp2:m_if>>(<span id="filter-counter[<inp2:m_Param name='filter_field'/>][<inp2:m_param name='key'/>]" class="filter-counter"><inp2:m_Param name="count"/></span>)</dd>
</inp2:m_DefineElement>
<inp2:m_DefineElement name="filter_checkbox_block" PrefixSpecial="item-filter" filter_type="checkbox" is_list="0">
<dl class="manufacturer">
<inp2:ListFilterOptions render_as="filter_checkbox_element" form_id="filter-form-{$filter_field}" pass_params="1"/>
</dl>
<div class="clear"></div>
<input type="hidden" name="<inp2:FilterInputName/>" id="<inp2:FilterInputName/>" value="<inp2:FilterField/>"/>
</inp2:m_DefineElement>
<inp2:m_DefineElement name="filter_range_value_element">
<li>
<!--##<inp2:m_param name='key'/>; ##--><inp2:m_Param name="title"/>
</li>
</inp2:m_DefineElement>
<inp2:m_DefineElement name="filter_range_count_element">
<li>(<span id="filter-counter[<inp2:m_Param name='filter_field'/>][<inp2:m_param name='key'/>]" class="filter-counter"><inp2:m_Param name="count"/></span>)</li>
</inp2:m_DefineElement>
<inp2:m_DefineElement name="filter_range_block" PrefixSpecial="item-filter" filter_type="range" is_list="0">
+ <div style="text-align: center; margin-bottom: 10px;">
+ <input type="text" class="field" id="<inp2:FilterInputName/>_start" style="width: 35px;"/> - <input type="text" class="field" id="<inp2:FilterInputName/>_end" style="width: 35px;"/>
+
+ <a href="#" class="grey-but" id="<inp2:FilterInputName/>_apply_btn">
+ <span>Apply</span>
+ </a>
+
+ </div>
+
<div class="range-block">
<ul class="range">
<inp2:ListFilterOptions render_as="filter_range_value_element" type="value" currency="selected" pass_params="1"/>
</ul>
<div class="slider-vertical" id="<inp2:FilterInputName/>_slider" style="height:<inp2:SliderHeight factor="26"/>px;"></div>
<ul class="range2">
<inp2:ListFilterOptions render_as="filter_range_count_element" type="count" pass_params="1"/>
</ul>
<div class="clear"></div>
</div>
<script type="text/javascript">
$(document).ready(
function() {
var $slider_options = {
min: <inp2:m_Get name="min_range_value"/>,
max: <inp2:m_Get name="max_range_value"/>,
step: <inp2:m_Get name="range_step"/>
},
$options = {
orientation: 'vertical',
range: true,
values: [<inp2:m_Get name="selected_from_range"/>, <inp2:m_Get name="selected_to_range"/>],
change: function(event, ui) {
// jQuery UI slider has inverted range - fix that here
var $selected_range = ListManager.invertRange($slider_options, ui.values[0], ui.values[1]);
if ( $selected_range[0] == $slider_options.min && $selected_range[1] == $slider_options.max ) {
$('#' + jq('<inp2:FilterInputName/>')).val('');
}
else {
$('#' + jq('<inp2:FilterInputName/>')).val($selected_range[0] + '-' + $selected_range[1]);
}
+ $( '#' + jq('<inp2:FilterInputName/>_start') ).val($selected_range[0]);
+ $( '#' + jq('<inp2:FilterInputName/>_end') ).val($selected_range[1]);
+
ListManager.updateFilterParams('<inp2:m_Param name="filter_field"/>');
}
},
$values = ListManager.invertRange($slider_options, $options.values[0], $options.values[1]);
$options.values[0] = $values[0];
$options.values[1] = $values[1];
$.extend($options, $slider_options);
$( '#' + jq('<inp2:FilterInputName/>_slider') ).slider($options);
+
+ $( '#' + jq('<inp2:FilterInputName/>_apply_btn')).click(
+ function ($e) {
+ var $remainder = 0,
+ $range_from = parseFloat( $( '#' + jq('<inp2:FilterInputName/>_start') ).val() ),
+ $range_to = parseFloat( $( '#' + jq('<inp2:FilterInputName/>_end') ).val() );
+
+ // ensure entered range is valid
+ if ( isNaN($range_from) || $range_from < $slider_options.min ) {
+ $range_from = $slider_options.min;
+ }
+
+ if ( isNaN($range_to) || $range_to > $slider_options.max ) {
+ $range_to = $slider_options.max;
+ }
+
+ // changed entered range to exactly match range steps on a slider
+ $remainder = $range_from % $slider_options.step;
+
+ if ( $remainder > 0 ) {
+ $range_from -= $remainder;
+ }
+
+ $remainder = $range_to % $slider_options.step;
+
+ if ( $remainder > 0 ) {
+ $range_to += $slider_options.step - $remainder;
+ }
+
+ // set new values to the slider
+ var $selected_range = ListManager.invertRange($slider_options, $range_from, $range_to);
+
+ $( '#' + jq('<inp2:FilterInputName/>_slider') ).slider('option', 'values', $selected_range);
+
+ return false;
+ }
+ );
+
}
);
+
+ $filter_params = {max_value: <inp2:m_Get name="max_range_value"/>};
</script>
<input type="hidden" name="<inp2:FilterInputName/>" id="<inp2:FilterInputName/>" value="<inp2:FilterField/>"/>
</inp2:m_DefineElement>
<inp2:m_DefineElement name="filter_element" PrefixSpecial="item-filter" prefix="" filter_field="" filter_type="" is_list="0">
<inp2:m_IFDataExists>
<inp2:m_ifnot check="m_Param" name="is_list">
<inp2:ReloadItem prefix="$prefix" field="$filter_field"/>
</inp2:m_ifnot>
<form action="<inp2:m_FormAction/>" id="filter-form-<inp2:m_Param name='filter_field'/>" method="post" class="filter-form" filter_field="<inp2:m_Param name='filter_field'/>" filter_type="<inp2:m_Param name='filter_type'/>">
+ <script type="text/javascript">
+ var $filter_params = {};
+ </script>
+
<div class="block alt-block">
<h2>
<em class="filter-header">
Filter by <inp2:m_Phrase name="lu_fld_{$filter_field}"/>
</em>
<a href="#" class="reset-filter" style="display: none;">
<img src="<inp2:m_TemplatesBase/>img/btn_reset_filter.png" width="18" height="18" alt="Reset Filter"/>
</a>
</h2>
<div class="block-content">
<inp2:m_RenderElement name="filter_{$filter_type}_block" pass_params="1"/>
</div>
</div>
<script type="text/javascript">
$(document).ready(
function () {
- ListManager.registerFilter('<inp2:m_Param name="filter_field"/>');
+ ListManager.registerFilter('<inp2:m_Param name="filter_field"/>', $filter_params);
}
);
</script>
</form>
</inp2:m_IFDataExists>
</inp2:m_DefineElement>
<inp2:m_DefineElement name="filter_counter_element">
'<inp2:m_Param name="key"/>': <inp2:m_Param name="count"/><inp2:m_ifnot check="m_Param" name="is_last">,</inp2:m_ifnot>
</inp2:m_DefineElement>
<inp2:m_DefineElement name="filter_counters_element">
ListManager.replaceCounters('<inp2:m_Param name="filter_field"/>', {<inp2:ListFilterOptions render_as="filter_counter_element" type="count" pass_params="1" strip_nl="2"/>});
</inp2:m_DefineElement>
<inp2:m_DefineElement name="used_filter_element">
ListManager.replaceFilter('filter-form-<inp2:m_Param name="filter_field"/>', '<inp2:m_RenderElement name="filter_element" pass_params="1" js_escape="1"/>');
</inp2:m_DefineElement>
\ No newline at end of file

Event Timeline