1 /* |
1 /** filter form, aka facets, javascript functions |
|
2 * |
2 * :organization: Logilab |
3 * :organization: Logilab |
3 * :copyright: 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
4 * :copyright: 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
4 * :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
5 * :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
5 */ |
6 */ |
6 |
7 |
7 CubicWeb.require('htmlhelpers.js'); |
8 var SELECTED_IMG = baseuri() + "data/black-check.png"; |
8 CubicWeb.require('ajax.js'); |
9 var UNSELECTED_IMG = baseuri() + "data/no-check-no-border.png"; |
9 |
10 var UNSELECTED_BORDER_IMG = baseuri() + "data/black-uncheck.png"; |
10 //============= filter form functions ========================================// |
11 |
|
12 |
11 function copyParam(origparams, newparams, param) { |
13 function copyParam(origparams, newparams, param) { |
12 var index = findValue(origparams[0], param); |
14 var index = jQuery.inArray(param, origparams[0]); |
13 if (index > -1) { |
15 if (index > - 1) { |
14 newparams[param] = origparams[1][index]; |
16 newparams[param] = origparams[1][index]; |
15 } |
17 } |
16 } |
18 } |
17 |
19 |
18 function facetFormContent(form) { |
20 |
|
21 function facetFormContent($form) { |
19 var names = []; |
22 var names = []; |
20 var values = []; |
23 var values = []; |
21 jQuery(form).find('.facet').each(function () { |
24 $form.find('.facet').each(function() { |
22 var facetName = jQuery(this).find('.facetTitle').attr('cubicweb:facetName'); |
25 var facetName = jQuery(this).find('.facetTitle').attr('cubicweb:facetName'); |
23 var facetValues = jQuery(this).find('.facetValueSelected').each(function(x) { |
26 var facetValues = jQuery(this).find('.facetValueSelected').each(function(x) { |
24 names.push(facetName); |
27 names.push(facetName); |
25 values.push(this.getAttribute('cubicweb:value')); |
28 values.push(this.getAttribute('cubicweb:value')); |
26 }); |
29 }); |
27 }); |
30 }); |
28 jQuery(form).find('input').each(function () { |
31 $form.find('input').each(function() { |
29 names.push(this.name); |
32 names.push(this.name); |
30 values.push(this.value); |
33 values.push(this.value); |
31 }); |
34 }); |
32 jQuery(form).find('select option[selected]').each(function () { |
35 $form.find('select option[selected]').each(function() { |
33 names.push(this.parentNode.name); |
36 names.push(this.parentNode.name); |
34 values.push(this.value); |
37 values.push(this.value); |
35 }); |
38 }); |
36 return [names, values]; |
39 return [names, values]; |
37 } |
40 } |
|
41 |
38 |
42 |
39 function buildRQL(divid, vid, paginate, vidargs) { |
43 function buildRQL(divid, vid, paginate, vidargs) { |
40 jQuery(CubicWeb).trigger('facets-content-loading', [divid, vid, paginate, vidargs]); |
44 jQuery(CubicWeb).trigger('facets-content-loading', [divid, vid, paginate, vidargs]); |
41 var form = getNode(divid+'Form'); |
45 var $form = $('#' + divid + 'Form'); |
42 var zipped = facetFormContent(form); |
46 var zipped = facetFormContent($form); |
43 zipped[0].push('facetargs'); |
47 zipped[0].push('facetargs'); |
44 zipped[1].push(vidargs); |
48 zipped[1].push(vidargs); |
45 var d = asyncRemoteExec('filter_build_rql', zipped[0], zipped[1]); |
49 var d = loadRemote('json', ajaxFuncArgs('filter_build_rql', null, zipped[0], zipped[1])); |
46 d.addCallback(function(result) { |
50 d.addCallback(function(result) { |
47 var rql = result[0]; |
51 var rql = result[0]; |
48 var $bkLink = jQuery('#facetBkLink'); |
52 var $bkLink = jQuery('#facetBkLink'); |
49 if ($bkLink.length) { |
53 if ($bkLink.length) { |
50 var bkPath = 'view?rql=' + escape(rql); |
54 var bkPath = 'view?rql=' + escape(rql); |
51 if (vid) { |
55 if (vid) { |
52 bkPath += '&vid=' + escape(vid); |
56 bkPath += '&vid=' + escape(vid); |
53 } |
57 } |
54 var bkUrl = $bkLink.attr('cubicweb:target') + '&path=' + escape(bkPath); |
58 var bkUrl = $bkLink.attr('cubicweb:target') + '&path=' + escape(bkPath); |
55 $bkLink.attr('href', bkUrl); |
59 $bkLink.attr('href', bkUrl); |
56 } |
60 } |
57 var toupdate = result[1]; |
61 var toupdate = result[1]; |
58 var extraparams = vidargs; |
62 var extraparams = vidargs; |
59 if (paginate) { extraparams['paginate'] = '1'; } // XXX in vidargs |
63 if (paginate) { extraparams['paginate'] = '1'; } // XXX in vidargs |
60 // copy some parameters |
64 // copy some parameters |
61 // XXX cleanup vid/divid mess |
65 // XXX cleanup vid/divid mess |
62 // if vid argument is specified , the one specified in form params will |
66 // if vid argument is specified , the one specified in form params will |
63 // be overriden by replacePageChunk |
67 // be overriden by replacePageChunk |
64 copyParam(zipped, extraparams, 'vid'); |
68 copyParam(zipped, extraparams, 'vid'); |
65 extraparams['divid'] = divid; |
69 extraparams['divid'] = divid; |
66 copyParam(zipped, extraparams, 'divid'); |
70 copyParam(zipped, extraparams, 'divid'); |
67 copyParam(zipped, extraparams, 'subvid'); |
71 copyParam(zipped, extraparams, 'subvid'); |
68 copyParam(zipped, extraparams, 'fromformfilter'); |
72 copyParam(zipped, extraparams, 'fromformfilter'); |
69 // paginate used to know if the filter box is acting, in which case we |
73 // paginate used to know if the filter box is acting, in which case we |
70 // want to reload action box to match current selection (we don't want |
74 // want to reload action box to match current selection (we don't want |
71 // this from a table filter) |
75 // this from a table filter) |
72 replacePageChunk(divid, rql, vid, extraparams, true, function() { |
76 extraparams['rql'] = rql; |
73 jQuery(CubicWeb).trigger('facets-content-loaded', [divid, rql, vid, extraparams]); |
77 if (vid) { // XXX see copyParam above. Need cleanup |
74 }); |
78 extraparams['vid'] = vid; |
75 if (paginate) { |
79 } |
76 // FIXME the edit box might not be displayed in which case we don't |
80 d = $('#' + divid).loadxhtml('json', ajaxFuncArgs('view', extraparams), |
77 // know where to put the potential new one, just skip this case |
81 null, 'swap'); |
78 // for now |
82 d.addCallback(function() { |
79 if (jQuery('#edit_box').length) { |
83 // XXX rql/vid in extraparams |
80 reloadComponent('edit_box', rql, 'boxes', 'edit_box'); |
84 jQuery(CubicWeb).trigger('facets-content-loaded', [divid, rql, vid, extraparams]); |
81 } |
85 }); |
82 if (jQuery('#breadcrumbs').length) { |
86 if (paginate) { |
83 reloadComponent('breadcrumbs', rql, 'components', 'breadcrumbs'); |
87 // FIXME the edit box might not be displayed in which case we don't |
84 } |
88 // know where to put the potential new one, just skip this case for |
85 } |
89 // now |
86 var d = asyncRemoteExec('filter_select_content', toupdate, rql); |
90 var $node = jQuery('#edit_box'); |
87 d.addCallback(function(updateMap) { |
91 if ($node.length) { |
88 for (facetId in updateMap) { |
92 $node.loadxhtml('json', ajaxFuncArgs('render', { |
89 var values = updateMap[facetId]; |
93 'rql': rql |
90 jqNode(facetId).find('.facetCheckBox').each(function () { |
94 }, |
91 var value = this.getAttribute('cubicweb:value'); |
95 'boxes', 'edit_box')); |
92 if (!values.contains(value)) { |
96 } |
93 if (!jQuery(this).hasClass('facetValueDisabled')) { |
97 $node = jQuery('#breadcrumbs') |
94 jQuery(this).addClass('facetValueDisabled'); |
98 if ($node.length) { |
95 } |
99 $node.loadxhtml('json', ajaxFuncArgs('render', { |
96 } else { |
100 'rql': rql |
97 if (jQuery(this).hasClass('facetValueDisabled')) { |
101 }, |
98 jQuery(this).removeClass('facetValueDisabled'); |
102 'components', 'breadcrumbs')); |
99 } |
103 } |
100 } |
104 } |
101 }); |
105 var d = loadRemote('json', ajaxFuncArgs('filter_select_content', null, toupdate, rql)); |
102 } |
106 d.addCallback(function(updateMap) { |
103 }); |
107 for (facetId in updateMap) { |
104 }); |
108 var values = updateMap[facetId]; |
105 } |
109 cw.jqNode(facetId).find('.facetCheckBox').each(function() { |
106 |
110 var value = this.getAttribute('cubicweb:value'); |
107 |
111 if (jQuery.inArray(value, values) == -1) { |
108 var SELECTED_IMG = baseuri()+"data/black-check.png"; |
112 if (!jQuery(this).hasClass('facetValueDisabled')) { |
109 var UNSELECTED_IMG = baseuri()+"data/no-check-no-border.png"; |
113 jQuery(this).addClass('facetValueDisabled'); |
110 var UNSELECTED_BORDER_IMG = baseuri()+"data/black-uncheck.png"; |
114 } |
|
115 } else { |
|
116 if (jQuery(this).hasClass('facetValueDisabled')) { |
|
117 jQuery(this).removeClass('facetValueDisabled'); |
|
118 } |
|
119 } |
|
120 }); |
|
121 } |
|
122 }); |
|
123 }); |
|
124 } |
|
125 |
111 |
126 |
112 function initFacetBoxEvents(root) { |
127 function initFacetBoxEvents(root) { |
113 // facetargs : (divid, vid, paginate, extraargs) |
128 // facetargs : (divid, vid, paginate, extraargs) |
114 root = root || document; |
129 root = root || document; |
115 jQuery(root).find('form').each(function () { |
130 jQuery(root).find('form').each(function() { |
116 var form = jQuery(this); |
131 var form = jQuery(this); |
117 // NOTE: don't evaluate facetargs here but in callbacks since its value |
132 // NOTE: don't evaluate facetargs here but in callbacks since its value |
118 // may changes and we must send its value when the callback is |
133 // may changes and we must send its value when the callback is |
119 // called, not when the page is initialized |
134 // called, not when the page is initialized |
120 var facetargs = form.attr('cubicweb:facetargs'); |
135 var facetargs = form.attr('cubicweb:facetargs'); |
121 if (facetargs !== undefined) { |
136 if (facetargs !== undefined) { |
122 form.submit(function() { |
137 form.submit(function() { |
123 buildRQL.apply(null, evalJSON(form.attr('cubicweb:facetargs'))); |
138 buildRQL.apply(null, cw.evalJSON(form.attr('cubicweb:facetargs'))); |
124 return false; |
139 return false; |
125 }); |
140 }); |
126 form.find('div.facet').each(function() { |
141 form.find('div.facet').each(function() { |
127 var facet = jQuery(this); |
142 var facet = jQuery(this); |
128 facet.find('div.facetCheckBox').each(function (i) { |
143 facet.find('div.facetCheckBox').each(function(i) { |
129 this.setAttribute('cubicweb:idx', i); |
144 this.setAttribute('cubicweb:idx', i); |
130 }); |
145 }); |
131 facet.find('div.facetCheckBox').click(function () { |
146 facet.find('div.facetCheckBox').click(function() { |
132 var $this = jQuery(this); |
147 var $this = jQuery(this); |
133 // NOTE : add test on the facet operator (i.e. OR, AND) |
148 // NOTE : add test on the facet operator (i.e. OR, AND) |
134 // if ($this.hasClass('facetValueDisabled')){ |
149 // if ($this.hasClass('facetValueDisabled')){ |
135 // return |
150 // return |
136 // } |
151 // } |
137 if ($this.hasClass('facetValueSelected')) { |
152 if ($this.hasClass('facetValueSelected')) { |
138 $this.removeClass('facetValueSelected'); |
153 $this.removeClass('facetValueSelected'); |
139 $this.find('img').each(function (i){ |
154 $this.find('img').each(function(i) { |
140 if (this.getAttribute('cubicweb:unselimg')){ |
155 if (this.getAttribute('cubicweb:unselimg')) { |
141 this.setAttribute('src', UNSELECTED_BORDER_IMG); |
156 this.setAttribute('src', UNSELECTED_BORDER_IMG); |
142 this.setAttribute('alt', (_('not selected'))); |
157 this.setAttribute('alt', (_('not selected'))); |
143 } |
158 } |
144 else{ |
159 else { |
145 this.setAttribute('src', UNSELECTED_IMG); |
160 this.setAttribute('src', UNSELECTED_IMG); |
146 this.setAttribute('alt', (_('not selected'))); |
161 this.setAttribute('alt', (_('not selected'))); |
147 } |
162 } |
148 }); |
163 }); |
149 var index = parseInt($this.attr('cubicweb:idx')); |
164 var index = parseInt($this.attr('cubicweb:idx')); |
150 // we dont need to move the element when cubicweb:idx == 0 |
165 // we dont need to move the element when cubicweb:idx == 0 |
151 if (index > 0){ |
166 if (index > 0) { |
152 var shift = jQuery.grep(facet.find('.facetValueSelected'), function (n) { |
167 var shift = jQuery.grep(facet.find('.facetValueSelected'), function(n) { |
153 var nindex = parseInt(n.getAttribute('cubicweb:idx')); |
168 var nindex = parseInt(n.getAttribute('cubicweb:idx')); |
154 return nindex > index; |
169 return nindex > index; |
155 }).length; |
170 }).length; |
156 index += shift; |
171 index += shift; |
157 var parent = this.parentNode; |
172 var parent = this.parentNode; |
158 var $insertAfter = jQuery(parent).find('.facetCheckBox:nth('+index+')'); |
173 var $insertAfter = jQuery(parent).find('.facetCheckBox:nth(' + index + ')'); |
159 if ( ! ($insertAfter.length == 1 && shift == 0) ) { |
174 if (! ($insertAfter.length == 1 && shift == 0)) { |
160 // only rearrange element if necessary |
175 // only rearrange element if necessary |
161 $insertAfter.after(this); |
176 $insertAfter.after(this); |
162 } |
177 } |
163 } |
178 } |
164 } else { |
179 } else { |
165 var lastSelected = facet.find('.facetValueSelected:last'); |
180 var lastSelected = facet.find('.facetValueSelected:last'); |
166 if (lastSelected.length) { |
181 if (lastSelected.length) { |
167 lastSelected.after(this); |
182 lastSelected.after(this); |
168 } else { |
183 } else { |
169 var parent = this.parentNode; |
184 var parent = this.parentNode; |
170 jQuery(parent).prepend(this); |
185 jQuery(parent).prepend(this); |
171 } |
186 } |
172 jQuery(this).addClass('facetValueSelected'); |
187 jQuery(this).addClass('facetValueSelected'); |
173 var $img = jQuery(this).find('img'); |
188 var $img = jQuery(this).find('img'); |
174 $img.attr('src', SELECTED_IMG).attr('alt', (_('selected'))); |
189 $img.attr('src', SELECTED_IMG).attr('alt', (_('selected'))); |
175 } |
190 } |
176 buildRQL.apply(null, evalJSON(form.attr('cubicweb:facetargs'))); |
191 buildRQL.apply(null, cw.evalJSON(form.attr('cubicweb:facetargs'))); |
177 facet.find('.facetBody').animate({scrollTop: 0}, ''); |
192 facet.find('.facetBody').animate({ |
178 }); |
193 scrollTop: 0 |
179 facet.find('select.facetOperator').change(function() { |
194 }, |
180 var nbselected = facet.find('div.facetValueSelected').length; |
195 ''); |
181 if (nbselected >= 2) { |
196 }); |
182 buildRQL.apply(null, evalJSON(form.attr('cubicweb:facetargs'))); |
197 facet.find('select.facetOperator').change(function() { |
183 } |
198 var nbselected = facet.find('div.facetValueSelected').length; |
184 }); |
199 if (nbselected >= 2) { |
185 facet.find('div.facetTitle').click(function() { |
200 buildRQL.apply(null, cw.evalJSON(form.attr('cubicweb:facetargs'))); |
186 facet.find('div.facetBody').toggleClass('hidden').toggleClass('opened'); |
201 } |
187 jQuery(this).toggleClass('opened'); |
202 }); |
188 }); |
203 facet.find('div.facetTitle').click(function() { |
189 |
204 facet.find('div.facetBody').toggleClass('hidden').toggleClass('opened'); |
190 }); |
205 jQuery(this).toggleClass('opened'); |
191 } |
206 }); |
192 }); |
207 |
193 } |
208 }); |
|
209 } |
|
210 }); |
|
211 } |
|
212 |
194 |
213 |
195 // trigger this function on document ready event if you provide some kind of |
214 // trigger this function on document ready event if you provide some kind of |
196 // persistent search (eg crih) |
215 // persistent search (eg crih) |
197 function reorderFacetsItems(root){ |
216 function reorderFacetsItems(root) { |
198 root = root || document; |
217 root = root || document; |
199 jQuery(root).find('form').each(function () { |
218 jQuery(root).find('form').each(function() { |
200 var form = jQuery(this); |
219 var form = jQuery(this); |
201 if (form.attr('cubicweb:facetargs')) { |
220 if (form.attr('cubicweb:facetargs')) { |
202 form.find('div.facet').each(function() { |
221 form.find('div.facet').each(function() { |
203 var facet = jQuery(this); |
222 var facet = jQuery(this); |
204 var lastSelected = null; |
223 var lastSelected = null; |
205 facet.find('div.facetCheckBox').each(function (i) { |
224 facet.find('div.facetCheckBox').each(function(i) { |
206 var $this = jQuery(this); |
225 var $this = jQuery(this); |
207 if ($this.hasClass('facetValueSelected')) { |
226 if ($this.hasClass('facetValueSelected')) { |
208 if (lastSelected) { |
227 if (lastSelected) { |
209 lastSelected.after(this); |
228 lastSelected.after(this); |
210 } else { |
229 } else { |
211 var parent = this.parentNode; |
230 var parent = this.parentNode; |
212 jQuery(parent).prepend(this); |
231 jQuery(parent).prepend(this); |
213 } |
232 } |
214 lastSelected = $this; |
233 lastSelected = $this; |
215 } |
234 } |
216 }); |
235 }); |
217 }); |
236 }); |
218 } |
237 } |
219 }); |
238 }); |
220 } |
239 } |
221 |
240 |
222 // we need to differenciate cases where initFacetBoxEvents is called |
241 |
223 // with one argument or without any argument. If we use `initFacetBoxEvents` |
242 // we need to differenciate cases where initFacetBoxEvents is called with one |
224 // as the direct callback on the jQuery.ready event, jQuery will pass some argument |
243 // argument or without any argument. If we use `initFacetBoxEvents` as the |
225 // of his, so we use this small anonymous function instead. |
244 // direct callback on the jQuery.ready event, jQuery will pass some argument of |
226 jQuery(document).ready(function() {initFacetBoxEvents();}); |
245 // his, so we use this small anonymous function instead. |
227 |
246 jQuery(document).ready(function() { |
228 CubicWeb.provide('facets.js'); |
247 initFacetBoxEvents(); |
|
248 }); |