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