reports: Fix id of custom date selector
[ninja.git] / application / media / js / jquery.easywidgets.js
blob62c0b75d35fc74c13e55e4df3c5fa41b8fc50718
1 /**\r
2  * op5 NOTE: I found this online and stuck it in here. It doesn't\r
3  * necessarily work for us, but at least now we have the expanded\r
4  * source.\r
5  *\r
6  * Easy Widgets 2.0 for jQuery and jQuery UI\r
7  *\r
8  * David Esperalta <http://www.davidesperalta.com/>\r
9  * \r
10  * More information, examples and latest version in the website:\r
11  * <http://www.bitacora.davidesperalta.com/archives/projects/easywidgets/>\r
12  *\r
13  * I based my work on a tutorial writen by James Padolsey\r
14  * <http://nettuts.com/tutorials/javascript-ajax/inettuts/>\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with Easy Widgets. If not, see <http://www.gnu.org/licenses/>\r
18  *\r
19  */\r
20 (function($) {\r
22     ///////////////////////////\r
23     // Public plugin methods //\r
24     ///////////////////////////\r
26     /**\r
27     * Main public method of plugin\r
28     *\r
29     * Call this method to initialize the plugin, that prepare all the available\r
30     * widgets in the document, and execute the appropiate task on every widget.\r
31     *\r
32     * Basically call the InitializeWidgets() private function, with the second\r
33     * param by default: using this method we not prepare widgets on demand, but\r
34     * prepare all widgets found in the document.\r
35     *\r
36     * See the mentioned function for more details, and how we use this function\r
37     * too in another plugin public method: AddEasyWidget(), see it for details.\r
38     *\r
39     * @access public\r
40     * @see InitializeWidgets()\r
41     * @param settings Array with the plugin settings\r
42     * @return Boolean True in every case\r
43     *\r
44     */\r
45     $.fn.EasyWidgets = function(settings) {\r
46         InitializeWidgets(settings, false);\r
47         return true;\r
48     };\r
50     /**\r
51     * Add a new widget "on demand"\r
52     *\r
53     * This public method can be use to add a new widget "on demand" into certain\r
54     * place. The method need the HTML markup for widget, and this can specify\r
55     * all the available widget options.\r
56     *\r
57     * In this method we use the private InitializeWidgets() function, also used\r
58     * in another public method of the plugin: EasyWidgets(). Note that in this\r
59     * case the second param for this funtion specify that in this case we want\r
60     * to add a widget "on demand".\r
61     *\r
62     * For more details see the refered private function.\r
63     *\r
64     * @access public\r
65     * @see InitializeWidgets()\r
66     * @param html String Widget HTML markup\r
67     * @param placeId String Element ID to place the Widget\r
68     * @param settings Array with the plugin settings\r
69     * @return Boolean True if widget is finally added, False if not\r
70     *\r
71     */\r
72     $.fn.AddEasyWidget = function(html, placeId, settings) {\r
73         var canAdd = true;\r
74         var widget = $(html);\r
75         var s = $.extend(true, $.fn.EasyWidgets.defaults, settings);\r
76         if ($.isFunction(s.callbacks.onAddQuery)) {\r
77             canAdd = s.callbacks.onAddQuery(widget, placeId);\r
78         }\r
79         if (canAdd) {\r
80             $('#' + placeId).append(html);\r
81             if ($.isFunction(s.callbacks.onAdd)) {\r
82                 s.callbacks.onAdd(widget, placeId);\r
83             }\r
84             InitializeWidgets(s, true);\r
85             return true;\r
86         } else {\r
87             return false;\r
88         }\r
89     };\r
91     /**\r
92     * Disable all widgets (fix then) in document\r
93     *\r
94     * This public method can be use to fix the widgets on document, in other\r
95     * words, disable the widgets, because the user cant move this after the\r
96     * widgets as been disables.\r
97     * \r
98     * @access public\r
99     * @see EnableEasyWidgets()\r
100     * @param settings Array with the plugin settings\r
101     * @return Boolean True if widgets are finally disables, False if not\r
102     *\r
103     */\r
104     $.fn.DisableEasyWidgets = function(settings) {\r
105         var canDisable = true;\r
106         var s = $.extend(true, $.fn.EasyWidgets.defaults, settings);\r
107         if ($.isFunction(s.callbacks.onDisableQuery)) {\r
108             canDisable = s.callbacks.onDisableQuery();\r
109         }\r
110         if (canDisable) {\r
111             $(s.selectors.places).sortable('disable');\r
112             $(s.selectors.widget).each(function() {\r
113                 var widget = $(this);\r
114                 if (widget.hasClass(s.options.movable)) {\r
115                     widget.find(s.selectors.header).css('cursor', 'default');\r
116                     widget.find(s.selectors.widgetMenu).css('display', 'none');\r
117                 }\r
118             });\r
119             if ($.isFunction(s.callbacks.onDisable)) {\r
120                 s.callbacks.onDisable();\r
121             }\r
122             SetCookie(s.cookies.disableName, 1, s);\r
123             return true;\r
124         } else {\r
125             return false;\r
126         }\r
127     };\r
129     /**\r
130     * Enable all widgets (make movables) in document\r
131     *\r
132     * This public method can be use to make movables the widgets on document,\r
133     * in other words, enable the widgets, because the user can move this after\r
134     * the widgets as been enables.\r
135     *\r
136     * Note that the widgets are enables by default, so, this method have sense\r
137     * in case that you use before another method of plugin: DisableEasyWidgets()\r
138     *\r
139     * @access public\r
140     * @see DisableEasyWidgets()\r
141     * @param settings Array with the plugin settings\r
142     * @return Boolean True if widgets are finally enables, False if not\r
143     *\r
144     */\r
145     $.fn.EnableEasyWidgets = function(settings) {\r
146         var canEnable = true;\r
147         var s = $.extend(true, $.fn.EasyWidgets.defaults, settings);\r
148         if ($.isFunction(s.callbacks.onEnableQuery)) {\r
149             canEnable = s.callbacks.onEnableQuery();\r
150         }\r
151         if (canEnable) {\r
152             $(s.selectors.places).sortable('enable');\r
153             $(s.selectors.widget).each(function() {\r
154                 var widget = $(this);\r
155                 if (widget.hasClass(s.options.movable)) {\r
156                     widget.find(s.selectors.header).css('cursor', 'move');\r
157                 }\r
158             });\r
159             if ($.isFunction(s.callbacks.onEnable)) {\r
160                 s.callbacks.onEnable();\r
161             }\r
162             if (s.behaviour.useCookies) {\r
163                 SetCookie(s.cookies.disableName, 0, s);\r
164             }\r
165             return true;\r
166         } else {\r
167             return false;\r
168         }\r
169     };\r
171     /**\r
172     * Hide all widgets in document\r
173     *\r
174     * This public method can be use to hide all the document visible widgets.\r
175     * Note that this method and related is thinking if you use the plugin\r
176     * cookies feature.\r
177     *\r
178     * In other case, you can use directly something like this:\r
179     *\r
180     * $('widgets-class-selector').hide();\r
181     *\r
182     * So, this method can sense if you use the plugin cookies feature, because\r
183     * the plugin update the appropiate cookie with the needed information, to\r
184     * mantain the widgets hidden even if user refresh the page.\r
185     *\r
186     * @access public\r
187     * @see HideEasyWidget()\r
188     * @see ShowEasyWidgets()\r
189     * @param settings Array with the plugin settings\r
190     * @return Boolean True in every case\r
191     *\r
192     */\r
193     $.fn.HideEasyWidgets = function(settings) {\r
194         var s = $.extend(true, $.fn.EasyWidgets.defaults, settings);\r
195         $(s.selectors.widget + ':visible').each(function() {\r
196             var canHide = true;\r
197             var thisWidget = $(this);\r
198             var thisWidgetId = thisWidget.attr('id');\r
199             if ($.isFunction(s.callbacks.onHideQuery)) {\r
200                 canHide = s.callbacks.onHideQuery(thisWidget);\r
201             }\r
202             if (canHide) {\r
203                 ApplyEffect(\r
204           thisWidget,\r
205           s.effects.widgetHide,\r
206           s.effects.effectDuration,\r
207           false\r
208         );\r
209                 if (s.behaviour.useCookies && thisWidgetId) {\r
210                     UpdateCookie(thisWidgetId, s.cookies.closeName, s);\r
211                 }\r
212                 if ($.isFunction(s.callbacks.onHide)) {\r
213                     s.callbacks.onHide(thisWidget);\r
214                 }\r
215             }\r
216         });\r
217         return true;\r
218     };\r
220     /**\r
221     * Show all widgets in document\r
222     *\r
223     * This public method can be use to show all the document hidden widgets.\r
224     * Note that this method and related is thinking if you use the plugin\r
225     * cookies feature.\r
226     *\r
227     * In other case, you can use directly something like this:\r
228     *\r
229     * $('widgets-class-selector').show();\r
230     *\r
231     * So, this method can sense if you use the plugin cookies feature, because\r
232     * the plugin update the appropiate cookie with the needed information, to\r
233     * mantain the widgets showing even if user refresh the page.\r
234     *\r
235     * @access public\r
236     * @see ShowEasyWidget()\r
237     * @see HideEasyWidgets()\r
238     * @param settings Array with the plugin settings\r
239     * @return Boolean True in every case\r
240     *\r
241     */\r
242     $.fn.ShowEasyWidgets = function(settings) {\r
243         var s = $.extend(true, $.fn.EasyWidgets.defaults, settings);\r
244         $(s.selectors.widget + ':hidden').each(function() {\r
245             var canShow = true;\r
246             var widget = $(this);\r
247             var widgetId = widget.attr('id');\r
248             var haveId = ($.trim(widgetId) != '');\r
249             if ($.isFunction(s.callbacks.onShowQuery)) {\r
250                 canShow = s.callbacks.onShowQuery(widget);\r
251             }\r
252             if (canShow) {\r
253                 ApplyEffect(\r
254           widget,\r
255           s.effects.widgetShow,\r
256           s.effects.effectDuration,\r
257           true\r
258         );\r
259                 if (haveId && s.behaviour.useCookies) {\r
260                     CleanCookie(widgetId, s.cookies.closeName, s);\r
261                 }\r
262                 if ($.isFunction(s.callbacks.onShow)) {\r
263                     s.callbacks.onShow(widget);\r
264                 }\r
265             }\r
266         });\r
267         return true;\r
268     };\r
270     /**\r
271     * Show an individual widget\r
272     *\r
273     * This public method can be use to show an individual hidden widget.\r
274     * Note that this method and related is thinking if you use the plugin\r
275     * cookies feature.\r
276     *\r
277     * In other case, you can use directly something like this:\r
278     *\r
279     * $('widget-id-selector').show();\r
280     *\r
281     * So, this method can sense if you use the plugin cookies feature, because\r
282     * the plugin update the appropiate cookie with the needed information, to\r
283     * mantain the widgets showing even if user refresh the page.\r
284     *\r
285     * @access public\r
286     * @see HideEasyWidget()\r
287     * @see ShowEasyWidgets()\r
288     * @param widgetId String Widget element identifier\r
289     * @param settings Array with the plugin settings\r
290     * @return Boolean True if widget finally is show, False if not\r
291     *\r
292     */\r
293     $.fn.ShowEasyWidget = function(widgetId, settings) {\r
294         var canShow = true;\r
295         var widget = $('#' + widgetId);\r
296         if (widget.css('display') == 'none') {\r
297             var s = $.extend(true, $.fn.EasyWidgets.defaults, settings);\r
298             if ($.isFunction(s.callbacks.onShowQuery)) {\r
299                 canShow = s.callbacks.onShowQuery(widget);\r
300             }\r
301             if (canShow) {\r
302                 ApplyEffect(\r
303           widget,\r
304           s.effects.widgetShow,\r
305           s.effects.effectDuration,\r
306           true\r
307         );\r
308                 if (s.behaviour.useCookies) {\r
309                     CleanCookie(widgetId, s.cookies.closeName, s);\r
310                 }\r
311                 if ($.isFunction(s.callbacks.onShow)) {\r
312                     s.callbacks.onShow(widget);\r
313                 }\r
314                 return true;\r
315             } else {\r
316                 return false;\r
317             }\r
318         } else {\r
319             return false;\r
320         }\r
321     };\r
323     /**\r
324     * Hide an individual widget\r
325     *\r
326     * This public method can be use to hide an individual visible widget.\r
327     * Note that this method and related is thinking if you use the plugin\r
328     * cookies feature.\r
329     *\r
330     * In other case, you can use directly something like this:\r
331     *\r
332     * $('widget-id-selector').hide();\r
333     *\r
334     * So, this method can sense if you use the plugin cookies feature, because\r
335     * the plugin update the appropiate cookie with the needed information, to\r
336     * mantain the widgets showing even if user refresh the page.\r
337     *\r
338     * @access public\r
339     * @see ShowEasyWidget()\r
340     * @see HideEasyWidgets()\r
341     * @param widgetId String Widget element identifier\r
342     * @param settings Array with the plugin settings\r
343     * @return Boolean True if widget finally is hide, False if not\r
344     *\r
345     */\r
346     $.fn.HideEasyWidget = function(widgetId, settings) {\r
347         var canHide = true;\r
348         var widget = $('#' + widgetId);\r
349         if (widget.css('display') != 'none') {\r
350             var s = $.extend(true, $.fn.EasyWidgets.defaults, settings);\r
351             if ($.isFunction(s.callbacks.onHideQuery)) {\r
352                 canHide = s.callbacks.onHideQuery(widget);\r
353             }\r
354             if (canHide) {\r
355                 ApplyEffect(\r
356           widget,\r
357           s.effects.widgetHide,\r
358           s.effects.effectDuration,\r
359           false\r
360         );\r
361                 if (s.behaviour.useCookies) {\r
362                     UpdateCookie(widgetId, s.cookies.closeName, s);\r
363                 }\r
364                 if ($.isFunction(s.callbacks.onHide)) {\r
365                     s.callbacks.onHide(widget);\r
366                 }\r
367                 return true;\r
368             } else {\r
369                 return false;\r
370             }\r
371         } else {\r
372             return false;\r
373         }\r
374     };\r
376     /////////////////////////////\r
377     // Plugin default settings //\r
378     /////////////////////////////\r
380     /**\r
381     * Plugin default settings\r
382     *\r
383     * This is the settings that plugin use in case that you not provide your\r
384     * own plugin settings. Also, you dont need to provide all the settings, but\r
385     * change only that you need: the plugin use the default settings that you\r
386     * not provided, and also the settings that you provide.\r
387     *\r
388     * In other words, the plugin merge your own settings with plugin defaults.\r
389     * \r
390     */\r
391     $.fn.EasyWidgets.defaults = {\r
393         // Behaviour of the plugin\r
394         behaviour: {\r
396             // Miliseconds delay between mousedown and drag start\r
397             dragDelay: 100,\r
399             // Miliseconds delay between mouseup and drag stop\r
400             dragRevert: 100,\r
402             // Determinme the opacity of Widget when start drag\r
403             dragOpacity: 0.8,\r
405             // Cookies (require Cookie plugin) to store positions and states\r
406             useCookies: false\r
407         },\r
409         // Some effects that can be apply sometimes\r
410         effects: {\r
412             // Miliseconds for effects duration\r
413             effectDuration: 500,\r
415             // Can be none, slide or fade\r
416             widgetShow: 'none',\r
417             widgetHide: 'none',\r
418             widgetClose: 'none',\r
419             widgetExtend: 'none',\r
420             widgetCollapse: 'none',\r
421             widgetOpenEdit: 'none',\r
422             widgetCloseEdit: 'none',\r
423             widgetCancelEdit: 'none'\r
424         },\r
426         // Only for the optional cookie feature\r
427         cookies: {\r
429             // Cookie path\r
430             path: '',\r
432             // Cookie domain\r
433             domain: '',\r
435             // Cookie expiration time in days\r
436             expires: 90,\r
438             // Store a secure cookie?\r
439             secure: false,\r
441             // Cookie name for close Widgets\r
442             closeName: 'ew-close',\r
444             // Cookie name for disable all Widgets\r
445             disableName: 'ew-disable',\r
447             // Cookie name for positined Widgets\r
448             positionName: 'ew-position',\r
450             // Cookie name for collapsed Widgets\r
451             collapseName: 'ew-collapse'\r
452         },\r
454         // Options name to use in the HTML markup\r
455         options: {\r
457             // To recognize a movable Widget\r
458             movable: 'movable',\r
460             // To recognize a editable Widget\r
461             editable: 'editable',\r
463             // To recognize a collapse Widget\r
464             collapse: 'collapse',\r
466             // To recognize a removable Widget\r
467             removable: 'removable',\r
469             // To recognize a collapsable Widget\r
470             collapsable: 'collapsable',\r
472             // To recognize Widget that require confirmation when remove\r
473             closeConfirm: 'closeconfirm'\r
474         },\r
476         // Callbacks functions\r
477         callbacks: {\r
479             // When a Widget is added on demand, send the widget object and place ID\r
480             onAdd: null,\r
482             // When a editbox is closed, send the link and the widget objects\r
483             onEdit: null,\r
485             // When a Widget is show, send the widget object\r
486             onShow: null,\r
488             // When a Widget is hide, send the widget object\r
489             onHide: null,\r
491             // When a Widget is closed, send the link and the widget objects\r
492             onClose: null,\r
494             // When Widgets are enabled using the appropiate public method\r
495             onEnable: null,\r
497             // When a Widget is extend, send the link and the widget objects\r
498             onExtend: null,\r
500             // When Widgets are disabled using the appropiate public method\r
501             onDisable: null,\r
503             // When a editbox is closed, send a ui object, see jQuery::sortable()\r
504             onDragStop: null,\r
506             // When a Widget is collapse, send the link and the widget objects\r
507             onCollapse: null,\r
509             // When a Widget is try to added, send the widget object and place ID\r
510             onAddQuery: null,\r
512             // When a editbox is try to close, send the link and the widget objects\r
513             onEditQuery: null,\r
515             // When a Widget is try to show, send the widget object\r
516             onShowQuery: null,\r
518             // When a Widget is try to hide, send the widget object\r
519             onHideQuery: null,\r
521             // When a Widget is try to close, send the link and the widget objects\r
522             onCloseQuery: null,\r
524             // When a editbox is cancel (close), send the link and the widget objects\r
525             onCancelEdit: null,\r
527             // When Widgets are enabled using the appropiate public method\r
528             onEnableQuery: null,\r
530             // When a Widget is try to expand, send the link and the widget objects\r
531             onExtendQuery: null,\r
533             // When Widgets are disabled using the appropiate public method\r
534             onDisableQuery: null,\r
536             // When a Widget is try to expand, send the link and the widget objects\r
537             onCollapseQuery: null,\r
539             // When a editbox is try to cancel, send the link and the widget objects\r
540             onCancelEditQuery: null,\r
542             // When one Widget is repositioned, send the positions serialization\r
543             onChangePositions: null,\r
545             // When Widgets need repositioned, get the serialization positions\r
546             onRefreshPositions: null\r
547         },\r
549         // Selectors in HTML markup. All can be change by you, but not all is\r
550         // used in the HTML markup. For example, the "editLink" or "closeLink"\r
551         // is prepared by the plugin for every Widget.\r
552         selectors: {\r
554             // Container of a Widget (into another element that use as place)\r
555             // The container can be "div" or "li", for example. In the first case\r
556             // use another "div" as place, and a "ul" in the case of "li".\r
557             container: 'div',\r
559             // Class identifier for a Widget\r
560             widget: '.widget',\r
562             // Class identifier for a Widget place (parents of Widgets)\r
563             places: '.widget-place',\r
565             // Class identifier for a Widget header (handle)\r
566             header: '.widget-header',\r
568             // Class for the Widget header menu\r
569             widgetMenu: '.widget-menu',\r
571             // Class identifier for Widget editboxes\r
572             editbox: '.widget-editbox',\r
574             // Class identifier for Widget content\r
575             content: '.widget-content',\r
577             // Class identifier for editbox close link or button, for example\r
578             closeEdit: '.widget-close-editbox',\r
580             // Class identifier for a Widget edit link\r
581             editLink: '.widget-editlink',\r
583             // Class identifier for a Widget close link\r
584             closeLink: '.widget-closelink',\r
586             // Class identifier for Widgets placehoders\r
587             placeHolder: 'widget-placeholder',\r
589             // Class identifier for a Widget collapse link\r
590             collapseLink: '.widget-collapselink'\r
591         },\r
593         // To be translate the plugin into another languages\r
594         // But this variables can be used to show images instead\r
595         // links text, if you preffer. In this case set the HTML\r
596         // of the IMG elements.\r
597         i18n: {\r
599             // Widget edit link text\r
600             editText: 'Edit',\r
602             // Widget close link text\r
603             closeText: 'Close',\r
605             // Widget extend link text\r
606             extendText: 'Extend',\r
608             // Widget collapse link text\r
609             collapseText: 'Collapse',\r
611             // Widget cancel edit link text\r
612             cancelEditText: 'Cancel',\r
614             // Widget edition link title\r
615             editTitle: 'Edit this widget',\r
617             // Widget close link title\r
618             closeTitle: 'Close this widget',\r
620             // Widget confirmation dialog message\r
621             confirmMsg: 'Remove this widget?',\r
623             // Widget cancel edit link title\r
624             cancelEditTitle: 'Cancel edition',\r
626             // Widget extend link title\r
627             extendTitle: 'Extend this widget',\r
629             // Widget collapse link title\r
630             collapseTitle: 'Collapse this widget'\r
631         }\r
632     };\r
634     //////////////////////////////\r
635     // Private plugin functions //\r
636     //////////////////////////////\r
638     /**\r
639     * Initialize the widgets\r
640     *\r
641     * This private function is used in two methods of the plugin, the main\r
642     * public method: EasyWidgets() and AddEasyWidget() public method. In other\r
643     * words, this function is the main function of the plugin, and is use to\r
644     * initialize the widgets at a first time, and initialize the widgets added\r
645     * on demand.\r
646     *\r
647     * This function separate different things into other private functions:\r
648     * for more details see the related and used here plugin private functions.\r
649     *\r
650     * @access private\r
651     * @param settings Array with the plugin settings\r
652     * @param widgetOnDemand Boolean Widget added on demand or not\r
653     * @return Boolean True in every case\r
654     *\r
655     */\r
656     function InitializeWidgets(\r
657    settings, widgetOnDemand) {\r
658         var b = widgetOnDemand;\r
659         var d = $.fn.EasyWidgets.defaults;\r
660         var s = $.extend(true, d, settings);\r
661         $(s.selectors.widget).each(function() {\r
662             PrepareWidgetBehaviour($(this), b, s);\r
663         });\r
664         RepositionedWidgets(s);\r
665         MakeWidgetsSortables(s);\r
666         CleanWidgetsCookies(s, b);\r
667         return true;\r
668     }\r
670     /**\r
671     * Prepare the widgets behaviour\r
672     *\r
673     * This private function is called from another: InitializeWidgets()\r
674     * to prepare the behaviour of a found widget: append the widget menu\r
675     * if is needed, put into this the appropiate links, etc.\r
676     *\r
677     * As you can see, another private plugin functions are used here,\r
678     * we refer you to this functions for more details about this task.\r
679     * However, here is an important question about this function logical:\r
680     *\r
681     * This function can be use to deal with "normal" widgets and widgets\r
682     * added on demand. This function can be called to prepare certain\r
683     * widget that as been prepared when page onload: so, this widgets\r
684     * cannot be prepared again.\r
685     *\r
686     * To evit the duplication of the widget menus, basically, we find\r
687     * for this widget menu, and, if is empty, this widget need to be\r
688     * prepared, but, if this widget have a menu yet, cannot need to\r
689     * be prepared.\r
690     *\r
691     * This condition only have sense when added widgets on demand, if\r
692     * not is the case, no one widget have a menu before prepared, so,\r
693     * are prepared here the first time that this function is called.\r
694     *\r
695     * @access private\r
696     * @see InitializeWidgets()\r
697     * @see AddWidgetEditLink()\r
698     * @see AddWidgetRemoveLink()\r
699     * @see AddWidgetCollapseLink()\r
700     * @param widget jQuery object with a widget\r
701     * @param widgetOnDemand Boolean Widget added on demand or not\r
702     * @param settings Array with the plugin settings\r
703     * @return Boolean True if widget are prepared, False if is yet prepared\r
704     *\r
705     */\r
706     function PrepareWidgetBehaviour(widget, widgetOnDemand, settings) {\r
707         var s = settings;\r
708         var widgetMenu = widget.find(s.selectors.widgetMenu);\r
709         if (widgetMenu.html() == null) {\r
710             var widgetId = widget.attr('id');\r
711             var haveId = ($.trim(widgetId) != '');\r
712             widget.find(s.selectors.editbox).hide();\r
713             if (widgetOnDemand && haveId && s.behaviour.useCookies) {\r
714                 // Force this widget out of closed widgets cookie\r
715                 // because in other case is possible that widget\r
716                 // are added, but in fact not show in the document\r
717                 CleanCookie(widgetId, s.cookies.closeName, s);\r
718             }\r
719             if (!widgetOnDemand && haveId && s.behaviour.useCookies\r
720        && GetCookie(s.cookies.closeName) != null) {\r
721                 var cookieValue = GetCookie(s.cookies.closeName);\r
722                 if (cookieValue.indexOf(widgetId) != -1) {\r
723                     // But in case of not on demand widget, is possible\r
724                     // to hide the widget, if is present in the appropiate\r
725                     // related cookie\r
726                     widget.hide();\r
727                 }\r
728             }\r
729             var menuWrap = '<span class="' + s.selectors\r
730        .widgetMenu.replace(/\./, '') + '"></span>';\r
731             widget.find(s.selectors.header).append(menuWrap);\r
732             // Now this menu is a valid wrap to add the links\r
733             widgetMenu = widget.find(s.selectors.widgetMenu);\r
734             // The order of this function call is important\r
735             // because determine the order of links appear\r
736             AddWidgetCollapseLink(widget, widgetMenu, s);\r
737             AddWidgetEditLink(widget, widgetMenu, s);\r
738             AddWidgetRemoveLink(widget, widgetMenu, s);\r
739             return true;\r
740         } else {\r
741             return false;\r
742         }\r
743     }\r
745     /**\r
746     * Repositioned the widgets\r
747     *\r
748     * This private function is called from InitializeWidgets() and is used\r
749     * to repositioned the widgets in the appropiate places into the document.\r
750     *\r
751     * Some important question about this function is that the plugin can\r
752     * repositioned the widgets follow certain string, that containt the\r
753     * needed information.\r
754     *\r
755     * This string is produced in WidgetsPositionsChange() private function,\r
756     * and bassically contain the places IDs and the widgets IDs saved in\r
757     * a know format, that here we read to apply just later.\r
758     *\r
759     * Take a look at this: the mentioned string is saved in a cookie if you\r
760     * use the cookies feature of the plugin. But in any case the plugin send\r
761     * to you this string in the "onChangePositions()" callback.\r
762     *\r
763     * What is this? Suppose that you cannot use cookies, but still want to\r
764     * repositioned the widgets. So, you can get the refered string and save\r
765     * it in a database, for example.\r
766     *\r
767     * Then, just when this function is executed, you can provide this string\r
768     * returning it in the "onRefreshPositions()" plugin callback. Then, if you\r
769     * provide here a string that contain the widgets positions, the plugin use\r
770     * this string to repositioned the widgets.\r
771     *\r
772     * If you use the cookies plugin feature, the widget read the appropiate\r
773     * cookie, get the string previously saved (see WidgetsPositionsChange())\r
774     * and repositioned the widgets. Of course, if you not provide any string\r
775     * and also not use the cookies feature, the widgets cannot be positioned.\r
776     *\r
777     * Another thing more. You can see at WidgetsPositionsChange() how we\r
778     * conform the appropiate string, so, in this function we read the string\r
779     * based on the appropiate format. This string is like this:\r
780     *\r
781     * place-1=widget-1,widget-2|place-1=widget-3,widget-4\r
782     *\r
783     * Note one more thing: the order of the string is not casual: reflect the\r
784     * real order of the places and widgets in the document when the string is\r
785     * formed, so, the order of the widgets after this function is executed is\r
786     * the correct, because we follow the string as is.\r
787     *\r
788     * @access private\r
789     * @see InitializeWidgets()\r
790     * @see PrepareSortablePlaces()\r
791     * @see WidgetsPositionsChange()\r
792     * @return Boolean True in every case\r
793     * \r
794     */\r
795     function RepositionedWidgets(settings) {\r
796         var s = settings;\r
797         var positions = '';\r
798         if ($.isFunction(s.callbacks.onRefreshPositions)) {\r
799             positions = s.callbacks.onRefreshPositions();\r
800         }\r
801         // Only if not provide a string widget positions,\r
802         // use cookies and the appropiate cookie is not empty\r
803         if (($.trim(positions) == '') && s.behaviour.useCookies\r
804      && GetCookie(s.cookies.positionName) != null) {\r
805             // We get the widgets positions from the cookie\r
806             positions = GetCookie(s.cookies.positionName)\r
807         }\r
808         if ($.trim(positions) != '') {\r
809             // Get the widgets places IDs and widgets IDs\r
810             var places = positions.split('|');\r
811             var totalPlaces = places.length;\r
812             for (var i = 0; i < totalPlaces; i++) {\r
813                 // Every part contain a place ID and possible widgets IDs\r
814                 var place = places[i].split('=');\r
815                 // Validate (more or less) the format of the part that must\r
816                 // contain two element: A place ID and one or more widgets IDs\r
817                 if (place.length == 2) {\r
818                     // Subpart one: the place ID\r
819                     var placeSel = '#' + place[0];\r
820                     // Subpart two: one or more widgets IDs\r
821                     var widgets = place[1].split(',');\r
822                     var totalWidgets = widgets.length;\r
823                     // Here we have a place and one or more widgets IDs\r
824                     for (var j = 0; j < totalWidgets; j++) {\r
825                         if ($.trim(widgets[j]) != '') {\r
826                             // So, append every widget in the appropiate place\r
827                             var widgetSel = '#' + widgets[j];\r
828                             $(widgetSel).appendTo(placeSel);\r
829                         }\r
830                     }\r
831                 }\r
832             }\r
833         }\r
834         return true;\r
835     }\r
837     /**\r
838     * Make widgets sortables\r
839     *\r
840     * This private function make found widgets as sortable items. This\r
841     * is called from another plugin private funtion: InitializeWidgets()\r
842     *\r
843     * As you can see, another private plugin functions are used here:\r
844     * we refer you to this functions for more details about this task.\r
845     *\r
846     * @access private\r
847     * @see InitializeWidgets()\r
848     * @see GetSortableItems()\r
849     * @see PrepareSortableHeaders()\r
850     * @see PrepareSortablePlaces()\r
851     * @param settings Array with the plugin settings\r
852     * @return Boolean True in every case\r
853     * \r
854     */\r
855     function MakeWidgetsSortables(settings) {\r
856         var sortables = GetSortableItems(settings);\r
857         PrepareSortableHeaders(sortables, settings);\r
858         PrepareSortablePlaces(sortables, settings);\r
859         return true;\r
860     }\r
862     /**\r
863     * Find widgets and places as sortables items\r
864     *\r
865     * And return it. This function is called from MakeWidgetsSortables()\r
866     * to find the widgets and places as sortable items to work with this.\r
867     *\r
868     * @access private\r
869     * @see MakeWidgetsSortables()\r
870     * @param settings Array with the plugin settings\r
871     * @return Boolean True in every case\r
872     *\r
873     */\r
874     function GetSortableItems(settings) {\r
875         var fixesSel = '';\r
876         var s = settings;\r
877         // Iterate all the widgets in document\r
878         $(s.selectors.widget).each(function(count) {\r
879             // When found a not movable widget\r
880             if (!$(this).hasClass(s.options.movable)) {\r
881                 // Try to get the widget ID\r
882                 if (!this.id) {\r
883                     // And if not found prepare a special one\r
884                     this.id = 'fixed-widget-id-' + count;\r
885                 }\r
886                 // Because this widget (fixed) not can be\r
887                 // put as a sortable item, so, add to the\r
888                 // fixed widgets selector, to use bellow\r
889                 if (fixesSel == '') {\r
890                     fixesSel += '#' + this.id;\r
891                 } else {\r
892                     fixesSel += ',' + '#' + this.id;\r
893                 }\r
894             }\r
895         });\r
896         // We prepare now the widget that cannot be put as\r
897         // sortable items, because are fixed widgets. We cannot\r
898         // use directly the fixed widgets selectors, because is\r
899         // no one fixed widget is found the selector is like this:\r
900         // :not(), that is, a emtpy "not selector", and this cause\r
901         // problems with jQuery version 1.3\r
902         var notFixes = '';\r
903         if ($.trim(fixesSel) == '') {\r
904             // So, if no fixed widgets are found, dont use the not selector\r
905             notFixes = '> ' + s.selectors.container;\r
906         } else {\r
907             // Use only in case that one or more fixed widgets are found\r
908             notFixes = '> ' + s.selectors.container + ':not(' + fixesSel + ')';\r
909         }\r
910         // Its all. Return not fixed widgets and places as sortable items\r
911         return $(notFixes, s.selectors.places);\r
912     }\r
914     /**\r
915     * Prepare sortables widgets headers\r
916     *\r
917     * This private function is called from another: MakeWidgetsSortables()\r
918     * and is used to prepare the widget headers as sortable items. Some\r
919     * behaviour is needed here, and the mayor part is based in the sortable\r
920     * feature of the jQuery UI library.\r
921     *\r
922     * In other words, this function prepare the widgets sortable headers\r
923     * to can be use as the widget handle, that the users can be use to move\r
924     * the widget into one place to another.\r
925     *\r
926     * For more information we refer you to the jQuery UI sortable feature\r
927     * documentation at this website for example: <http://www.api.jquery.com/>\r
928     *\r
929     * @access private\r
930     * @see MakeWidgetsSortables()\r
931     * @param sortableItems jQuery object with found sortable items\r
932     * @param settings Array with the plugin settings\r
933     * @return Boolean True in every case\r
934     *\r
935     */\r
936     function PrepareSortableHeaders(sortableItems, settings) {\r
937         var s = settings;\r
938         sortableItems.find(s.selectors.header).css({\r
939             cursor: 'move'\r
940         }).mousedown(function(e) {\r
941             var header = $(this);\r
942             var widget = header.parent();\r
943             sortableItems.css({ width: '' });\r
944             widget.css({\r
945                 width: widget.width() + 'px'\r
946             });\r
947         }).mouseup(function() {\r
948             var header = $(this);\r
949             var widget = header.parent();\r
950             if (!widget.hasClass('dragging')) {\r
951                 widget.css({ width: '' });\r
952             } else {\r
953                 $(s.selectors.places).sortable('disable');\r
954             }\r
955         });\r
956         return true;\r
957     }\r
959     /**\r
960     * Prepare sortables widgets places\r
961     *\r
962     * This private function is called from another: MakeWidgetsSortables()\r
963     * and is used to prepare the widget places as sortable items. Some\r
964     * behaviour is needed here, and the mayor part is based in the sortable\r
965     * feature of the jQuery UI library.\r
966     *\r
967     * For more information we refer you to the jQuery UI sortable feature\r
968     * documentation at this website for example: <http://www.api.jquery.com/>\r
969     *\r
970     * @access private\r
971     * @see MakeWidgetsSortables()\r
972     * @see WidgetsPositionsChange()\r
973     * @param sortableItems jQuery object with found sortable items\r
974     * @param settings Array with the plugin settings\r
975     * @return Boolean True in every case\r
976     *\r
977     */\r
978     function PrepareSortablePlaces(sortableItems, settings) {\r
979         var s = settings;\r
980         $(s.selectors.places).sortable('destroy');\r
981         $(s.selectors.places).sortable({\r
982             items: sortableItems,\r
983             containment: 'document',\r
984             forcePlaceholderSize: true,\r
985             handle: s.selectors.header,\r
986             delay: s.behaviour.dragDelay,\r
987             revert: s.behaviour.dragRevert,\r
988             opacity: s.behaviour.dragOpacity,\r
989             connectWith: $(s.selectors.places),\r
990             placeholder: s.selectors.placeHolder,\r
991             start: function(e, ui) {\r
992                 $(ui.helper).addClass('dragging');\r
993                 return true;\r
994             },\r
995             stop: function(e, ui) {\r
996                 WidgetsPositionsChange(s);\r
997                 $(ui.item).css({ width: '' });\r
998                 $(ui.item).removeClass('dragging');\r
999                 $(s.selectors.places).sortable('enable');\r
1000                 if ($.isFunction(s.callbacks.onDragStop)) {\r
1001                     s.callbacks.onDragStop(e, ui);\r
1002                 }\r
1003                 return true;\r
1004             }\r
1005         });\r
1006         // Ok, we take this place to disable widgets based on certain cookie\r
1007         if (s.behaviour.useCookies && (GetCookie(s.cookies.disableName) == 1)) {\r
1008             $.fn.DisableEasyWidgets(s);\r
1009         }\r
1010         return true;\r
1011     }\r
1013     /**\r
1014     * Handle the widgets positions changes\r
1015     *\r
1016     * This function is called from the "stop" event of sortable widgets as\r
1017     * you can see here: PrepareSortablePlaces(), and is used to provide to\r
1018     * you of a string that contain the widgets positions in certain format.\r
1019     *\r
1020     * This string structure is like:\r
1021     *\r
1022     * place-1=widget-1,widget-2|place-1=widget-3,widget-4\r
1023     *\r
1024     * See bellow how we conform this. You can save this string in a database\r
1025     * for example, and provide latter, when the "onRefreshPositions()" callback\r
1026     * is executed. So, the plugin use this string to repositioned the widgets\r
1027     * as you can see in RepositionedWidgets() function.\r
1028     *\r
1029     * @access private\r
1030     * @see RepositionedWidgets()\r
1031     * @see PrepareSortablePlaces()\r
1032     * @param settings Array with the plugin settings\r
1033     * @return Boolean True in every case\r
1034     *\r
1035     */\r
1036     function WidgetsPositionsChange(settings) {\r
1037         var s = settings;\r
1038         var positions = '';\r
1039         $(s.selectors.places).each(function() {\r
1040             var widgets = '';\r
1041             var place = $(this);\r
1042             var places = place.attr('id') + '=';\r
1043             place.children(s.selectors.widget).each(function() {\r
1044                 var widget = this;\r
1045                 var widgetId = widget.id;\r
1046                 var haveId = ($.trim(widgetId) != '');\r
1047                 if (haveId) {\r
1048                     if (widgets == '') {\r
1049                         widgets += widgetId;\r
1050                     } else {\r
1051                         widgets += ',' + widgetId;\r
1052                     }\r
1053                 }\r
1054             });\r
1055             places += widgets;\r
1056             if (positions == '') {\r
1057                 positions += places;\r
1058             } else {\r
1059                 positions += '|' + places;\r
1060             }\r
1061         });\r
1062         // You can save the positions string in a database, for example,\r
1063         // using the "onChangePositions()" plugin callback. So, when the\r
1064         // "onRefreshPositions()" callback is executed, you can retrieve\r
1065         // the string and returnt it: so the plugin use this string to\r
1066         // repositioned the widgets.\r
1067         if ($.isFunction(s.callbacks.onChangePositions)) {\r
1068             s.callbacks.onChangePositions(positions);\r
1069         }\r
1070         // @todo Maybe we only put the positions on the cookie\r
1071         // if the user font use the "onChangePositions()" callback, because\r
1072         // at this time, ever if no use the cookie value (the user provide)\r
1073         // the positions from "onRefreshPositions()" callback) the positions\r
1074         // are saved in the cookie...\r
1075         if (s.behaviour.useCookies) {\r
1076             // However, you need to use the cookies feature\r
1077             // to make possible the widgets repositioned\r
1078             if (GetCookie(s.cookies.positionName) != positions) {\r
1079                 SetCookie(s.cookies.positionName, positions, s);\r
1080             }\r
1081         }\r
1082         return true;\r
1083     }\r
1085     /**\r
1086     * Prepare a widget collapse menu link\r
1087     *\r
1088     * @access private\r
1089     * @see PrepareWidgetBehaviour()\r
1090     * @param widget jQuery object with a widget encapsulation\r
1091     * @param widgetMenu jQuery object with a widget menu encapsulation\r
1092     * @param settings Array with the plugin settings\r
1093     * @return Boolean Truein every case\r
1094     *\r
1095     */\r
1096     function AddWidgetCollapseLink(widget, widgetMenu, settings) {\r
1097         var s = settings;\r
1098         var link = '';\r
1099         var widgetId = widget.attr('id');\r
1100         var haveId = $.trim(widgetId) != '';\r
1101         var content = widget.find(s.selectors.content);\r
1102         if (widget.hasClass(s.options.collapsable)) {\r
1103             if (widget.hasClass(s.options.collapse)) {\r
1104                 link = MenuLink(\r
1105           s.i18n.extendText,\r
1106           s.i18n.extendTitle,\r
1107           s.selectors.collapseLink\r
1108         );\r
1109                 content.hide();\r
1110             } else {\r
1111                 link = MenuLink(\r
1112           s.i18n.collapseText,\r
1113           s.i18n.collapseTitle,\r
1114           s.selectors.collapseLink\r
1115         );\r
1116             }\r
1117             if (haveId && s.behaviour.useCookies &&\r
1118        GetCookie(s.cookies.collapseName) != null) {\r
1119                 var cookieValue = GetCookie(s.cookies.collapseName);\r
1120                 if (cookieValue.indexOf(widgetId) != -1) {\r
1121                     link = MenuLink(\r
1122              s.i18n.extendText,\r
1123              s.i18n.extendTitle,\r
1124              s.selectors.collapseLink\r
1125            );\r
1126                     content.hide();\r
1127                 }\r
1128             }\r
1129             $(link).mousedown(function(e) {\r
1130                 e.stopPropagation();\r
1131             }).click(function() {\r
1132                 var canExtend = true;\r
1133                 var canCollapse = true;\r
1134                 var link = $(this);\r
1135                 var widget = link.parents(s.selectors.widget);\r
1136                 var widgetId = widget.attr('id');\r
1137                 var haveId = $.trim(widgetId) != '';\r
1138                 var content = widget.find(s.selectors.content);\r
1139                 var contentVisible = content.css('display') != 'none';\r
1140                 link.blur();\r
1141                 if (contentVisible) {\r
1142                     if ($.isFunction(s.callbacks.onCollapseQuery)) {\r
1143                         canCollapse = s.callbacks.onCollapseQuery(link, widget);\r
1144                     }\r
1145                     if (canCollapse) {\r
1146                         ApplyEffect(\r
1147               content,\r
1148               s.effects.widgetCollapse,\r
1149               s.effects.effectDuration,\r
1150               false\r
1151             );\r
1152                         link.html(s.i18n.extendText);\r
1153                         link.attr('title', s.i18n.extendTitle);\r
1154                         if (s.behaviour.useCookies && widgetId) {\r
1155                             UpdateCookie(widgetId, s.cookies.collapseName, s);\r
1156                         }\r
1157                         if ($.isFunction(s.callbacks.onCollapse)) {\r
1158                             s.callbacks.onCollapse(link, widget);\r
1159                         }\r
1160                     }\r
1161                 } else {\r
1162                     if ($.isFunction(s.callbacks.onExtendQuery)) {\r
1163                         canExtend = s.callbacks.onExtendQuery(link, widget);\r
1164                     }\r
1165                     if (canExtend) {\r
1166                         link.html(s.i18n.collapseText);\r
1167                         link.attr('title', s.i18n.collapseTitle);\r
1168                         ApplyEffect(\r
1169               content,\r
1170               s.effects.widgetExtend,\r
1171               s.effects.effectDuration,\r
1172               true\r
1173             );\r
1174                         if (haveId && s.behaviour.useCookies) {\r
1175                             CleanCookie(widgetId, s.cookies.collapseName, s);\r
1176                         }\r
1177                         if ($.isFunction(s.callbacks.onExtend)) {\r
1178                             s.callbacks.onExtend(link, widget);\r
1179                         }\r
1180                     }\r
1181                 }\r
1182                 return false;\r
1183             }).appendTo(widgetMenu);\r
1184         }\r
1185         return true;\r
1186     }\r
1188     /**\r
1189     * Prepare a widget edit menu link\r
1190     *\r
1191     * @access private\r
1192     * @see PrepareWidgetBehaviour()\r
1193     * @param widget jQuery object with a widget encapsulation\r
1194     * @param widgetMenu jQuery object with a widget menu encapsulation\r
1195     * @param settings Array with the plugin settings\r
1196     * @return Boolean Truein every case\r
1197     *\r
1198     */\r
1199     function AddWidgetEditLink(widget, widgetMenu, settings) {\r
1200         var s = settings;\r
1201         var link = '';\r
1202         if (widget.hasClass(s.options.editable)) {\r
1203             link = MenuLink(\r
1204         s.i18n.editText,\r
1205         s.i18n.editTitle,\r
1206         s.selectors.editLink\r
1207       );\r
1208             widget.find(s.selectors.closeEdit).click(function(e) {\r
1209                 var link = $(this);\r
1210                 var widget = link.parents(s.selectors.widget);\r
1211                 var editbox = widget.find(s.selectors.editbox);\r
1212                 var editLink = widget.find(s.selectors.editLink);\r
1213                 link.blur();\r
1214                 ApplyEffect(\r
1215           editbox,\r
1216           s.effects.widgetCloseEdit,\r
1217           s.effects.effectDuration,\r
1218           false\r
1219         );\r
1220                 editLink.html(s.i18n.editText);\r
1221                 editLink.attr('title', s.i18n.editTitle);\r
1222                 return false;\r
1223             });\r
1224             $(link).mousedown(function(e) {\r
1225                 e.stopPropagation();\r
1226             }).click(function() {\r
1227                 var link = $(this);\r
1228                 var canShow = canHide = true;\r
1229                 var widget = link.parents(s.selectors.widget);\r
1230                 var editbox = widget.find(s.selectors.editbox);\r
1231                 var editboxVisible = editbox.css('display') != 'none';\r
1232                 link.blur();\r
1233                 if (editboxVisible) {\r
1234                     if ($.isFunction(s.callbacks.onCancelEditQuery)) {\r
1235                         canHide = s.callbacks.onCancelEditQuery(link, widget);\r
1236                     }\r
1237                     if (canHide) {\r
1238                         ApplyEffect(\r
1239               editbox,\r
1240               s.effects.widgetCancelEdit,\r
1241               s.effects.effectDuration,\r
1242               false\r
1243             );\r
1244                         link.html(s.i18n.editText);\r
1245                         link.attr('title', s.i18n.editTitle);\r
1246                         if ($.isFunction(s.callbacks.onCancelEdit)) {\r
1247                             s.callbacks.onCancelEdit(link, widget);\r
1248                         }\r
1249                     }\r
1250                 } else {\r
1251                     if ($.isFunction(s.callbacks.onEditQuery)) {\r
1252                         canShow = s.callbacks.onEditQuery(link, widget);\r
1253                     }\r
1254                     if (canShow) {\r
1255                         link.html(s.i18n.cancelEditText);\r
1256                         link.attr('title', s.i18n.cancelEditTitle);\r
1257                         ApplyEffect(\r
1258               editbox,\r
1259               s.effects.widgetOpenEdit,\r
1260               s.effects.effectDuration,\r
1261               true\r
1262             );\r
1263                         if ($.isFunction(s.callbacks.onEdit)) {\r
1264                             s.callbacks.onEdit(link, widget);\r
1265                         }\r
1266                     }\r
1267                 }\r
1268                 return false;\r
1269             }).appendTo(widgetMenu);\r
1270         }\r
1271         return true;\r
1272     }\r
1274     /**\r
1275     * Prepare a widget remove menu link\r
1276     *\r
1277     * @access private\r
1278     * @see PrepareWidgetBehaviour()\r
1279     * @param widget jQuery object with a widget encapsulation\r
1280     * @param widgetMenu jQuery object with a widget menu encapsulation\r
1281     * @param settings Array with the plugin settings\r
1282     * @return Boolean Truein every case\r
1283     *\r
1284     */\r
1285     function AddWidgetRemoveLink(widget, widgetMenu, settings) {\r
1286         var s = settings;\r
1287         var link = '';\r
1288         if (widget.hasClass(s.options.removable)) {\r
1289             link = MenuLink(\r
1290         s.i18n.closeText,\r
1291         s.i18n.closeTitle,\r
1292         s.selectors.closeLink\r
1293       );\r
1294             $(link).mousedown(function(e) {\r
1295                 e.stopPropagation();\r
1296             }).click(function() {\r
1297                 var link = $(this);\r
1298                 var canRemove = true;\r
1299                 var widget = link.parents(s.selectors.widget);\r
1300                 var widgetId = widget.attr('id');\r
1301                 var haveId = ($.trim(widgetId) != '');\r
1302                 link.blur();\r
1303                 if ($.isFunction(s.callbacks.onCloseQuery)) {\r
1304                     canRemove = s.callbacks.onCloseQuery(link, widget);\r
1305                 }\r
1306                 if (canRemove) {\r
1307                     if (!widget.hasClass(s.options.closeConfirm)\r
1308             || confirm(s.i18n.confirmMsg)) {\r
1309                         if (haveId && s.behaviour.useCookies) {\r
1310                             UpdateCookie(widgetId, s.cookies.closeName, s);\r
1311                         }\r
1312                         ApplyEffect(\r
1313                 widget,\r
1314                 s.effects.widgetClose,\r
1315                 s.effects.effectDuration,\r
1316                 false\r
1317               );\r
1318                         if ($.isFunction(s.callbacks.onClose)) {\r
1319                             s.callbacks.onClose(link, widget);\r
1320                         }\r
1321                     }\r
1322                 }\r
1323                 return false;\r
1324             }).appendTo(widgetMenu);\r
1325         }\r
1326         return true;\r
1327     }\r
1329     /**\r
1330     * Clean widgets related cookies\r
1331     *\r
1332     * This private function is called from InitializeWidgets() and used to\r
1333     * clean certain widgets related cookies. What is this? Well, basically\r
1334     * here we find for no more used widgets IDs into the appropiate cookies\r
1335     * values, and remove from this.\r
1336     *\r
1337     * Why? Because in this form the related cookies ever still clean. ;)\r
1338     * This cookies are the "closed widgets" and "collapses widgets" cookies,\r
1339     * that store widgets IDs in the same way: separated by commas. So, find\r
1340     * widgets IDs that in fact not found in the document, and remove from the\r
1341     * appropiate cookie value, remainded the rest of the widgets IDs.\r
1342     *\r
1343     * Because this function is called from the main plugin method, called\r
1344     * itself every time that a page that contain widgets is refresh, or when\r
1345     * add widgets on demand, we only try to clean the cookies in a "random"\r
1346     * mode, because, finally, is not problem that a cookie contain widgets\r
1347     * IDs that dont exists.\r
1348     *\r
1349     * So, to save resources, we clean the cookies only in no on demand widgets,\r
1350     * and only in some "random" times, as you can see in the bellow code.\r
1351     *\r
1352     * @access private\r
1353     * @see InitializeWidgets()\r
1354     * @param settings Array with the plugin settings\r
1355     * @param widgetOnDemand Boolean Depend if deal with on demand widget or not\r
1356     * @return Boolean True in every case\r
1357     *\r
1358     */\r
1359     function CleanWidgetsCookies(settings, widgetOnDemand) {\r
1360         var s = settings;\r
1361         var cleanCookies = !widgetOnDemand && s.behaviour.useCookies\r
1362       && (Math.ceil(Math.random() * 3) == 1);\r
1363         if (cleanCookies) {\r
1364             var i = j = 0;\r
1365             var cookies = new Array(\r
1366         s.cookies.closeName,\r
1367         s.cookies.collapseName\r
1368       );\r
1369             var cookiesLen = cookies.length;\r
1370             var widgetsIds = new Array();\r
1371             $(s.selectors.widget).each(function(count) {\r
1372                 var widgetId = $(this).attr('id');\r
1373                 if ($.trim(widgetId) != '') {\r
1374                     widgetsIds[count] = widgetId;\r
1375                 }\r
1376             });\r
1377             for (i = 0; i < cookiesLen; i++) {\r
1378                 if (GetCookie(cookies[i])) {\r
1379                     var widgetId = '';\r
1380                     var cleanValue = '';\r
1381                     var storedValue = GetCookie(cookies[i]).split(',');\r
1382                     var storedWidgets = storedValue.length;\r
1383                     for (j = 0; j < storedWidgets; j++) {\r
1384                         widgetId = $.trim(storedValue[j]);\r
1385                         if ($.inArray(widgetId, widgetsIds) != -1) {\r
1386                             if ($.trim(cleanValue) == '') {\r
1387                                 cleanValue += widgetId;\r
1388                             } else {\r
1389                                 cleanValue += ',' + widgetId;\r
1390                             }\r
1391                         }\r
1392                     }\r
1393                     SetCookie(cookies[i], cleanValue, s);\r
1394                 }\r
1395             }\r
1396         }\r
1397         return true;\r
1398     }\r
1400     /**\r
1401     * Get a specific cookie value\r
1402     *\r
1403     * This function is based in jQuery Cookie plugin by Klaus Hartl\r
1404     *\r
1405     * @access private\r
1406     * @param name String with the cookie name\r
1407     * @return Null|String Cookie value or nothing\r
1408     *\r
1409     */\r
1410     function GetCookie(name) {\r
1411         var result = null;\r
1412         if (document.cookie && $.trim(document.cookie) != '') {\r
1413             var cookies = document.cookie.split(';');\r
1414             var cookiesLen = cookies.length;\r
1415             if (cookiesLen > 0) {\r
1416                 for (var i = 0; i < cookiesLen; i++) {\r
1417                     var cookie = $.trim(cookies[i]);\r
1418                     if (cookie.substring(0, name.length + 1) == (name + '=')) {\r
1419                         result = decodeURIComponent(cookie.substring(name.length + 1));\r
1420                         break;\r
1421                     }\r
1422                 }\r
1423             }\r
1424         }\r
1425         return result;\r
1426     }\r
1428     /**\r
1429     * Set a specific cookie value\r
1430     *\r
1431     * This function is based in jQuery Cookie plugin by Klaus Hartl\r
1432     *\r
1433     * @access private\r
1434     * @param name String with the cookie name\r
1435     * @param value String with the cookie value\r
1436     * @param settings Array with plugin settings to use\r
1437     * @return Boolean True in every case\r
1438     *\r
1439     */\r
1440     function SetCookie(name, value, settings) {\r
1441         var s = settings;\r
1442         var expires = '';\r
1443         var nType = 'number';\r
1444         if (s.cookies.expires && (typeof s.cookies.expires\r
1445      == nType) || s.cookies.expires.toUTCString) {\r
1446             var date = null;\r
1447             if (typeof s.cookies.expires == nType) {\r
1448                 date = new Date();\r
1449                 date.setTime(date.getTime() + (s.cookies.expires * 24 * 60 * 60 * 1000));\r
1450             } else {\r
1451                 date = s.cookies.expires;\r
1452             }\r
1453             // use expires attribute, max-age is not supported by IE\r
1454             expires = '; expires=' + date.toUTCString();\r
1455         }\r
1456         var path = s.cookies.path ? '; path=' + s.cookies.path : '';\r
1457         var domain = s.cookies.domain ? '; domain=' + s.cookies.domain : '';\r
1458         var secure = s.cookies.secure ? '; secure' : '';\r
1459         document.cookie = [name, '=', encodeURIComponent(value),\r
1460      expires, path, domain, secure].join('');\r
1461         return true;\r
1462     }\r
1464     /**\r
1465     * Clean a Widget Id from a cookie\r
1466     *\r
1467     * We use this in some places, so, centralize here. We clean certain\r
1468     * related cookie: two of the plugins related cookies using the same\r
1469     * structure to save their data, and can be clean in the same way.\r
1470     *\r
1471     * A string with comma separated Widgets IDs is stored in this cookies,\r
1472     * and "clean a cookie" want to say: remove certain Widget ID from this\r
1473     * cookie, because this widget is now visible or extended.\r
1474     *\r
1475     * @access private\r
1476     * @param widgetId String with a Widget identifier\r
1477     * @param cookieName String with the cookie name\r
1478     * @param settings Array with plugin settings to use\r
1479     * @return Boolean True in every case\r
1480     *\r
1481     */\r
1482     function CleanCookie(widgetId, cookieName, settings) {\r
1483         var value = GetCookie(cookieName);\r
1484         if (value != null) {\r
1485             if (value.indexOf(widgetId) != -1) {\r
1486                 value = value.replace(',' + widgetId, '');\r
1487                 value = value.replace(widgetId + ',', '');\r
1488                 value = value.replace(widgetId, '');\r
1489             }\r
1490             SetCookie(cookieName, value, settings);\r
1491         }\r
1492         return true;\r
1493     }\r
1495     /**\r
1496     * Update a Widget Id from a cookie\r
1497     *\r
1498     * We use this in some places, so, centralize here. We update certain\r
1499     * related cookie: two of the plugins related cookies using the same\r
1500     * structure to save their data, and can be update in the same way.\r
1501     *\r
1502     * A string with comma separated Widgets IDs is stored in this cookies,\r
1503     * and "update a cookie" want to say: put certain Widget ID in this\r
1504     * cookie, because this widget is now closed or collapsed.\r
1505     *\r
1506     * @access private\r
1507     * @param widgetId String with a Widget identifier\r
1508     * @param cookieName String with the cookie name\r
1509     * @param settings Array with plugin settings to use\r
1510     * @return Boolean True in every case\r
1511     *\r
1512     */\r
1513     function UpdateCookie(widgetId, cookieName, settings) {\r
1514         var value = GetCookie(cookieName);\r
1515         if (value == null) {\r
1516             value = widgetId;\r
1517         } else if (value.indexOf(widgetId) == -1) {\r
1518             value = value + ',' + widgetId;\r
1519         }\r
1520         SetCookie(cookieName, value, settings);\r
1521         return true;\r
1522     }\r
1524     /**\r
1525     * Auxiliar function to prepare Widgets header menu links.\r
1526     *\r
1527     * @access private\r
1528     * @param text Link text\r
1529     * @param title Link title\r
1530     * @param aClass CSS class (behaviour) of link\r
1531     * @return String HTML of the link\r
1532     *\r
1533     */\r
1534     function MenuLink(text, title, aClass) {\r
1535         var l = '<a href="#" title="TITLE" class="CLASS">TEXT</a>';\r
1536         l = l.replace(/TEXT/g, text);\r
1537         l = l.replace(/TITLE/g, title);\r
1538         l = l.replace(/CLASS/g, aClass.replace(/\./, ''));\r
1539         return l;\r
1540     }\r
1542     /**\r
1543     * Auxiliar function to show, hide and apply effects.\r
1544     *\r
1545     * @access private\r
1546     * @param jqObj jQuery object to apply the effect and show or hide\r
1547     * @param effect String that identifier what effect must be applied\r
1548     * @param duration Miliseconds to the effect duration\r
1549     * @param show Boolean True if want to show the object, False to be hide\r
1550     * @return Boolean True in every case\r
1551     *\r
1552     */\r
1553     function ApplyEffect(jqObj, effect, duration, show) {\r
1554         var n = 'none',\r
1555         f = 'fade',\r
1556         s = 'slide';\r
1557         if (!show) {\r
1558             if (effect == n) {\r
1559                 jqObj.hide();\r
1560             } else if (effect == f) {\r
1561                 jqObj.fadeOut(duration);\r
1562             } else if (effect == s) {\r
1563                 jqObj.slideUp(duration);\r
1564             }\r
1565         } else {\r
1566             if (effect == n) {\r
1567                 jqObj.show();\r
1568             } else if (effect == f) {\r
1569                 jqObj.fadeIn(duration);\r
1570             } else if (effect == s) {\r
1571                 jqObj.slideDown(duration);\r
1572             }\r
1573         }\r
1574         return true;\r
1575     }\r
1576 })(jQuery);\r