source: extensions/GrumPluginClasses/js/ui.categorySelector.js @ 17735

Last change on this file since 17735 was 17735, checked in by grum, 12 years ago

version 3.5.4 - fix minor bug & add new functions to framework

  • Property svn:executable set to *
File size: 57.2 KB
Line 
1/**
2 * -----------------------------------------------------------------------------
3 * file: ui.categorySelector.js
4 * file version: 1.1.1
5 * date: 2012-06-18
6 *
7 * A jQuery plugin provided by the piwigo's plugin "GrumPluginClasses"
8 *
9 * -----------------------------------------------------------------------------
10 * Author     : Grum
11 *   email    : grum@piwigo.com
12 *   website  : http://photos.grum.fr
13 *
14 *   << May the Little SpaceFrog be with you ! >>
15 * -----------------------------------------------------------------------------
16 *
17 * see ui.categorySelector.help.txt for help about this plugin
18 *
19 * :: HISTORY ::
20 *
21 * | release | date       |
22 * | 1.0.0   | 2010/10/10 | * first release
23 * |         |            |
24 * | 1.0.1   | 2010/10/14 | * fix bug on 'value' functions ':none', ':all' and
25 * |         |            |   ':invert'
26 * |         |            |
27 * |         |            | * add 'name' property
28 * |         |            |
29 * | 1.1.0   | 2011/01/12 | * checkbox moved between +/- button and text
30 * |         |            |
31 * |         |            | * dropdown list is managed like dropdown list on
32 * |         |            |   <select> object (hidden only when object loose
33 * |         |            |   focus )
34 * |         |            |
35 * |         |            | * selected values are dislayed like tags
36 * |         |            |
37 * |         |            | * add 'isValid' method
38 * |         |            |
39 * |         |            | * add 'displayPath' property
40 * |         |            |
41 * | 1.1.1   | 2012-06-18 | * fix bug with jquery 1.7.2
42 * |         |            |   . display list now works :)
43 * |         |            |
44 * |         |            | * improve memory managment
45 * |         |            |
46 * |         |            |
47 * |         |            |
48 *
49 */
50
51
52
53(
54  function($)
55  {
56    /*
57     * plugin 'public' functions
58     */
59    var publicMethods =
60    {
61      init : function (opt)
62        {
63          return this.each(function()
64            {
65              // default values for the plugin
66              var $this=$(this),
67                  timeStamp=new Date(),
68                  data = $this.data('options'),
69                  objects = $this.data('objects'),
70                  properties = $this.data('properties'),
71                  options =
72                    {
73                      autoLoad:true,
74                      galleryRoot:true,
75                      displayStatus:true,
76                      //displayNbPhotos:true,
77                      listMaxWidth:0,
78                      listMaxHeight:0,
79                      levelIndent:16,
80                      iconWidthEC:15,
81                      serverUrl:'plugins/GrumPluginClasses/gpc_ajax.php',
82                      postData:{},
83                      filter:'accessible',
84                      popup:null,
85                      change:null,
86                      load:null,
87                      multiple:false,
88                      userMode:'public',
89                      popupMode:'click',
90                      displayPath:false,
91                      downArrow:'' //'&dArr;'
92                    };
93
94              // if options given, merge it
95              // if(opt) $.extend(options, opt); ==> options are set by setters
96
97              $this.data('options', options);
98
99
100              if(!properties)
101              {
102                $this.data('properties',
103                  {
104                    objectId:'cs'+Math.ceil(timeStamp.getTime()*Math.random()),
105                    index:-1,
106                    initialized:false,
107                    selectorVisible:false,
108                    categories:[],
109                    labelStatus:['', ''],
110                    mouseOver:false,
111                    isValid:true
112                  }
113                );
114                properties=$this.data('properties');
115              }
116
117              if(!objects)
118              {
119                objects =
120                  {
121                    container:$('<div/>',
122                        {
123                          'class':'ui-category-selector',
124                          tabindex:0,
125                          css:{
126                            width:'100%'
127                          }
128                        }
129                    ).bind('click.categorySelector',
130                        function ()
131                        {
132                          privateMethods.displaySelector($this, !$this.data('properties').selectorVisible);
133                          //$(this).focus(); // if get the focus, it hide the dorp-down list.. ?
134                        }
135                      ),
136                    containerName:$('<div/>',
137                      {
138                        html: '&nbsp;',
139                        'class':'ui-category-selector-name'
140                      }
141                    ),
142                    containerList:null,
143                    containerStatus:$('<div/>',
144                      {
145                        'class':'ui-category-selector-status',
146                        css: {
147                          'float':'right',
148                          display:(options.displayStatus)?'block':'none'
149                        }
150                      }
151                    ),
152                    containerArrow:$('<div/>',
153                      {
154                        html: '&dArr;',
155                        'class':'ui-category-selector-arrow',
156                        css: {
157                          'float':'right',
158                          cursor:'pointer'
159                        }
160                      }
161                    ).bind('mousedown',
162                        function ()
163                        {
164                          $(this).addClass('ui-category-selector-arrow-active');
165                        }
166                    ).bind('mouseup',
167                        function ()
168                        {
169                          $(this).removeClass('ui-category-selector-arrow-active');
170                        }
171                    ),
172                    listContainer:$('<div/>',
173                        {
174                          html: "",
175                          'class':'ui-category-selector-list',
176                          css: {
177                            overflow:"auto",
178                            display:'none',
179                            position:'absolute'
180                          }
181                        }
182                    ),
183                    list:$('<ul/>',
184                      {
185                        css: {
186                          listStyle:'none',
187                          padding:'0px',
188                          margin:'0px'
189                        }
190                      }
191                    )
192                  };
193              }
194
195              $this.data('objects', objects);
196
197              privateMethods.setOptions($this, opt);
198
199
200              if($this.html()!='') privateMethods.setItems($this, $this.html());
201
202              $this
203                .html('')
204                .append(objects.container.append(objects.containerArrow).append(objects.containerStatus).append(objects.containerName))
205                .append(objects.listContainer.append(objects.list));
206
207            }
208          );
209        }, // init
210      destroy : function ()
211        {
212          return this.each(
213            function()
214            {
215              // default values for the plugin
216              var $this=$(this),
217                  objects = $this.data('objects');
218              objects.containerName.unbind().remove();
219              objects.containerList.unbind().remove();
220              objects.containerStatus.unbind().remove();
221              objects.containerArrow.unbind().remove();
222              objects.container.unbind().remove();
223              objects.list.children().unbind();
224              objects.listContainer.remove();
225              $(document).unbind('focusout.'+properties.objectId+' focusin.'+properties.objectId);
226              $this
227                .removeData()
228                .unbind('.categorySelector')
229                .css(
230                  {
231                    width:'',
232                    height:''
233                  }
234                );
235              delete $this;
236            }
237          );
238        }, // destroy
239
240      options: function (value)
241        {
242          return this.each(function()
243            {
244              privateMethods.setOptions($(this), value);
245            }
246          );
247        }, // autoLoad
248
249      autoLoad: function (value)
250        {
251          if(value!=null)
252          {
253            return this.each(function()
254              {
255                privateMethods.setAutoLoad($(this), value);
256              }
257            );
258          }
259          else
260          {
261            var options = this.data('options');
262
263            if(options)
264            {
265              return(options.autoLoad);
266            }
267            else
268            {
269              return(true);
270            }
271          }
272        }, // autoLoad
273
274      galleryRoot: function (value)
275        {
276          if(value!=null)
277          {
278            return this.each(function()
279              {
280                privateMethods.setGalleryRoot($(this), value);
281              }
282            );
283          }
284          else
285          {
286            var options = this.data('options');
287
288            if(options)
289            {
290              return(options.galleryRoot);
291            }
292            else
293            {
294              return(true);
295            }
296          }
297        }, // autoLoad
298
299
300      listMaxWidth: function (value)
301        {
302          if(value!=null)
303          {
304            return this.each(function()
305              {
306                privateMethods.setListMaxWidth($(this), value);
307              }
308            );
309          }
310          else
311          {
312            var options = this.data('options');
313
314            if(options)
315            {
316              return(options.listMaxWidth);
317            }
318            else
319            {
320              return(0);
321            }
322          }
323        }, // listMaxWidth
324
325      listMaxHeight: function (value)
326        {
327          if(value!=null)
328          {
329            return this.each(function()
330              {
331                privateMethods.setListMaxHeight($(this), value);
332              }
333            );
334          }
335          else
336          {
337            var options = this.data('options');
338
339            if(options)
340            {
341              return(options.listMaxHeight);
342            }
343            else
344            {
345              return(0);
346            }
347          }
348        }, // listMaxHeight
349
350      displayStatus: function (value)
351        {
352          if(value!=null)
353          {
354            return this.each(function()
355              {
356                privateMethods.setDisplayStatus($(this), value);
357              }
358            );
359          }
360          else
361          {
362            var options = this.data('options');
363
364            if(options)
365            {
366              return(options.displayStatus);
367            }
368            else
369            {
370              return(true);
371            }
372          }
373        }, // displayStatus
374
375      levelIndent: function (value)
376        {
377          if(value!=null)
378          {
379            return this.each(function()
380              {
381                privateMethods.setLevelIndent($(this), value);
382              }
383            );
384          }
385          else
386          {
387            var options = this.data('options');
388
389            if(options)
390            {
391              return(options.levelIndent);
392            }
393            else
394            {
395              return(0);
396            }
397          }
398        }, // levelIndent
399
400      serverUrl: function (value)
401        {
402          if(value!=null)
403          {
404            return this.each(function()
405              {
406                privateMethods.setServerUrl($(this), value);
407              }
408            );
409          }
410          else
411          {
412            var options = this.data('options');
413
414            if(options)
415            {
416              return(options.serverUrl);
417            }
418            else
419            {
420              return('');
421            }
422          }
423        }, // serverUrl
424
425      postData: function (value)
426        {
427          if(value!=null)
428          {
429            // set selected value
430            return(
431              this.each(
432                function()
433                {
434                  privateMethods.setPostData($(this), value, true);
435                }
436              )
437            );
438          }
439          else
440          {
441            var options=this.data('options');
442            return(options.postData);
443          }
444        }, // postData
445
446      filter: function (value)
447        {
448          if(value!=null)
449          {
450            return this.each(function()
451              {
452                privateMethods.setFilter($(this), value);
453              }
454            );
455          }
456          else
457          {
458            var options = this.data('options');
459
460            if(options)
461            {
462              return(options.filter);
463            }
464            else
465            {
466              return('');
467            }
468          }
469        }, // filter
470
471      collapse: function (value)
472        {
473          return this.each(function()
474            {
475              if(!value) value=':all';
476              privateMethods.setExpandCollapse($(this), value, 'C');
477            }
478          );
479        }, // collapse
480
481      expand: function (value)
482        {
483          return this.each(function()
484            {
485              if(!value) value=':all';
486              privateMethods.setExpandCollapse($(this), value, 'E');
487            }
488          );
489        }, // expand
490
491      iconWidthEC: function (value)
492        {
493          if(value!=null)
494          {
495            return this.each(function()
496              {
497                privateMethods.setIconWidthEC($(this), value);
498              }
499            );
500          }
501          else
502          {
503            var options = this.data('options');
504
505            if(options)
506            {
507              return(options.iconWidthEC);
508            }
509            else
510            {
511              return(0);
512            }
513          }
514        }, // iconWidthEC
515
516      userMode: function (value)
517        {
518          if(value!=null)
519          {
520            return this.each(function()
521              {
522                privateMethods.setUserMode($(this), value);
523              }
524            );
525          }
526          else
527          {
528            var options = this.data('options');
529
530            if(options)
531            {
532              return(options.userMode);
533            }
534            else
535            {
536              return(0);
537            }
538          }
539        }, // userMode
540
541      name: function ()
542        {
543          var options=this.data('options'),
544              properties=this.data('properties');
545
546          if(!options.multiple)
547          {
548            return(properties.categories[properties.index].name);
549          }
550          else
551          {
552            var listNames=[];
553            for(var i=0;i<properties.index.length;i++)
554            {
555              listNames.push(properties.categories[properties.index[i]].name);
556            }
557            return(listNames);
558          }
559        }, // userMode
560
561      popupMode: function (value)
562        {
563          if(value!=null)
564          {
565            return this.each(function()
566              {
567                privateMethods.setPopupMode($(this), value);
568              }
569            );
570          }
571          else
572          {
573            var options = this.data('options');
574
575            if(options)
576            {
577              return(options.popupMode);
578            }
579            else
580            {
581              return(0);
582            }
583          }
584        }, // popupMode
585
586      displayPath: function (value)
587        {
588          if(value!=null)
589          {
590            return this.each(function()
591              {
592                privateMethods.setDisplayPath($(this), value);
593              }
594            );
595          }
596          else
597          {
598            var options = this.data('options');
599
600            if(options)
601            {
602              return(options.displayPath);
603            }
604            else
605            {
606              return(0);
607            }
608          }
609        }, // displayPath
610
611      downArrow: function (value)
612        {
613          if(value!=null)
614          {
615            return this.each(function()
616              {
617                privateMethods.setDownArrow($(this), value);
618              }
619            );
620          }
621          else
622          {
623            var options = this.data('options');
624
625            if(options)
626            {
627              return(options.downArrow);
628            }
629            else
630            {
631              return('');
632            }
633          }
634        }, // downArrow
635
636      value: function (value)
637        {
638          if(value!=null)
639          {
640            // set selected value
641            return this.each(function()
642              {
643                privateMethods.setValue($(this), value);
644              }
645            );
646          }
647          else
648          {
649            // return the selected value
650            var properties=this.data('properties'),
651                options = this.data('options');
652
653            if(properties && properties.index!=null && !options.multiple && properties.index>-1 && properties.index<properties.categories.length)
654            {
655              return(properties.categories[properties.index].id);
656            }
657            else if(properties && properties.index!=null && options.multiple)
658            {
659              var returned=[];
660              for(var i=0;i<properties.index.length;i++)
661              {
662                if(properties.index[i]>-1 && properties.index[i]<properties.categories.length)
663                  returned.push(properties.categories[properties.index[i]].id);
664              }
665              return(returned);
666            }
667            else
668            {
669              return(null);
670            }
671          }
672        }, // value
673
674      isValid: function (value)
675        {
676          if(value!=null)
677          {
678            return this.each(function()
679              {
680                privateMethods.setIsValid($(this), value);
681              }
682            );
683          }
684          else
685          {
686            var properties=this.data('properties');
687            return(properties.isValid);
688          }
689        }, // isValid
690
691      load: function (value)
692        {
693          /*
694           * two functionnalities :
695           *  - if value is set, use it to set the load event function
696           *  - if no value, loads data from server
697           */
698          if(value && $.isFunction(value))
699          {
700            // set selected value
701            return this.each(function()
702              {
703                privateMethods.setEventLoad($(this), value);
704              }
705            );
706          }
707          else
708          {
709            // loads data from server
710            privateMethods.load(this);
711          }
712        },
713
714      popup: function (value)
715        {
716          if(value && $.isFunction(value))
717          {
718            // set selected value
719            return this.each(function()
720              {
721                privateMethods.setEventPopup($(this), value);
722              }
723            );
724          }
725          else
726          {
727            // return the selected value
728            var options=this.data('options');
729
730            if(options)
731            {
732              return(options.popup);
733            }
734            else
735            {
736              return(null);
737            }
738          }
739        }, // popup
740      change: function (value)
741        {
742          if(value && $.isFunction(value))
743          {
744            // set selected value
745            return this.each(function()
746              {
747                privateMethods.setEventChange($(this), value);
748              }
749            );
750          }
751          else
752          {
753            // return the selected value
754            var options=this.data('options');
755
756            if(options)
757            {
758              return(options.change);
759            }
760            else
761            {
762              return(null);
763            }
764          }
765        }, // popup
766
767      numberOfCategories: function ()
768        {
769          var properties=this.data('properties');
770
771          if(properties)
772          {
773            return(properties.categories.length);
774          }
775          else
776          {
777            return(null);
778          }
779        }, // numberOfCategories
780
781      properties: function (value)
782        {
783          var properties=this.data('properties'),
784              options=this.data('options');
785
786          if(properties && value==':first' && properties.categories.length>0)
787          {
788            return(properties.categories[0]);
789          }
790          else if(properties && properties.index!=null && (value==':selected' || value==null) && properties.categories.length>0)
791          {
792            if(!options.multiple && properties.index>-1 && properties.index<properties.categories.length)
793            {
794              return(properties.categories[properties.index]);
795            }
796            else if(options.multiple)
797            {
798              var returned=[];
799              for(var i=0;i<properties.index.length;i++)
800              {
801                if(properties.index[i]>-1 && properties.index<properties.categories.length)
802                  returned.push(properties.categories[properties.index[i]]);
803              }
804              return(returned);
805            }
806            return(null);
807          }
808          else if(properties && value>-1)
809          {
810            var index=privateMethods.findIndexByValue(this, value);
811            if(index>-1)
812            {
813              return(properties.categories[index]);
814            }
815            return(null);
816          }
817          else
818          {
819            return(null);
820          }
821        }, // numberOfCategories
822    }; // methods
823
824
825    /*
826     * plugin 'private' methods
827     */
828    var privateMethods =
829    {
830      setOptions : function (object, value)
831        {
832          var properties=object.data('properties'),
833              options=object.data('options');
834
835          if(!$.isPlainObject(value)) return(false);
836
837          properties.initialized=false;
838
839          privateMethods.setAutoLoad(object, (value.autoLoad!=null)?value.autoLoad:options.autoLoad);
840          privateMethods.setGalleryRoot(object, (value.galleryRoot!=null)?value.galleryRoot:options.galleryRoot);
841          privateMethods.setDisplayStatus(object, (value.displayStatus!=null)?value.displayStatus:options.displayStatus);
842          privateMethods.setListMaxWidth(object, (value.listMaxWidth!=null)?value.listMaxWidth:options.listMaxWidth);
843          privateMethods.setListMaxHeight(object, (value.listMaxHeight!=null)?value.listMaxHeight:options.listMaxHeight);
844          privateMethods.setLevelIndent(object, (value.levelIndent!=null)?value.levelIndent:options.levelIndent);
845          privateMethods.setIconWidthEC(object, (value.iconWidthEC!=null)?value.iconWidthEC:options.iconWidthEC);
846          privateMethods.setPostData(object, (value.postData!=null)?value.postData:options.postData);
847          privateMethods.setServerUrl(object, (value.serverUrl!=null)?value.serverUrl:options.serverUrl);
848          privateMethods.setFilter(object, (value.filter!=null)?value.filter:options.filter);
849          privateMethods.setUserMode(object, (value.userMode!=null)?value.userMode:options.userMode);
850          privateMethods.setPopupMode(object, (value.popupMode!=null)?value.popupMode:options.popupMode);
851          privateMethods.setDisplayPath(object, (value.displayPath!=null)?value.displayPath:options.displayPath);
852          privateMethods.setDownArrow(object, (value.downArrow!=null)?value.downArrow:options.downArrow);
853          privateMethods.setEventPopup(object, (value.popup!=null)?value.popup:options.popup);
854          privateMethods.setEventChange(object, (value.change!=null)?value.change:options.change);
855          privateMethods.setEventLoad(object, (value.load!=null)?value.load:options.load);
856          privateMethods.setMultiple(object, (value.multiple!=null)?value.multiple:options.multiple); // can be set only at the initialization
857
858          if(options.autoLoad) privateMethods.load(object);
859
860          properties.initialized=true;
861        },
862
863      setIsValid : function (object, value)
864        {
865          var objects=object.data('objects'),
866              properties=object.data('properties');
867
868          if(properties.isValid!=value)
869          {
870            properties.isValid=value;
871            if(properties.isValid)
872            {
873              objects.container.removeClass('ui-error');
874            }
875            else
876            {
877              objects.container.addClass('ui-error');
878            }
879          }
880          return(properties.isValid);
881        },
882
883      setAutoLoad : function (object, value)
884        {
885          var options=object.data('options'),
886              properties=object.data('properties');
887
888          if((!properties.initialized || options.autoLoad!=value) && (value==true || value==false))
889          {
890            options.autoLoad=value;
891          }
892          return(options.autoLoad);
893        },
894
895      setGalleryRoot : function (object, value)
896        {
897          var options=object.data('options'),
898              properties=object.data('properties');
899
900          if((!properties.initialized || options.galleryRoot!=value) && (value==true || value==false))
901          {
902            options.galleryRoot=value;
903            if(options.autoLoad && properties.initialized) privateMethods.load(object);
904          }
905          return(options.galleryRoot);
906        },
907
908      setListMaxWidth : function (object, value)
909        {
910          var options=object.data('options'),
911              properties=object.data('properties'),
912              objects=object.data('objects');
913
914          if((!properties.initialized || options.listMaxWidth!=value) && value>=0)
915          {
916            options.listMaxWidth=value;
917            if(options.listMaxWidth>0)
918            {
919              objects.listContainer.css('max-width', options.listMaxWidth+'px');
920            }
921            else
922            {
923              objects.listContainer.css('max-width', '');
924            }
925          }
926          return(options.listMaxWidth);
927        },
928
929      setListMaxHeight : function (object, value)
930        {
931          var options=object.data('options'),
932              properties=object.data('properties'),
933              objects=object.data('objects');
934
935          if((!properties.initialized || options.listMaxHeight!=value) && value>=0)
936          {
937            options.listMaxHeight=value;
938            if(options.listMaxHeight>0)
939            {
940              objects.listContainer.css('max-height', options.listMaxHeight+'px');
941            }
942            else
943            {
944              objects.listContainer.css('max-height', '');
945            }
946          }
947          return(options.listMaxHeight);
948        },
949
950      setDisplayStatus : function (object, value)
951        {
952          var options=object.data('options'),
953              properties=object.data('properties'),
954              objects=object.data('objects');
955
956          if((!properties.initialized || options.displayStatus!=value) && (value==true || value==false))
957          {
958            options.displayStatus=value;
959            if(options.displayStatus)
960            {
961              object.find('.ui-category-selector-status').show();
962            }
963            else
964            {
965              object.find('.ui-category-selector-status').hide();
966            }
967          }
968          return(options.displayStatus);
969        },
970
971      setLevelIndent : function (object, value)
972        {
973          var options=object.data('options'),
974              properties=object.data('properties'),
975              objects=object.data('objects');
976
977          if((!properties.initialized || options.levelIndent!=value) && value>=0)
978          {
979            options.levelIndent=value;
980            objects.list.find('.ui-category-selector-item').each(
981              function ()
982              {
983                $(this).css('padding-left', (options.iconWidthEC+$(this).attr('level')*options.levelIndent)+'px');
984              }
985            );
986          }
987          return(options.levelIndent);
988        },
989
990      setServerUrl : function (object, value)
991        {
992          var options=object.data('options'),
993              properties=object.data('properties');
994
995          if(!properties.initialized || options.serverUrl!=value)
996          {
997            options.serverUrl=value;
998            if(options.autoLoad && properties.initialized) privateMethods.load(object);
999          }
1000          return(options.serverUrl);
1001        },
1002
1003      setPostData : function (object, value)
1004        {
1005          var properties=object.data('properties'),
1006              options=object.data('options');
1007
1008          if(!properties.initialized || value!=options.postData)
1009          {
1010            options.postData=value;
1011          }
1012
1013          return(options.postData);
1014        }, // setPostData
1015
1016      setFilter : function (object, value)
1017        {
1018          var options=object.data('options'),
1019              properties=object.data('properties');
1020
1021          if((!properties.initialized || options.filter!=value) && (value=='none' || value=='accessible' || value=='public'))
1022          {
1023            options.filter=value;
1024            if(options.autoLoad && properties.initialized) privateMethods.load(object);
1025          }
1026          return(options.filter);
1027        },
1028
1029      setIconWidthEC : function (object, value)
1030        {
1031          var options=object.data('options'),
1032              properties=object.data('properties'),
1033              objects=object.data('objects');
1034
1035          if((!properties.initialized || options.iconWidthEC!=value) && value>=0)
1036          {
1037            options.iconWidthEC=value;
1038            objects.list.find('.ui-category-selector-item').each(
1039              function ()
1040              {
1041                $(this).css('padding-left', (options.iconWidthEC+$(this).attr('level')*options.levelIndent)+'px');
1042              }
1043            );
1044          }
1045          return(options.iconWidthEC);
1046        },
1047
1048      setMultiple : function (object, value)
1049        {
1050          var options=object.data('options'),
1051              properties=object.data('properties'),
1052              objects=object.data('objects');
1053
1054          if((!properties.initialized || options.multiple!=value) && (value==true || value==false))
1055          {
1056            if(!value)
1057            {
1058              properties.index=-1;
1059              if(objects.containerList!=null)
1060              {
1061                objects.containerList.remove();
1062                objects.containerList=null;
1063              }
1064            }
1065            else
1066            {
1067              properties.index=[];
1068              objects.listContainer.addClass('ui-category-selector-multiple');
1069              if(objects.containerList==null)
1070              {
1071                objects.containerList=$('<ul/>',
1072                  {
1073                    css: {
1074                      listStyle:'none',
1075                      padding:'0px',
1076                      margin:'0px',
1077                      overflow:"auto"
1078                    },
1079                    html:'<li>&nbsp;</li>'
1080                  }
1081                );
1082                objects.containerName.html('').append(objects.containerList);
1083              }
1084            }
1085            options.multiple=value;
1086          }
1087          return(options.multiple);
1088        }, //setMultiple
1089
1090      setUserMode : function (object, value)
1091        {
1092          var options=object.data('options'),
1093              properties=object.data('properties');
1094
1095          if((!properties.initialized || options.userMode!=value) && (value=='admin' || value=='public'))
1096          {
1097            options.userMode=value;
1098            if(options.autoLoad && properties.initialized) privateMethods.load(object);
1099          }
1100          return(options.userMode);
1101        }, //setUserMode
1102
1103      setPopupMode : function (object, value)
1104        {
1105          var options=object.data('options'),
1106              properties=object.data('properties'),
1107              objects=object.data('objects');
1108
1109          if((!properties.initialized || options.popupMode!=value) && (value=='click' || value=='mouseout'))
1110          {
1111            options.popupMode=value;
1112
1113            if(value=='mouseout')
1114            {
1115              objects.listContainer
1116                .unbind('mouseleave.categorySelector')
1117                .unbind('mouseenter.categorySelector')
1118                .bind('mouseleave.categorySelector',
1119                  function ()
1120                  {
1121                    privateMethods.displaySelector(object, false);
1122                  }
1123                );
1124            }
1125            else
1126            {
1127              objects.listContainer
1128                .unbind('mouseleave.categorySelector')
1129                .bind('mouseleave.categorySelector',
1130                  function ()
1131                  {
1132                    properties.mouseOver=false;
1133                  }
1134                )
1135                .bind('mouseenter.categorySelector',
1136                  function ()
1137                  {
1138                    properties.mouseOver=true;
1139                  }
1140                );
1141              $(document).bind('focusout.'+properties.objectId+' focusin.'+properties.objectId,
1142                function (event)
1143                {
1144                  if(!properties.mouseOver) privateMethods.displaySelector(object, false);
1145                }
1146              );
1147            }
1148          }
1149          return(options.popupMode);
1150        }, //setUserMode
1151
1152
1153      setDisplayPath : function (object, value)
1154        {
1155          var options=object.data('options'),
1156              properties=object.data('properties'),
1157              objects=object.data('objects');
1158
1159          if((!properties.initialized || options.displayPath!=value) && (value==true || value==false))
1160          {
1161            options.displayPath=value;
1162
1163          }
1164          return(options.displayPath);
1165        }, //setDisplayPath
1166
1167      setDownArrow : function (object, value)
1168        {
1169          var options=object.data('options'),
1170              properties=object.data('properties'),
1171              objects=object.data('objects');
1172
1173          if(!properties.initialized || options.downArrow!=value)
1174          {
1175            options.downArrow=value;
1176            objects.containerArrow.html(options.downArrow);
1177          }
1178          return(options.downArrow);
1179        }, //setDownArrow
1180
1181
1182      setItems : function (object, value)
1183        {
1184          var properties=object.data('properties'),
1185              options=object.data('options'),
1186              objects=object.data('objects');
1187
1188          if(value=='' || value==null)
1189          {
1190            value={
1191              status:['',''],
1192              categories:[]
1193            }
1194          }
1195          else if($.isArray(value))
1196          {
1197            value={
1198              status:'public',
1199              categories:value
1200            }
1201          }
1202          else
1203          {
1204            try
1205            {
1206              value=$.parseJSON($.trim(value));
1207            }
1208            catch (e)
1209            {
1210              return(false);
1211            }
1212          }
1213
1214          properties.labelStatus=value.status;
1215          privateMethods.listClear(object);
1216          if(value.categories.length>0) privateMethods.listAddItems(object, value.categories, objects.list);
1217
1218          properties.initialized=false;
1219          if(options.multiple)
1220          {
1221            privateMethods.setValue(object, ':none');
1222          }
1223          else
1224          {
1225            privateMethods.setValue(object, ':first');
1226          }
1227          properties.initialized=true;
1228
1229          if(options.load) object.trigger('categorySelectorLoad');
1230        },
1231
1232      /**
1233       * usage : see notes on the header file
1234       *
1235       * @param jQuery object : the jQuery object
1236       * @param String value : the filter
1237       * @param String mode : 'C' for collapse, 'E' for expand
1238       */
1239      setExpandCollapse : function (object, value, mode)
1240        {
1241          var objects=object.data('objects');
1242
1243          /*
1244           *  target[1] = ':all' or catId
1245           * target[2] = '=' or '<' or '>' or '+'
1246           * target[3] = level
1247           */
1248          re=/^(?:(:all)(?:(=|<|>|\+)(\d+))?)|(?:(\d+)(<|>|\+))?$/i;
1249          target=re.exec(value);
1250
1251          if(target!=null)
1252          {
1253            switch(mode)
1254            {
1255              case 'C':
1256                applyExpandCollapse=privateMethods.applyCollapse;
1257                break;
1258              case 'E':
1259                applyExpandCollapse=privateMethods.applyExpand;
1260                break;
1261            }
1262
1263
1264            if(target[1]==':all')
1265            {
1266              objects.list.find('.ui-category-selector-expandable-item, .ui-category-selector-collapsable-item').each(applyExpandCollapse);
1267            }
1268            else if(target[4]!=null)
1269            {
1270              switch(target[5])
1271              {
1272                case '+':
1273                  objects.list.find('.ui-category-selector-expandable-item, .ui-category-selector-collapsable-item').each(privateMethods.applyCollapse);
1274                  objects.list.find(':has([catId='+target[4]+'])').prev().each(privateMethods.applyExpand);
1275                  objects.list.find('[catId='+target[4]+']').each(applyExpandCollapse);
1276                  break;
1277                case '>':
1278                  objects.list.find('[catId='+target[4]+'] + ul').find('.ui-category-selector-expandable-item, .ui-category-selector-collapsable-item').each(applyExpandCollapse);
1279                  objects.list.find('[catId='+target[4]+']').each(applyExpandCollapse);
1280                  break;
1281                case '<':
1282                  objects.list.find(':has([catId='+target[4]+'])').prev().each(applyExpandCollapse);
1283                  objects.list.find('[catId='+target[4]+']').each(applyExpandCollapse);
1284                  break;
1285                default:
1286                  objects.list.find('[catId='+target[4]+']').each(applyExpandCollapse);
1287                  break;
1288              }
1289            }
1290
1291          }
1292        }, //setExpandCollapse
1293
1294      applyExpand : function (index, domElt)
1295        {
1296          privateMethods.applyExpandCollapse(index, domElt, 'E');
1297        }, //applyExpand
1298      applyCollapse : function (index, domElt)
1299        {
1300          privateMethods.applyExpandCollapse(index, domElt, 'C');
1301        }, //applyCollapse
1302
1303      /**
1304       * used by the setExpandCollapse function
1305       * not aimed to be used directly
1306       */
1307      applyExpandCollapse : function (index, domElt, mode)
1308              {
1309                action='';
1310                var $domElt=$(domElt);
1311
1312                if(target.length>2 && target[2]!=null && target[3]!=null)
1313                {
1314                  switch(target[2])
1315                  {
1316                    case '=':
1317                      if($domElt.attr('level')==target[3]) action=mode;
1318                      break;
1319                    case '>':
1320                      if($domElt.attr('level')>=target[3]) action=mode;
1321                      break;
1322                    case '<':
1323                      if($domElt.attr('level')<=target[3]) action=mode;
1324                      break;
1325                    case '+':
1326                      if((mode=='E' && $domElt.attr('level')<=target[3]) ||
1327                         (mode=='C' && $domElt.attr('level')>=target[3]))
1328                      {
1329                        action=mode;
1330                      }
1331                      else
1332                      {
1333                        action=(mode=='C')?'E':'C';
1334                      }
1335                      break;
1336                  }
1337                }
1338                else action=mode;
1339
1340                switch(action)
1341                {
1342                  case 'C':
1343                    $domElt
1344                      .removeClass('ui-category-selector-expandable-item ui-category-selector-collapsable-item')
1345                      .addClass('ui-category-selector-expandable-item')
1346                      .next().hide();
1347                    break;
1348                  case 'E':
1349                    $domElt
1350                      .removeClass('ui-category-selector-expandable-item ui-category-selector-collapsable-item')
1351                      .addClass('ui-category-selector-collapsable-item')
1352                      .next().show();
1353                    break;
1354                }
1355
1356              }, //applyExpandCollapse
1357
1358      setValue : function (object, value, trigger)
1359        {
1360          var options=object.data('options'),
1361              properties=object.data('properties'),
1362              objects=object.data('objects'),
1363              index=-1;
1364
1365          re=/^(:invert|:all|:none)(?:(=|<|>)(\d+))$/i;
1366          target=re.exec(value);
1367          if(target!=null) value=target[1];
1368
1369          switch(value)
1370          {
1371            case ':first':
1372              if(properties.categories.length>0) index=0;
1373              break;
1374            case ':last':
1375              index=properties.categories.length-1;
1376              break;
1377            case ':invert':
1378              if(!options.multiple) return(false);
1379              properties.index=[];
1380              objects.list.find('.ui-category-selector-item').each(
1381                function ()
1382                {
1383                  var $this=$(this),
1384                      apply=true;
1385
1386                  if(target!=null)
1387                  {
1388                    switch(target[2])
1389                    {
1390                      case '=':
1391                        apply=($this.attr('level')==target[3]);
1392                        break;
1393                      case '>':
1394                        apply=($this.attr('level')>=target[3]);
1395                        break;
1396                      case '<':
1397                        apply=($this.attr('level')<=target[3]);
1398                        break;
1399                    }
1400                  }
1401
1402                  if(apply)
1403                  {
1404                    if($this.hasClass('ui-category-selector-selected-item'))
1405                    {
1406                      $this.removeClass('ui-category-selector-selected-item');
1407                    }
1408                    else
1409                    {
1410                      $this.addClass('ui-category-selector-selected-item');
1411                      tmp=privateMethods.findIndexByValue(object, $this.attr('catId'));
1412                      if(tmp>-1) properties.index.push(tmp);
1413                    }
1414                  }
1415                }
1416              );
1417              privateMethods.setValue(object, [], false);
1418              return(false);
1419              break;
1420            case ':none':
1421              if(!options.multiple) return(false);
1422
1423              properties.index=[];
1424              objects.list.find('.ui-category-selector-selected-item').each(
1425                function ()
1426                {
1427                  var $this=$(this),
1428                      apply=true;
1429
1430                  if(target!=null)
1431                  {
1432                    switch(target[2])
1433                    {
1434                      case '=':
1435                        apply=($this.attr('level')==target[3]);
1436                        break;
1437                      case '>':
1438                        apply=($this.attr('level')>=target[3]);
1439                        break;
1440                      case '<':
1441                        apply=($this.attr('level')<=target[3]);
1442                        break;
1443                    }
1444                  }
1445
1446                  if(apply) $this.removeClass('ui-category-selector-selected-item');
1447                }
1448              );
1449              privateMethods.setValue(object, [], false);
1450              return(false);
1451              break;
1452            case ':all':
1453              if(!options.multiple) return(false);
1454              properties.index=[];
1455              objects.list.find('.ui-category-selector-item').each(
1456                function ()
1457                {
1458                  var $this=$(this),
1459                      apply=true;
1460
1461                  if(target!=null)
1462                  {
1463                    switch(target[2])
1464                    {
1465                      case '=':
1466                        apply=($this.attr('level')==target[3]);
1467                        break;
1468                      case '>':
1469                        apply=($this.attr('level')>=target[3]);
1470                        break;
1471                      case '<':
1472                        apply=($this.attr('level')<=target[3]);
1473                        break;
1474                    }
1475                  }
1476                  if(apply)
1477                  {
1478                    tmp=privateMethods.findIndexByValue(object, $this.attr('catId'));
1479                    if(tmp>-1) properties.index.push(tmp);
1480
1481                    $this.addClass('ui-category-selector-selected-item');
1482                  }
1483                }
1484              );
1485              privateMethods.setValue(object, [], false);
1486              return(false);
1487              break;
1488            default:
1489              if($.isArray(value) && options.multiple)
1490              {
1491                index=[];
1492                for(var i=0;i<value.length;i++)
1493                {
1494                  tmp=privateMethods.findIndexByValue(object, value[i]);
1495                  if(tmp>-1) index.push(tmp);
1496                }
1497              }
1498              else
1499              {
1500                index=privateMethods.findIndexByValue(object, value);
1501              }
1502
1503              break;
1504          }
1505
1506          if(!options.multiple && (!properties.initialized || properties.index!=index) && index>-1)
1507          {
1508
1509            objects.list.find('.ui-category-selector-selected-item').removeClass('ui-category-selector-selected-item');
1510            objects.list.find('[catId="'+value+'"]').addClass('ui-category-selector-selected-item');
1511            title=privateMethods.getParentName(object, objects.list.find('[catId="'+value+'"] div.ui-category-selector-name')).replace('&amp;', '&').replace('&gt;', '>').replace('&lt;', '<');
1512            properties.index=index;
1513            objects.containerName.html(properties.categories[properties.index].name).attr('title', title);
1514            objects.containerStatus.html(properties.labelStatus[properties.categories[properties.index].status]);
1515            if(trigger && options.change) object.trigger('categorySelectorChange', [properties.categories[properties.index].id]);
1516            if(properties.index>-1) return(properties.categories[properties.index].id);
1517          }
1518          else if(options.multiple)
1519          {
1520            if(!$.isArray(index))
1521            {
1522              if(index<0 || index==null) return(-1);
1523              index=[index];
1524            }
1525            tmp=[];
1526            for(var i=0;i<index.length;i++)
1527            {
1528              var item=objects.list.find('[catId="'+properties.categories[index[i]].id+'"]');
1529
1530              if(item.hasClass('ui-category-selector-selected-item'))
1531              {
1532                item.removeClass('ui-category-selector-selected-item');
1533
1534                tmpIndex=$.inArray(index[i] ,properties.index);
1535                if(tmpIndex>-1) properties.index.splice(tmpIndex, 1);
1536              }
1537              else
1538              {
1539                item.addClass('ui-category-selector-selected-item');
1540                properties.index.push(index[i]);
1541              }
1542              tmp.push(properties.categories[index[i]].id);
1543            }
1544            objects.containerList.html('');
1545            objects.list.find('.ui-category-selector-selected-item div.ui-category-selector-name').each(
1546              function ()
1547              {
1548                var path='';
1549
1550                title=privateMethods.getParentName(object, $(this)).replace('&amp;', '&').replace('&gt;', '>').replace('&lt;', '<');
1551                if(!options.displayPath)
1552                {
1553                  path=$(this).html();
1554                }
1555                else
1556                {
1557                  path=title;
1558                }
1559
1560                objects.containerList.append(
1561                  $('<li/>',
1562                    {
1563                      html:path,
1564                      title:title,
1565                      'class':'ui-category-selector-selected-cat'
1566                    }
1567                  ).prepend(
1568                      $('<span/>',
1569                        {
1570                          html:'x'
1571                        }
1572                       ).bind('click.categorySelector',
1573                          {object:object, value:$(this).parent().parent().attr('catId')},
1574                          function (event)
1575                          {
1576                            event.stopPropagation();
1577                            privateMethods.setValue(event.data.object, event.data.value);
1578                          }
1579                        )
1580                      )
1581                )
1582              }
1583            );
1584
1585            if(objects.containerList.children().length==0) objects.containerList.append('<li>&nbsp;</li>');
1586
1587            if(trigger && options.change) object.trigger('categorySelectorChange', [tmp]);
1588            return(tmp);
1589          }
1590          return(null);
1591        },
1592
1593      getParentName : function (object, item)
1594      {
1595        if(item==null || item.length==0) return('');
1596        foundItem=item.parent().parent().parent().prev().find('div.ui-category-selector-name');
1597
1598        if(foundItem.length==0) return(item.html());
1599
1600        return(privateMethods.getParentName(object, foundItem)+' / '+item.html());
1601      },
1602
1603      displaySelector : function (object, value)
1604        {
1605          var options=object.data('options'),
1606              properties=object.data('properties'),
1607              objects=object.data('objects');
1608
1609          if(properties.selectorVisible!=value)
1610          {
1611            properties.selectorVisible=value;
1612
1613            if(properties.selectorVisible && properties.categories.length>0)
1614            {
1615              var index=0;
1616              objects.listContainer
1617                .css(
1618                  {
1619                    display:'block',
1620                    'min-width':objects.listContainer.parent().css('width')
1621                  }
1622                );
1623
1624              if($.isArray(properties.index))
1625              {
1626                if (properties.index.length>0) index=properties.index[0];
1627              }
1628              else if(properties.index>-1)
1629              {
1630                index=properties.index;
1631              }
1632              objects.listContainer.scrollTop(objects.listContainer.scrollTop()+objects.list.find('[catId="'+properties.categories[index].id+'"]').position().top);
1633            }
1634            else
1635            {
1636              objects.listContainer.css('display', 'none');
1637            }
1638            if(options.popup) object.trigger('categorySelectorPopup', [properties.selectorVisible]);
1639          }
1640          return(properties.selectorVisible);
1641        },
1642
1643      load : function (object)
1644        {
1645          // load datas from server through an asynchronous ajax call
1646          var options=object.data('options'),
1647              objects=object.data('objects');
1648
1649          if(options.serverUrl=='') return(false);
1650
1651          $.ajax(
1652            {
1653              type: "POST",
1654              url: options.serverUrl,
1655              async: true,
1656              data:
1657                {
1658                  ajaxfct:options.userMode+'.categorySelector.getList',
1659                  filter:options.filter,
1660                  galleryRoot:options.galleryRoot?'y':'n',
1661                  tree:'y',
1662                  data:options.postData
1663                },
1664              success: function(msg)
1665                {
1666                  privateMethods.setItems(object, msg);
1667                },
1668              error: function(msg)
1669                {
1670                  objects.listContainer.html('Error ! '+msg);
1671                },
1672            }
1673         );
1674        },
1675
1676      listClear : function (object)
1677        {
1678          // clear the categorie list
1679          var objects=object.data('objects'),
1680              options=object.data('options'),
1681              properties=object.data('properties');
1682
1683          objects.list.children().unbind();
1684          objects.list.html('');
1685          if(options.multiple)
1686          {
1687            properties.index=[];
1688          }
1689          else
1690          {
1691            properties.index=-1;
1692          }
1693          properties.categories=[];
1694        },
1695
1696      listAddItems : function (object, listItems, parent)
1697        {
1698          // add the items to the categorie list
1699          var options=object.data('options'),
1700              properties=object.data('properties'),
1701              objects=object.data('objects');
1702
1703          var previousLevel=-1;
1704          for(var i=0;i<listItems.length;i++)
1705          {
1706            properties.categories.push(
1707              {
1708                id:listItems[i].id,
1709                level:listItems[i].level,
1710                name:listItems[i].name,
1711                status:listItems[i].status,
1712                childs:listItems[i].childs.length
1713              }
1714            );
1715
1716            if(options.displayStatus)
1717            {
1718              status="<div class='ui-category-selector-status'>"+properties.labelStatus[listItems[i].status]+"</div>";
1719            }
1720            else
1721            {
1722              status="";
1723            }
1724
1725            var spaceWidth = (options.iconWidthEC+listItems[i].level*options.levelIndent),
1726                li=$('<li/>',
1727                      {
1728                        'class':'ui-category-selector-item',
1729                        html:"<div>"+status+"<div class='ui-category-selector-name'>"+listItems[i].name+"</div></div>",
1730                        catId:listItems[i].id,
1731                        level:listItems[i].level,
1732                        css:{
1733                          'padding-left':spaceWidth+'px'
1734                        }
1735                      }
1736                    ).bind('click.categorySelector',
1737                        {object:object, expandArea: spaceWidth, nbchilds:listItems[i].childs.length },
1738                        function (event)
1739                        {
1740                          event.layerX=event.pageX-$(event.currentTarget).offset().left;
1741                          event.layerY=event.pageY-$(event.currentTarget).offset().top;
1742
1743                          if(event.layerX<event.data.expandArea && event.data.nbchilds>0 )
1744                          {
1745                            if($(this).hasClass('ui-category-selector-expandable-item'))
1746                            {
1747                              $(this)
1748                                .removeClass('ui-category-selector-expandable-item')
1749                                .addClass('ui-category-selector-collapsable-item')
1750                                .next().show();
1751                            }
1752                            else
1753                            {
1754                              $(this)
1755                                .removeClass('ui-category-selector-collapsable-item')
1756                                .addClass('ui-category-selector-expandable-item')
1757                                .next().hide();
1758                            }
1759                          }
1760                          else
1761                          {
1762                            privateMethods.setValue(event.data.object, $(this).attr('catId'), true);
1763                            if(options.multiple)
1764                            {
1765                            }
1766                            else
1767                            {
1768                              privateMethods.displaySelector(event.data.object, false);
1769                            }
1770                          }
1771
1772                          if(options.multiple) objects.container.focus();
1773                        }
1774                      );
1775            if(listItems[i].childs.length>0)
1776            {
1777              li.addClass('ui-category-selector-collapsable-item').css('background-position', (options.levelIndent*listItems[i].level)+'px 0px');
1778            }
1779
1780            if(options.multiple)
1781            {
1782              li.children().prepend('<div class="ui-category-selector-check"></div>');
1783            }
1784
1785            parent.append(li);
1786
1787            if(listItems[i].childs.length>0)
1788            {
1789              var ul=$('<ul/>',
1790                        {
1791                          'class':'ui-category-selector-group',
1792                          css: {
1793                            listStyle:'none',
1794                            padding:'0px',
1795                            margin:'0px',
1796                            'font-size':(100-listItems[i].level*2)+'%'
1797                          }
1798                        }
1799                      );
1800              li.after(ul);
1801              privateMethods.listAddItems(object, listItems[i].childs, ul);
1802            }
1803
1804          }
1805        },
1806
1807      findIndexByValue : function (object, value)
1808        {
1809          /*
1810           * search a categorie inside the categories list and return the index
1811           * in the array
1812           */
1813          var properties=object.data('properties');
1814
1815          for(var i=0;i<properties.categories.length;i++)
1816          {
1817            if(properties.categories[i].id==value) return(i);
1818          }
1819          return(-1);
1820        },
1821
1822      setEventPopup : function (object, value)
1823        {
1824          var options=object.data('options');
1825
1826          options.popup=value;
1827          object.unbind('categorySelectorPopup');
1828          if(value) object.bind('categorySelectorPopup', options.popup);
1829          return(options.popup);
1830        },
1831
1832      setEventChange : function (object, value)
1833        {
1834          var options=object.data('options');
1835
1836          options.change=value;
1837          object.unbind('categorySelectorChange');
1838          if(value) object.bind('categorySelectorChange', options.change);
1839          return(options.change);
1840        },
1841
1842      setEventLoad : function (object, value)
1843        {
1844          var options=object.data('options');
1845
1846          options.load=value;
1847          object.unbind('categorySelectorLoad');
1848          if(value) object.bind('categorySelectorLoad', options.load);
1849          return(options.load);
1850        }
1851    };
1852
1853
1854    $.fn.categorySelector = function(method)
1855    {
1856      if(publicMethods[method])
1857      {
1858        return publicMethods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
1859      }
1860      else if(typeof method === 'object' || ! method)
1861      {
1862        return publicMethods.init.apply(this, arguments);
1863      }
1864      else
1865      {
1866        $.error( 'Method ' +  method + ' does not exist on jQuery.categorySelector' );
1867      }
1868    } // $.fn.categorySelector
1869
1870  }
1871)(jQuery);
1872
1873
Note: See TracBrowser for help on using the repository browser.