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

Last change on this file since 8961 was 8961, checked in by grum, 13 years ago

release 3.4.0
fix bug:1984, bug:2109
js file are minified, remove packed files

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