source: extensions/GrumPluginClasses/js/ui.inputTreeList.js @ 31506

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