jquery.easywidgets.js
上传用户:jhh8446530
上传日期:2016-01-28
资源大小:116k
文件大小:29k
源码类别:

Ajax

开发平台:

JavaScript

  1. /*
  2.    Copyrights (C) 2008 David Esperalta <davidesperalta@gmail.com>
  3.    This file is part of Easy Widgets jQuery plugin for jQuery
  4.    Easy Widgets is free software: you can redistribute it and/or
  5.    modify it under the terms of the GNU General Public License as
  6.    published by the Free Software Foundation, either version 3 of
  7.    the License, or (at your option) any later version.
  8.    Easy Widgets is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11.    General Public License for more details.
  12.    You should have received a copy of the GNU General Public License
  13.    along with Easy Widgets. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. /**
  16.  * Easy Widgets jQuery plugin 1.0 (beta)
  17.  * 
  18.  * David Esperalta - http://www.bitacora.davidesperalta.com/
  19.  *
  20.  * Please, use the included documentation and examples for
  21.  * information about how use this plugin. Thanks very much!
  22.  *
  23.  * Tested in Firefox 3, Opera 9, IExplorer 7 and Safari 3
  24.  *
  25.  * I base my work on a tutorial writen by James Padolsey
  26.  * http://nettuts.com/tutorials/javascript-ajax/inettuts/
  27.  */
  28. /**
  29.  * Begin the plugin workspace
  30.  */
  31. (function($){
  32.   /**
  33.    * This is the main method of the plugin. Is called when Widgets HTML
  34.    * markup, to execute the appropiate Javascript over it.
  35.    * 
  36.    * The method receive the settings argument with some options. If no
  37.    * argument is receive the method use the default plugin settins.
  38.    *
  39.    * See the default settings for this method bello, in this same script.
  40.    *
  41.    * @access public
  42.    * @param settings Array with the plugin options
  43.    * @return Boolean True in every case
  44.    */
  45.   $.fn.EasyWidgets = function(settings){
  46.     /**
  47.      * Initialize some useful variables
  48.      */
  49.     var widgetCount = 0;
  50.     var widgetsIds = new Array();
  51.     /**
  52.      * Recursively extend settings with default plugin settings
  53.      * Put the settings in a short variable for we convenience
  54.      */
  55.     var s = $.extend(true, $.fn.EasyWidgets.defaults, settings);
  56.     /**
  57.      * By default the Widgets editbox are hidden.
  58.      */
  59.     $(s.selectors.editbox).hide();
  60.     /**
  61.      * Prepare the Widget header menu links container
  62.      */
  63.     var menuLinksHtm = '<span class="' + s.selectors
  64.      .menuLinks.replace(/./, '') + '"></span>';
  65.     $(menuLinksHtm).appendTo(s.selectors.handle, this);
  66.     /**
  67.      * Iterate the Widgets found in the document, in other words
  68.      * execute some actions for every Widget found in the document
  69.      */
  70.     $(s.selectors.widget).each(function(){
  71.       /**
  72.        * Increment the widget count variable
  73.        */
  74.       widgetCount++;
  75.       /**
  76.        * Initialize some other variables for we convenience in this
  77.        * workspace. Is more easy (we think) use thisWidget variable
  78.        * insted the $(this) instruction, specially whe use to much.
  79.        */
  80.       var cookieValue = '';
  81.       var thisWidget = $(this);
  82.       var thisWidgetId = thisWidget.attr('id');
  83.       var thisMenuLinks = thisWidget.find(s.selectors.menuLinks);
  84.       var thisWidgetContent = thisWidget.find(s.selectors.content);
  85.       var useCookies = (thisWidgetId && s.behaviour.useCookies && $.cookie);
  86.       /**
  87.        * Begin the work
  88.        */
  89.       if(thisWidgetId){
  90.         // Store the Widget ID, if anyone found
  91.         widgetsIds[widgetCount] = thisWidgetId;
  92.       }
  93.       /**
  94.        * Find if the user want to use cookies or what
  95.        * In this case we can find if the Widget must
  96.        * be positioned in certain Widgets column
  97.        */
  98.       if(useCookies && $.cookie(s.cookies.positionName)){
  99.         // Get the positions cookie value
  100.         cookieValue = $.cookie(s.cookies.positionName);
  101.         // Find if the Widget ID is in the positions cookie
  102.         if(cookieValue.indexOf(thisWidgetId) != -1){
  103.           // Find the column to append the positioned Widget
  104.           var matched = cookieValue.match(thisWidgetId+"=(.*)");
  105.           if(matched){
  106.             // Append theWidget to matched column
  107.             thisWidget.appendTo('#'+matched[1]);
  108.           }
  109.         }
  110.       }
  111.       /**
  112.        * In this case we can find if the Widget must
  113.        * be closed (hidden) or not.
  114.        */
  115.       if(useCookies && $.cookie(s.cookies.closeName)){
  116.         cookieValue = $.cookie(s.cookies.closeName);
  117.         if(cookieValue.indexOf(thisWidgetId) != -1){
  118.           thisWidget.hide();
  119.         }
  120.       }
  121.       /**
  122.        * We prepare now the collapse Widget link. This link
  123.        * can be used to collapse and extend the Widget.
  124.        */
  125.       var collapseLink = '';
  126.       /**
  127.        * However, the collapse link only appear if user want
  128.        * with the appropiate class in the Widget HTML markup
  129.        */
  130.       if(thisWidget.hasClass(s.options.collapsable)){
  131.         /**
  132.          * Take a look: we find if the user want to collapse
  133.          * this Widget from the begin, using another CSS class
  134.          *
  135.          * We continue with the link creation, but, the text
  136.          * link and the link behaviour change: can be use to
  137.          * expand the Widget, not to collapse
  138.          */
  139.         if(thisWidget.hasClass(s.options.collapse)){
  140.           collapseLink = WidgetLink(
  141.             s.i18n.extendText,
  142.             s.i18n.extendTitle,
  143.             s.selectors.collapseLink
  144.           );
  145.           thisWidgetContent.hide();
  146.         }else{
  147.           collapseLink = WidgetLink(
  148.             s.i18n.collapseText, 
  149.             s.i18n.collapseTitle,
  150.             s.selectors.collapseLink
  151.           );
  152.         }
  153.         /**
  154.          * Note how the use of cookies can overwrite this link behaviour
  155.          * In other words, the Widget HTML markup can determine that the
  156.          * Widget is collapse or not, but if use cookies the cookie value
  157.          * can change this link behaviour
  158.          */
  159.         if(useCookies){
  160.           cookieValue = $.cookie(s.cookies.collapseName);
  161.           if(cookieValue){
  162.             if(cookieValue.indexOf(thisWidgetId) != -1){
  163.               collapseLink = WidgetLink(
  164.                 s.i18n.extendText,
  165.                 s.i18n.extendTitle,
  166.                 s.selectors.collapseLink
  167.               );
  168.               thisWidgetContent.hide();
  169.             }
  170.           }
  171.         }
  172.         /**
  173.          * Above we prepare the link text, title and CSS class (determine
  174.          * the link behaviour). Here we prepare the execution of this link,
  175.          * in other words, handle the "onmousedown" and "onclick" link events.
  176.          */
  177.         $(collapseLink).mousedown(function(e){
  178.           
  179.           e.stopPropagation();
  180.         }).click(function(){
  181.           /**
  182.            * Some variables for we convenience in this workspace
  183.            */
  184.           var thisLink = $(this);
  185.           var canbeExtend = true;
  186.           var canbeCollapse = true;
  187.           var thisWidget = thisLink.parents(s.selectors.widget);
  188.           var thisWidgetId = thisWidget.attr('id');
  189.           var thisWidgetContent = thisWidget.find(s.selectors.content);
  190.           var contentVisible = thisWidgetContent.css('display') != 'none';
  191.           var useCookie = thisWidgetId && s.behaviour.useCookies && $.cookie;
  192.           thisLink.blur();
  193.           /**
  194.            * Remember the workspace, here we handle the "onclick" event
  195.            * of this link. So, the user use the link and expect something
  196.            */
  197.           if(contentVisible){
  198.             // If Widget content is visible, user want to collapse the Widget
  199.             if(s.callbacks.onCollapseQuery != null){
  200.               // Call the appropiate plugin callback for this action
  201.               canbeCollapse = s.callbacks.onCollapseQuery(thisLink, thisWidget);
  202.             }
  203.             // By default the Widget can be collapse, but the plugin callback
  204.             // can change the behaviour using the collapse variable
  205.             if(canbeCollapse){
  206.               // If true, finally the Widget must be collapse
  207.               thisWidgetContent.hide();
  208.               thisLink.html(s.i18n.extendText);
  209.               thisLink.attr('title', s.i18n.extendTitle);
  210.               if(useCookie){
  211.                 // And prepare the collapse cookies if is use
  212.                 var cookieValue = $.cookie(s.cookies.collapseName);
  213.                 if(!cookieValue){
  214.                   cookieValue = thisWidgetId;
  215.                 }else if(cookieValue.indexOf(thisWidgetId) == -1){
  216.                   cookieValue = cookieValue+','+thisWidgetId;
  217.                 }
  218.                 $.cookie(s.cookies.collapseName, cookieValue, {
  219.                   path: s.cookies.path,
  220.                   secure: s.cookies.secure,
  221.                   domain: s.cookies.domain,
  222.                   expires: s.cookies.expires
  223.                 });
  224.               }
  225.               if(s.callbacks.onCollapse != null){
  226.                 s.callbacks.onCollapse(thisLink, thisWidget);
  227.               }
  228.             }
  229.           /**
  230.            * The Widget content is not visible, in other words, the user
  231.            * want to expand the Widget
  232.            */
  233.           }else{
  234.             if(s.callbacks.onExtendQuery != null){
  235.               // Call the appropiate plugin callback
  236.               canbeExtend = s.callbacks.onExtendQuery(thisLink, thisWidget);
  237.             }
  238.             // If finally the Widget can be extended, show it
  239.             if(canbeExtend){
  240.               thisLink.html(s.i18n.collapseText);
  241.               thisLink.attr('title', s.i18n.collapseTitle);
  242.               thisWidgetContent.show();
  243.               if(useCookie){
  244.                 // And update the collapse cookie value, removing this Widget
  245.                 cookieValue = $.cookie(s.cookies.collapseName);
  246.                 if(cookieValue.indexOf(thisWidgetId) != -1){
  247.                   cookieValue = cookieValue.replace(','+thisWidgetId, '');
  248.                   cookieValue = cookieValue.replace(thisWidgetId+',', '');
  249.                   cookieValue = cookieValue.replace(thisWidgetId, '');
  250.                 }
  251.                 $.cookie(s.cookies.collapseName, cookieValue, {
  252.                   path: s.cookies.path,
  253.                   secure: s.cookies.secure,
  254.                   domain: s.cookies.domain,
  255.                   expires: s.cookies.expires
  256.                 });
  257.               }
  258.               if(s.callbacks.onExtend != null){
  259.                 s.callbacks.onExtend(thisLink, thisWidget);
  260.               }
  261.             }
  262.           }
  263.           // Ever return false to evit default link behaviour
  264.           return false;
  265.         }).appendTo($(thisMenuLinks, this));
  266.       }
  267.       
  268.       /**
  269.        * We prepare now the edit Widget link. This link
  270.        * can be used to show the Widget editbox.
  271.        */
  272.       var editLink = '';
  273.       /**
  274.        * However, the edit link only appear if user want
  275.        * with the appropiate class in the Widget HTML markup
  276.        */
  277.       if(thisWidget.hasClass(s.options.editable)){
  278.         /**
  279.          * Text, title and behaviour for this link
  280.          */
  281.         editLink = WidgetLink(
  282.           s.i18n.editText, 
  283.           s.i18n.editTitle,
  284.           s.selectors.editLink
  285.         );
  286.         /**
  287.          * Another plugin options are the use of close edit CSS
  288.          * class into the Widget editbox container. If the class
  289.          * exists, attach a method for handle their "onclick" event
  290.          */
  291.         thisWidget.find(s.selectors.closeEdit).click(function(e){
  292.           var thisLink = $(this);
  293.           var thisWidget = thisLink.parents(s.selectors.widget);
  294.           var thisEditLink = thisWidget.find(s.selectors.editLink);
  295.           var thisEditbox = thisWidget.find(s.selectors.editbox);
  296.           thisLink.blur();
  297.           thisEditbox.hide();
  298.           thisEditLink.html(s.i18n.editText);
  299.           thisEditLink.attr('title', s.i18n.editTitle);
  300.           // Ever return false to evit default link behaviour
  301.           return false;
  302.         });
  303.         /**
  304.          * Above we prepare the link text, title and CSS class (determine
  305.          * the link behaviour). Here we prepare the execution of this link,
  306.          * in other words, handle the "onmousedown" and "onclick" link events.
  307.          */
  308.         $(editLink).mousedown(function(e){
  309.           e.stopPropagation();
  310.           
  311.         }).click(function(){
  312.           /**
  313.            * Again initialize some variables for this workspace
  314.            */
  315.           var canbeShow = true;
  316.           var canbeHide = true;
  317.           var thisLink = $(this);
  318.           var thisWidget = thisLink.parents(s.selectors.widget);
  319.           var thisEditbox = thisWidget.find(s.selectors.editbox);
  320.           var thisEditboxVisible = thisEditbox.css('display') != 'none';
  321.           thisLink.blur();
  322.           /**
  323.            * Remember the workspace, we handle here the "onclick" event
  324.            * of the Widget, so, if the Widget editbox is visible, the user
  325.            * want to hide (close) the Widget editbox.
  326.            */
  327.           if(thisEditboxVisible){
  328.             if(s.callbacks.onCancelEditQuery != null){
  329.               canbeHide = s.callbacks.onCancelEditQuery(thisLink, thisWidget);
  330.             }
  331.             if(canbeHide){
  332.               thisEditbox.hide();
  333.               thisLink.html(s.i18n.editText);
  334.               thisLink.attr('title', s.i18n.editTitle);
  335.               if(s.callbacks.onCancelEdit != null){
  336.                 s.callbacks.onCancelEdit(thisLink, thisWidget);
  337.               }
  338.             }
  339.           /**
  340.            * If the Widget editbox is not visible, the user want to view
  341.            */
  342.           }else{
  343.             if(s.callbacks.onEditQuery != null){
  344.               // A plugin callback have the opportunity of handle this
  345.               canbeShow = s.callbacks.onEditQuery(thisLink, thisWidget);
  346.             }
  347.             if(canbeShow){
  348.               // Ok, finally show the Widget edit box
  349.               thisLink.html(s.i18n.cancelEditText);
  350.               thisLink.attr('title', s.i18n.cancelEditTitle);
  351.               thisEditbox.show();
  352.               if(s.callbacks.onEdit != null){
  353.                 s.callbacks.onEdit(thisLink, thisWidget);
  354.               }
  355.             }
  356.           }
  357.           // Ever return false to evit default link behaviour
  358.           return false;
  359.         }).appendTo($(thisMenuLinks, this));
  360.       }
  361.       /**
  362.        * Now is the turn of the remove Widget link. This link can be
  363.        * use to close (hide) the Widget. Note that no link to show the
  364.        * Widget is provided: when a Widget is hidden, is hidden.
  365.        */
  366.       var removeLink = '';
  367.       /**
  368.        * However, the remove link only appear if user want
  369.        * with the appropiate class in the Widget HTML markup
  370.        */
  371.       if(thisWidget.hasClass(s.options.removable)){
  372.         /**
  373.          * Text, title and behaviour for this link
  374.          */
  375.         removeLink = WidgetLink(
  376.           s.i18n.closeText, 
  377.           s.i18n.closeTitle,
  378.           s.selectors.closeLink
  379.         );
  380.         /**
  381.          * After the text, title and behaviour for this link, is turn
  382.          * for handle the "onmousedown" and "onclick" events
  383.          */
  384.         $(removeLink).mousedown(function(e){
  385.           e.stopPropagation();
  386.         }).click(function(){
  387.           /**
  388.            * Variables for we convenience in this workspace
  389.            */
  390.           var canbeRemove = true;
  391.           var thisLink = $(this);
  392.           var thisWidget = thisLink.parents(s.selectors.widget);
  393.           var thisWidgetId = thisWidget.attr('id');
  394.           var useCookie = (thisWidgetId && s.behaviour.useCookies && $.cookie);
  395.           thisLink.blur();
  396.           
  397.           if(s.callbacks.onCloseQuery != null){
  398.             // An opportunity to not close the Widget
  399.             canbeRemove = s.callbacks.onCloseQuery(thisLink, thisWidget);
  400.           }
  401.           if(canbeRemove){
  402.             /**
  403.              * Another options of this plugin can be use to show a confirm
  404.              * dialog to the user before close the Widget. So, take a look
  405.              * at the bellow condition: if the Widget have the CSS class
  406.              * that we expect, we use the confirm dialog. In other case
  407.              * the confirm dialog not it show.
  408.              */
  409.             if(!thisWidget.hasClass(s.options.closeConfirm)
  410.              || confirm(s.i18n.confirmMsg)){
  411.                if(useCookie){
  412.                  // Store this Widget ID in the Widget closes cookie
  413.                  var cookieValue = $.cookie(s.cookies.closeName);
  414.                  if(!cookieValue){
  415.                    cookieValue = thisWidgetId;
  416.                  }else if(cookieValue.indexOf(thisWidgetId) == -1){
  417.                    cookieValue = cookieValue+','+thisWidgetId;
  418.                  }
  419.                  $.cookie(s.cookies.closeName, cookieValue, {
  420.                    path: s.cookies.path,
  421.                    secure: s.cookies.secure,
  422.                    domain: s.cookies.domain,
  423.                    expires: s.cookies.expires
  424.                  });
  425.                }
  426.                thisWidget.hide();
  427.                if(s.callbacks.onClose != null){
  428.                  s.callbacks.onClose(thisLink, thisWidget);
  429.                }
  430.             }
  431.           }
  432.           // Ever return false to evit default link behaviour
  433.           return false;
  434.         }).appendTo($(thisMenuLinks, this));
  435.       }
  436.     });
  437.     /**
  438.      * All the Widgets and header links is not ready. Now begin the
  439.      * preparation of the sortable stuff for Widgets and Widgets columns.
  440.      */
  441.     var sortableItems = null;
  442.     /**
  443.      * Finf all the Widgets that we turn bellow in sortable items
  444.      */
  445.     sortableItems = (function(){
  446.       var fixedWidgets = '';
  447.       /**
  448.        * Iterate for all Widgets
  449.        */
  450.       $(s.selectors.widget).each(function(count){
  451.         /**
  452.          * And find for movables or fixed Widgets
  453.          */
  454.         if(!$(this).hasClass(s.options.movable)){
  455.           if(!this.id){
  456.             // Unique ID for the Widget in any case
  457.             this.id = 'widget-without-id-' + count;
  458.           }
  459.           fixedWidgets += '#'+this.id+',';
  460.         }
  461.       });
  462.       /**
  463.        * Finally return movable Widgets and Widgets columns as sortable items
  464.        * Take a look at the container option: determine the Widget container
  465.        * and can be "div", "li" or another. By default is a "div", that is,
  466.        * the Widget is stored in a "div" container.
  467.        */
  468.       return $('> '+s.selectors.container+':not(' + fixedWidgets + ')',
  469.        s.selectors.columns);
  470.     })();
  471.     
  472.     /**
  473.      * Prepare the Widget headers of movable Widgets found. Set their
  474.      * cursor and handle their "onmosedown" and "onmouseup" events.
  475.      */
  476.     sortableItems.find(s.selectors.handle).css({
  477.       cursor: 'move'
  478.     }).mousedown(function(e){
  479.       var thisHeader = $(this);
  480.       sortableItems.css({width:''});
  481.       thisHeader.parent().css({
  482.         width: thisHeader.parent().width() + 'px'
  483.       });
  484.    }).mouseup(function(){
  485.       var thisHeader = $(this);
  486.       if(!thisHeader.parent().hasClass('dragging')){
  487.         thisHeader.parent().css({width:''});
  488.       }else{
  489.         $(s.selectors.columns).sortable('disable');
  490.       }
  491.     });
  492.     /**
  493.      * Now we are prepared to call the sortable jQuery function
  494.      * over the Widgets columns found in the document. More information
  495.      * about this function can be found in the jQuery Wiki website.
  496.      */
  497.     $(s.selectors.columns).sortable({
  498.       items: sortableItems,
  499.       containment: 'document',
  500.       forcePlaceholderSize: true,
  501.       handle: s.selectors.handle,
  502.       delay: s.behaviour.dragDelay,
  503.       revert: s.behaviour.dragRevert,
  504.       opacity: s.behaviour.dragOpacity,
  505.       connectWith: $(s.selectors.columns),
  506.       placeholder: s.selectors.placeHolder,
  507.       start : function(e, ui){
  508.         $(ui.helper).addClass('dragging');
  509.       },
  510.       stop : function(e, ui){
  511.         $(ui.item).css({width : ''}).removeClass('dragging');
  512.         $(s.selectors.columns).sortable('enable');
  513.         /**
  514.          * Some variables for we convenience in this workspace
  515.          */
  516.         var widgetId = ui.item[0].id;
  517.         var holderId = ui.element[0].id;
  518.         var targetId = ui.item[0].parentNode.id;
  519.         var useCookies = widgetId && s.behaviour.useCookies && $.cookie;
  520.         /**
  521.          * If use cookies and the target ID it not the same than hoder ID
  522.          * we store in the positions cookie this Widget ID and the new
  523.          * Widget holder (target ID). Before of that we must to remove of
  524.          * the cookie the previous Widget ID and place holder if exists.
  525.          */
  526.         if(useCookies && holderId != targetId){
  527.           var cookieValue = $.cookie(s.cookies.positionName);
  528.           if(!cookieValue){
  529.             // Save this Widget ID and their current place holder
  530.             cookieValue = widgetId+'='+targetId;
  531.           }else{
  532.             // Remove from the cookie the possible last Widget position
  533.             cookieValue = cookieValue.replace(','+widgetId+'='+holderId, '');
  534.             cookieValue = cookieValue.replace(widgetId+'='+holderId+',', '');
  535.             cookieValue = cookieValue.replace(widgetId+'='+holderId, '');
  536.             // And store appropiattely the new Widget position
  537.             if($.trim(cookieValue) == ''){
  538.               cookieValue += widgetId+'='+targetId;
  539.             }else{
  540.               cookieValue += ','+widgetId+'='+targetId;
  541.             }
  542.           }
  543.           // Finally set the position cookie value
  544.           $.cookie(s.cookies.positionName, cookieValue, {
  545.             path: s.cookies.path,
  546.             secure: s.cookies.secure,
  547.             domain: s.cookies.domain,
  548.             expires: s.cookies.expires
  549.           });
  550.         }
  551.         if(s.callbacks.onDragStop != null){
  552.           s.callbacks.onDragStop(e, ui);
  553.         }
  554.         return true;
  555.       }
  556.     });
  557.     /**
  558.      * At this point the Widgets are be ready for use, but one more thing
  559.      * can be clean the plugin cookies if the appropiate option is used. This
  560.      * task is useful (in case of use cookies) because mantain the cookies
  561.      * values with the existing Widgets.
  562.      *
  563.      * In other words, if a Widget is not printed out in the HTML markup
  564.      * but their identifier is used in the Widgets cookies related, this
  565.      * not have sense, so, we looking for unused Widgets in the cookies
  566.      * and remove it, cleaning the Widgets cookies.
  567.      */ 
  568.     var cleanCookies = s.behaviour.useCookies && (widgetsIds.length > 0);
  569.     if(cleanCookies){
  570.       var i = 0;
  571.       var j = 0;
  572.       var cookies = new Array(
  573.         s.cookies.closeName,
  574.         s.cookies.positionName,
  575.         s.cookies.collapseName
  576.       );
  577.       var cookiesLen = cookies.length;
  578.       /**
  579.        * Iterate all the Widgets cookies
  580.        */
  581.       for(i = 0; i < cookiesLen; i++){
  582.         if($.cookie(cookies[i])){
  583.           var newValue = '';
  584.           var currents = $.cookie(cookies[i]).split(',');
  585.           var optionsLen = currents.length;
  586.           for(j = 0; j < optionsLen; j++){
  587.             var widgetId = '';
  588.             var widgetColumn = '';
  589.             if(cookies[i] == s.cookies.positionName){
  590.               /**
  591.                * For this type of cookie we have a value with the Widget ID
  592.                * and their column separated by a "=" character. Get it.
  593.                */
  594.               var cookieValue = currents[j].split('=');
  595.               if(cookieValue.length == 2){
  596.                 widgetId = cookieValue[0];
  597.                 widgetColumn = cookieValue[1];
  598.               }
  599.             }else{
  600.               // For other cookies we store only the Widget ID
  601.               widgetId = currents[j];
  602.             }
  603.             widgetId = $.trim(widgetId);
  604.             if($.inArray(widgetId, widgetsIds) != -1){
  605.               if(cookies[i] == s.cookies.positionName){
  606.                 if($.trim(newValue) == ''){
  607.                   newValue += widgetId+'='+widgetColumn;
  608.                 }else{
  609.                   newValue += ','+widgetId+'='+widgetColumn;
  610.                 }
  611.               }else{
  612.                 if($.trim(newValue) == ''){
  613.                   newValue += widgetId;
  614.                 }else{
  615.                   newValue += ','+widgetId;
  616.                 }
  617.               }
  618.             }
  619.             // Finally store this cookie new value
  620.             $.cookie(cookies[i], newValue,{
  621.               path: s.cookies.path,
  622.               secure: s.cookies.secure,
  623.               domain: s.cookies.domain,
  624.               expires: s.cookies.expires
  625.             });
  626.           }
  627.         }
  628.       }
  629.     }
  630.   };
  631.   // End of the main plugin function
  632.   /**
  633.    * Fill the plugin default settings
  634.    */
  635.   $.fn.EasyWidgets.defaults = {
  636.     // Behaviour of the plugin
  637.     behaviour : {
  638.       // Miliseconds delay between mousedown and drag start
  639.       dragDelay : 100,
  640.       // Miliseconds delay between mouseup and drag stop
  641.       dragRevert : 100,
  642.       // Determinme the opacity of Widget when start drag
  643.       dragOpacity : 0.8,
  644.       // Cookies (require Cookie plugin) to store positions and states
  645.       useCookies : false
  646.     },
  647.     // Only for the optional cookie feature
  648.     cookies : {
  649.       // Cookie path
  650.       path : '',
  651.       // Cookie domain
  652.       domain : '',
  653.       // Cookie expiration time in days
  654.       expires : 90,
  655.       // Store a secure cookie?
  656.       secure : false,
  657.       // Cookie name for close Widgets
  658.       closeName : 'easywidgets-close',
  659.       // Cookie name for positined Widgets
  660.       positionName : 'easywidgets-position',
  661.       // Cookie name for collapsed Widgets
  662.       collapseName : 'easywidgets-collapse'
  663.     },
  664.     // Options name to use in the HTML markup
  665.     options : {
  666.       // To recognize a movable Widget
  667.       movable : 'movable',
  668.       // To recognize a editable Widget
  669.       editable : 'editable',
  670.       // To recognize a collapse Widget
  671.       collapse : 'collapse',
  672.       // To recognize a removable Widget
  673.       removable : 'removable',
  674.       // To recognize a collapsable Widget
  675.       collapsable : 'collapsable',
  676.       // To recognize Widget that require confirmation when remove
  677.       closeConfirm : 'closeconfirm'
  678.     },
  679.     // Callbacks functions
  680.     callbacks : {
  681.       // When a editbox is closed, send the link and the widget objects
  682.       onEdit : null,
  683.       // When a Widget is closed, send the link and the widget objects
  684.       onClose : null,
  685.       // When a Widget is extend, send the link and the widget objects
  686.       onExtend : null,
  687.       // When a editbox is closed, send a ui object, see jQuery::sortable()
  688.       onDragStop : null,
  689.       // When a Widget is collapse, send the link and the widget objects
  690.       onCollapse : null,
  691.       // When a editbox is try to close, send the link and the widget objects
  692.       onEditQuery : null,
  693.       // When a Widget is try to close, send the link and the widget objects
  694.       onCloseQuery : null,
  695.       // When a editbox is cancel (close), send the link and the widget objects
  696.       onCancelEdit : null,
  697.       // When a Widget is try to expand, send the link and the widget objects
  698.       onExtendQuery : null,
  699.       // When a Widget is try to expand, send the link and the widget objects
  700.       onCollapseQuery : null,
  701.       // When a editbox is try to cancel, send the link and the widget objects
  702.       onCancelEditQuery : null
  703.     },
  704.     // Selectors in HTML markup. All can be change by you, but not all is
  705.     // used in the HTML markup. For example, the "editLink" or "closeLink"
  706.     // is prepared by the plugin for every Widget.
  707.     selectors : {
  708.       // Container of a Widget (into another element that use as column)
  709.       // The container can be "div" or "li", for example. In the first case
  710.       // use another "div" as column, and a "ul" in the case of "li".
  711.       container : 'div',
  712.       // Class identifier for a Widget
  713.       widget : '.widget',
  714.       // Class identifier for a Widget handle (header)
  715.       handle : '.widget-head',
  716.       // Class for the Widget header links container
  717.       menuLinks : '.widget-menu-links',
  718.       // Class identifier for a Widget column (parents of Widgets)
  719.       columns : '.widget-column',
  720.       // Class identifier for Widget editboxes
  721.       editbox : '.widget-editbox',
  722.       // Class identifier for Widget content
  723.       content : '.widget-content',
  724.       // Class identifier for editbox close link or button, for example
  725.       closeEdit : '.widget-close-editbox',
  726.       // Class identifier for a Widget edit link
  727.       editLink : '.widget-editlink',
  728.       // Class identifier for a Widget close link
  729.       closeLink : '.widget-closelink',
  730.       // Class identifier for Widgets placehoders
  731.       placeHolder : 'widget-placeholder',
  732.       // Class identifier for a Widget collapse link
  733.       collapseLink : '.widget-collapselink'
  734.     },
  735.     // To be translate the plugin into another languages
  736.     // But this variables can be used to show images instead
  737.     // links text, if you preffer. In this case set the HTML
  738.     // of the IMG elements.
  739.     i18n : {
  740.       // Widget edit link text
  741.       editText : 'Edit',
  742.       // Widget close link text
  743.       closeText : 'Close',
  744.       // Widget extend link text
  745.       extendText : 'Extend',
  746.       // Widget collapse link text
  747.       collapseText : 'Collapse',
  748.       // Widget cancel edit link text
  749.       cancelEditText : 'Cancel',
  750.       // Widget edition link title
  751.       editTitle : 'Edit this widget',
  752.       // Widget close link title
  753.       closeTitle : 'Close this widget',
  754.       // Widget confirmation dialog message
  755.       confirmMsg : 'Remove this widget?',
  756.       // Widget cancel edit link title
  757.       cancelEditTitle : 'Cancel edition',
  758.       // Widget extend link title
  759.       extendTitle : 'Extend this widget',
  760.       // Widget collapse link title
  761.       collapseTitle : 'Collapse this widget'
  762.     }
  763.   };
  764.   /**
  765.    * Private members of the plugin
  766.    */
  767.   /**
  768.    * Auxiliar function to prepare Widgets header links.
  769.    *
  770.    * @access private
  771.    * @param text Link text
  772.    * @param title Link title
  773.    * @param aClass CSS class (behaviour) of link
  774.    * @return String HTML of the link
  775.    */
  776.   function WidgetLink(text, title, aClass){
  777.     var link = '<a href="#" title="TITLE" class="CLASS">TEXT</a>';
  778.     link = link.replace(/TEXT/g, text);
  779.     link = link.replace(/TITLE/g, title);
  780.     link = link.replace(/CLASS/g, aClass.replace(/./, ''));
  781.     return link;
  782.   }
  783. })(jQuery);