]> source.dussan.org Git - nextcloud-server.git/commitdiff
Make event category choice multiselect
authorBart Visscher <bartv@thisnet.nl>
Thu, 22 Sep 2011 20:22:52 +0000 (22:22 +0200)
committerBart Visscher <bartv@thisnet.nl>
Fri, 23 Sep 2011 17:40:06 +0000 (19:40 +0200)
apps/calendar/ajax/editeventform.php
apps/calendar/ajax/neweventform.php
apps/calendar/css/style.css
apps/calendar/index.php
apps/calendar/js/calendar.js
apps/calendar/lib/object.php
apps/calendar/templates/part.eventform.php
core/css/jquery.multiselect.css [new file with mode: 0644]
core/js/jquery.multiselect.js [new file with mode: 0644]
lib/base.php

index 3b8a30f70fccfc16947b841a6d73898d44eb3aaf..f310db3e79a0c0a1ad59ab2e290e5957fa654fb8 100644 (file)
@@ -20,8 +20,8 @@ if(!OC_USER::isLoggedIn()) {
        die('<script type="text/javascript">document.location = oc_webroot;</script>');
 }
 
-$calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser());
-$categories = OC_Calendar_Object::getCategoryOptions($l10n);
+$calendar_options = OC_Calendar_Calendar::allCalendars(OC_User::getUser());
+$category_options = OC_Calendar_Object::getCategoryOptions($l10n);
 $repeat_options = OC_Calendar_Object::getRepeatOptions($l10n);
 
 $id = $_GET['id'];
@@ -55,19 +55,23 @@ switch($dtstart->getDateType()) {
 
 $summary = isset($vevent->SUMMARY) ? $vevent->SUMMARY->value : '';
 $location = isset($vevent->LOCATION) ? $vevent->LOCATION->value : '';
-$category = isset($vevent->CATEGORIES) ? $vevent->CATEGORIES->value : '';
+$categories = array();
+if (isset($vevent->CATEGORIES)){
+       $categories = explode(',', $vevent->CATEGORIES->value);
+       $categories = array_map('trim', $categories);
+}
 $repeat = isset($vevent->CATEGORY) ? $vevent->CATEGORY->value : '';
 $description = isset($vevent->DESCRIPTION) ? $vevent->DESCRIPTION->value : '';
 
 $tmpl = new OC_Template('calendar', 'part.editevent');
 $tmpl->assign('id', $id);
-$tmpl->assign('calendars', $calendars);
-$tmpl->assign('categories', $categories);
+$tmpl->assign('calendar_options', $calendar_options);
+$tmpl->assign('category_options', $category_options);
 $tmpl->assign('repeat_options', $repeat_options);
 
 $tmpl->assign('title', $summary);
 $tmpl->assign('location', $location);
-$tmpl->assign('category', $category);
+$tmpl->assign('categories', $categories);
 $tmpl->assign('calendar', $data['calendarid']);
 $tmpl->assign('allday', $allday);
 $tmpl->assign('startdate', $startdate);
index 1d8a61dffd274eff53f11f1aec7491603c943930..132294b496ea0958b0564fa4de7e8256db038192 100644 (file)
@@ -25,8 +25,8 @@ if(!OC_USER::isLoggedIn()) {
        die('<script type="text/javascript">document.location = oc_webroot;</script>');
 }
 
-$calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser());
-$categories = OC_Calendar_Object::getCategoryOptions($l10n);
+$calendar_options = OC_Calendar_Calendar::allCalendars(OC_User::getUser());
+$category_options = OC_Calendar_Object::getCategoryOptions($l10n);
 $repeat_options = OC_Calendar_Object::getRepeatOptions($l10n);
 $startday   = substr($_GET['d'], 0, 2);
 $startmonth = substr($_GET['d'], 2, 2);
@@ -56,8 +56,8 @@ if($endtime == 23) {
 }
 
 $tmpl = new OC_Template('calendar', 'part.newevent');
-$tmpl->assign('calendars', $calendars);
-$tmpl->assign('categories', $categories);
+$tmpl->assign('calendar_options', $calendar_options);
+$tmpl->assign('category_options', $category_options);
 $tmpl->assign('startdate', $startday . '-' . $startmonth . '-' . $startyear);
 $tmpl->assign('starttime', ($starttime <= 9 ? '0' : '') . $starttime . ':' . $startminutes);
 $tmpl->assign('enddate', $endday . '-' . $endmonth . '-' . $endyear);
index 5d08402422a316e4c8daa873bad64b2449dad182..b11980627635bc34b6341e80c45b5e2e28115918 100644 (file)
@@ -68,3 +68,5 @@ color:#333;
 #fromtime.disabled, #totime.disabled {
 color:#A9A9A9;
 }
+select#category{width:140px;}
+button.category{margin:0 3px;}
index c93ea93bb6cf513cf6be9e1511700caa439a8d45..b4e7d5ff48f5c21a210518fbfcc9ed729a3cd6e2 100644 (file)
@@ -17,7 +17,7 @@
  * 59 Temple Place, Suite 330, Boston,            *
  * MA 02111-1307  USA                             *
  *************************************************/
-require_once ("../../lib/base.php");
+require_once ('../../lib/base.php');
 OC_Util::checkLoggedIn();
 // Create default calendar ...
 $calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser());
@@ -25,8 +25,10 @@ if( count($calendars) == 0){
        OC_Calendar_Calendar::addCalendar(OC_User::getUser(),'default','Default calendar');
        $calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser());
 }
-OC_UTIL::addScript("calendar", "calendar");
-OC_UTIL::addStyle("calendar", "style");
-OC_APP::setActiveNavigationEntry("calendar_index");
-$output = new OC_TEMPLATE("calendar", "calendar", "user");
+OC_UTIL::addScript('calendar', 'calendar');
+OC_UTIL::addStyle('calendar', 'style');
+OC_UTIL::addScript('', 'jquery.multiselect');
+OC_UTIL::addStyle('', 'jquery.multiselect');
+OC_APP::setActiveNavigationEntry('calendar_index');
+$output = new OC_TEMPLATE('calendar', 'calendar', 'user');
 $output -> printPage();
index 5864977eb38c0145d832ae9126a53f5c6c7c5eba..8c1a4afac098a6732f22a039d25cf81f65c56905 100644 (file)
@@ -288,6 +288,13 @@ Calendar={
                        $( "#to" ).datepicker({
                                dateFormat : 'dd-mm-yy'
                        });
+                       $('#category').multiselect({
+                                       header: false,
+                                       noneSelectedText: $('#category').attr('title'),
+                                       selectedList: 2,
+                                       minWidth:'auto',
+                                       classes: 'category',
+                       });
                        $('#event').dialog({
                                width : 500,
                                close : function(event, ui) {
index 702033c169c8c991638fa0e71901ff7d0b4a08b2..3bb6543d3fda24b03114cb9d82d44c47f905b6ae 100644 (file)
@@ -301,7 +301,6 @@ class OC_Calendar_Object{
        public static function getCategoryOptions($l10n)
        {
                return array(
-                       $l10n->t('None'),
                        $l10n->t('Birthday'),
                        $l10n->t('Business'),
                        $l10n->t('Call'),
@@ -345,6 +344,11 @@ class OC_Calendar_Object{
                        $errarr['cal'] = 'true';
                        $errnum++;
                }
+
+               if(isset($request['categories']) && !is_array($request['categories'])){
+                       $errors['categories'] = $l10n->t('Not an array');
+               }
+
                $fromday = substr($request['from'], 0, 2);
                $frommonth = substr($request['from'], 3, 2);
                $fromyear = substr($request['from'], 6, 4);
@@ -434,7 +438,7 @@ class OC_Calendar_Object{
        {
                $title = $request["title"];
                $location = $request["location"];
-               $cat = $request["category"];
+               $categories = $request["categories"];
                $allday = isset($request["allday"]);
                $from = $request["from"];
                $fromtime = $request["fromtime"];
@@ -493,15 +497,21 @@ class OC_Calendar_Object{
 
                if($location != ""){
                        $vevent->LOCATION = $location;
+               }else{
+                       unset($vevent->LOCATION);
                }
 
                if($description != ""){
                        $des = str_replace("\n","\\n", $description);
                        $vevent->DESCRIPTION = $des;
+               }else{
+                       unset($vevent->DESCRIPTION);
                }
 
-               if($cat != ""){
-                       $vevent->CATEGORIES = $cat;
+               if(!empty($categories)){
+                       $vevent->CATEGORIES = join(',', $categories);
+               }else{
+                       unset($vevent->CATEGORIES);
                }
 
                /*if($repeat == "true"){
index c63d709e26e271b5c88039bf958d5e2a2b92f534..5b12407330ac46616c87a91a105198e7edd55040 100644 (file)
                <tr>
                        <th width="75px"><?php echo $l->t("Category");?>:</th>
                        <td>
-                       <select style="width:140px;" name="category">
+                       <select id="category" name="categories[]" multiple="multiple" title="<?php echo $l->t("Select category") ?>">
                                <?php
-                               foreach($_['categories'] as $category){
-                                       echo '<option value="' . $category . '"' . ($_['category'] == $category ? ' selected="selected"' : '') . '>' . $category . '</option>';
+                               foreach($_['category_options'] as $category){
+                                       echo '<option value="' . $category . '"' . (in_array($category, $_['categories']) ? ' selected="selected"' : '') . '>' . $category . '</option>';
                                }
                                ?>
                        </select></td>
@@ -27,7 +27,7 @@
                        <td>
                        <select style="width:140px;" name="calendar">
                                <?php
-                               foreach($_['calendars'] as $calendar){
+                               foreach($_['calendar_options'] as $calendar){
                                        echo '<option value="' . $calendar['id'] . '"' . ($_['calendar'] == $calendar['id'] ? ' selected="selected"' : '') . '>' . $calendar['displayname'] . '</option>';
                                }
                                ?>
diff --git a/core/css/jquery.multiselect.css b/core/css/jquery.multiselect.css
new file mode 100644 (file)
index 0000000..156799f
--- /dev/null
@@ -0,0 +1,23 @@
+.ui-multiselect { padding:2px 0 2px 4px; text-align:left }
+.ui-multiselect span.ui-icon { float:right }
+.ui-multiselect-single .ui-multiselect-checkboxes input { position:absolute !important; top: auto !important; left:-9999px; }
+.ui-multiselect-single .ui-multiselect-checkboxes label { padding:5px !important }
+
+.ui-multiselect-header { margin-bottom:3px; padding:3px 0 3px 4px }
+.ui-multiselect-header ul { font-size:0.9em }
+.ui-multiselect-header ul li { float:left; padding:0 10px 0 0 }
+.ui-multiselect-header a { text-decoration:none }
+.ui-multiselect-header a:hover { text-decoration:underline }
+.ui-multiselect-header span.ui-icon { float:left }
+.ui-multiselect-header li.ui-multiselect-close { float:right; text-align:right; padding-right:0 }
+
+.ui-multiselect-menu { display:none; padding:3px; position:absolute; z-index:10000 }
+.ui-multiselect-checkboxes { position:relative /* fixes bug in IE6/7 */; overflow-y:scroll }
+.ui-multiselect-checkboxes label { cursor:default; display:block; border:1px solid transparent; padding:3px 1px }
+.ui-multiselect-checkboxes label input { position:relative; top:1px }
+.ui-multiselect-checkboxes li { clear:both; font-size:0.9em; padding-right:3px }
+.ui-multiselect-checkboxes li.ui-multiselect-optgroup-label { text-align:center; font-weight:bold; border-bottom:1px solid }
+.ui-multiselect-checkboxes li.ui-multiselect-optgroup-label a { display:block; padding:3px; margin:1px 0; text-decoration:none }
+
+/* remove label borders in IE6 because IE6 does not support transparency */
+* html .ui-multiselect-checkboxes label { border:none }
diff --git a/core/js/jquery.multiselect.js b/core/js/jquery.multiselect.js
new file mode 100644 (file)
index 0000000..46aab7e
--- /dev/null
@@ -0,0 +1,658 @@
+/*
+ * jQuery MultiSelect UI Widget 1.11
+ * Copyright (c) 2011 Eric Hynds
+ *
+ * http://www.erichynds.com/jquery/jquery-ui-multiselect-widget/
+ *
+ * Depends:
+ *   - jQuery 1.4.2+
+ *   - jQuery UI 1.8 widget factory
+ *
+ * Optional:
+ *   - jQuery UI effects
+ *   - jQuery UI position utility
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+*/
+(function($, undefined){
+
+var multiselectID = 0;
+
+$.widget("ech.multiselect", {
+
+       // default options
+       options: {
+               header: true,
+               height: 175,
+               minWidth: 225,
+               classes: '',
+               checkAllText: 'Check all',
+               uncheckAllText: 'Uncheck all',
+               noneSelectedText: 'Select options',
+               selectedText: '# selected',
+               selectedList: 0,
+               show: '',
+               hide: '',
+               autoOpen: false,
+               multiple: true,
+               position: {}
+       },
+
+       _create: function(){
+               var el = this.element.hide(),
+                       o = this.options;
+
+               this.speed = $.fx.speeds._default; // default speed for effects
+               this._isOpen = false; // assume no
+
+               var
+                       button = (this.button = $('<button type="button"><span class="ui-icon ui-icon-triangle-2-n-s"></span></button>'))
+                               .addClass('ui-multiselect ui-widget ui-state-default ui-corner-all')
+                               .addClass( o.classes )
+                               .attr({ 'title':el.attr('title'), 'aria-haspopup':true, 'tabIndex':el.attr('tabIndex') })
+                               .insertAfter( el ),
+
+                       buttonlabel = (this.buttonlabel = $('<span />'))
+                               .html( o.noneSelectedText )
+                               .appendTo( button ),
+
+                       menu = (this.menu = $('<div />'))
+                               .addClass('ui-multiselect-menu ui-widget ui-widget-content ui-corner-all')
+                               .addClass( o.classes )
+                               .insertAfter( button ),
+
+                       header = (this.header = $('<div />'))
+                               .addClass('ui-widget-header ui-corner-all ui-multiselect-header ui-helper-clearfix')
+                               .appendTo( menu ),
+
+                       headerLinkContainer = (this.headerLinkContainer = $('<ul />'))
+                               .addClass('ui-helper-reset')
+                               .html(function(){
+                                       if( o.header === true ){
+                                               return '<li><a class="ui-multiselect-all" href="#"><span class="ui-icon ui-icon-check"></span><span>' + o.checkAllText + '</span></a></li><li><a class="ui-multiselect-none" href="#"><span class="ui-icon ui-icon-closethick"></span><span>' + o.uncheckAllText + '</span></a></li>';
+                                       } else if(typeof o.header === "string"){
+                                               return '<li>' + o.header + '</li>';
+                                       } else {
+                                               return '';
+                                       }
+                               })
+                               .append('<li class="ui-multiselect-close"><a href="#" class="ui-multiselect-close"><span class="ui-icon ui-icon-circle-close"></span></a></li>')
+                               .appendTo( header ),
+
+                       checkboxContainer = (this.checkboxContainer = $('<ul />'))
+                               .addClass('ui-multiselect-checkboxes ui-helper-reset')
+                               .appendTo( menu );
+
+               // perform event bindings
+               this._bindEvents();
+
+               // build menu
+               this.refresh( true );
+
+               // some addl. logic for single selects
+               if( !o.multiple ){
+                       menu.addClass('ui-multiselect-single');
+               }
+       },
+
+       _init: function(){
+               if( this.options.header === false ){
+                       this.header.hide();
+               }
+               if( !this.options.multiple ){
+                       this.headerLinkContainer.find('.ui-multiselect-all, .ui-multiselect-none').hide();
+               }
+               if( this.options.autoOpen ){
+                       this.open();
+               }
+               if( this.element.is(':disabled') ){
+                       this.disable();
+               }
+       },
+
+       refresh: function( init ){
+               var el = this.element,
+                       o = this.options,
+                       menu = this.menu,
+                       checkboxContainer = this.checkboxContainer,
+                       optgroups = [],
+                       html = [],
+                       id = el.attr('id') || multiselectID++; // unique ID for the label & option tags
+
+               // build items
+               this.element.find('option').each(function( i ){
+                       var $this = $(this),
+                               parent = this.parentNode,
+                               title = this.innerHTML,
+                               description = this.title,
+                               value = this.value,
+                               inputID = this.id || 'ui-multiselect-'+id+'-option-'+i,
+                               isDisabled = this.disabled,
+                               isSelected = this.selected,
+                               labelClasses = ['ui-corner-all'],
+                               optLabel;
+
+                       // is this an optgroup?
+                       if( parent.tagName.toLowerCase() === 'optgroup' ){
+                               optLabel = parent.getAttribute('label');
+
+                               // has this optgroup been added already?
+                               if( $.inArray(optLabel, optgroups) === -1 ){
+                                       html.push('<li class="ui-multiselect-optgroup-label"><a href="#">' + optLabel + '</a></li>');
+                                       optgroups.push( optLabel );
+                               }
+                       }
+
+                       if( isDisabled ){
+                               labelClasses.push('ui-state-disabled');
+                       }
+
+                       // browsers automatically select the first option
+                       // by default with single selects
+                       if( isSelected && !o.multiple ){
+                               labelClasses.push('ui-state-active');
+                       }
+
+                       html.push('<li class="' + (isDisabled ? 'ui-multiselect-disabled' : '') + '">');
+
+                       // create the label
+                       html.push('<label for="'+inputID+'" title="'+description+'" class="'+labelClasses.join(' ')+ '">');
+                       html.push('<input id="'+inputID+'" name="multiselect_'+id+'" type="'+(o.multiple ? "checkbox" : "radio")+'" value="'+value+'" title="'+title+'"');
+
+                       // pre-selected?
+                       if( isSelected ){
+                               html.push(' checked="checked"');
+                               html.push(' aria-selected="true"');
+                       }
+
+                       // disabled?
+                       if( isDisabled ){
+                               html.push(' disabled="disabled"');
+                               html.push(' aria-disabled="true"');
+                       }
+
+                       // add the title and close everything off
+                       html.push(' /><span>' + title + '</span></label></li>');
+               });
+
+               // insert into the DOM
+               checkboxContainer.html( html.join('') );
+
+               // cache some moar useful elements
+               this.labels = menu.find('label');
+
+               // set widths
+               this._setButtonWidth();
+               this._setMenuWidth();
+
+               // remember default value
+               this.button[0].defaultValue = this.update();
+
+               // broadcast refresh event; useful for widgets
+               if( !init ){
+                       this._trigger('refresh');
+               }
+       },
+
+       // updates the button text.  call refresh() to rebuild
+       update: function(){
+               var o = this.options,
+                       $inputs = this.labels.find('input'),
+                       $checked = $inputs.filter(':checked'),
+                       numChecked = $checked.length,
+                       value;
+
+               if( numChecked === 0 ){
+                       value = o.noneSelectedText;
+               } else {
+                       if($.isFunction( o.selectedText )){
+                               value = o.selectedText.call(this, numChecked, $inputs.length, $checked.get());
+                       } else if( /\d/.test(o.selectedList) && o.selectedList > 0 && numChecked <= o.selectedList){
+                               value = $checked.map(function(){ return this.title; }).get().join(', ');
+                       } else {
+                               value = o.selectedText.replace('#', numChecked).replace('#', $inputs.length);
+                       }
+               }
+
+               this.buttonlabel.html( value );
+               return value;
+       },
+
+       // binds events
+       _bindEvents: function(){
+               var self = this, button = this.button;
+
+               function clickHandler(){
+                       self[ self._isOpen ? 'close' : 'open' ]();
+                       return false;
+               }
+
+               // webkit doesn't like it when you click on the span :(
+               button
+                       .find('span')
+                       .bind('click.multiselect', clickHandler);
+
+               // button events
+               button.bind({
+                       click: clickHandler,
+                       keypress: function( e ){
+                               switch(e.which){
+                                       case 27: // esc
+                                       case 38: // up
+                                       case 37: // left
+                                               self.close();
+                                               break;
+                                       case 39: // right
+                                       case 40: // down
+                                               self.open();
+                                               break;
+                               }
+                       },
+                       mouseenter: function(){
+                               if( !button.hasClass('ui-state-disabled') ){
+                                       $(this).addClass('ui-state-hover');
+                               }
+                       },
+                       mouseleave: function(){
+                               $(this).removeClass('ui-state-hover');
+                       },
+                       focus: function(){
+                               if( !button.hasClass('ui-state-disabled') ){
+                                       $(this).addClass('ui-state-focus');
+                               }
+                       },
+                       blur: function(){
+                               $(this).removeClass('ui-state-focus');
+                       }
+               });
+
+               // header links
+               this.header
+                       .delegate('a', 'click.multiselect', function( e ){
+                               // close link
+                               if( $(this).hasClass('ui-multiselect-close') ){
+                                       self.close();
+
+                               // check all / uncheck all
+                               } else {
+                                       self[ $(this).hasClass('ui-multiselect-all') ? 'checkAll' : 'uncheckAll' ]();
+                               }
+
+                               e.preventDefault();
+                       });
+
+               // optgroup label toggle support
+               this.menu
+                       .delegate('li.ui-multiselect-optgroup-label a', 'click.multiselect', function( e ){
+                               e.preventDefault();
+
+                               var $this = $(this),
+                                       $inputs = $this.parent().nextUntil('li.ui-multiselect-optgroup-label').find('input:visible:not(:disabled)'),
+                                   nodes = $inputs.get(),
+                                   label = $this.parent().text();
+
+                               // trigger event and bail if the return is false
+                               if( self._trigger('beforeoptgrouptoggle', e, { inputs:nodes, label:label }) === false ){
+                                       return;
+                               }
+
+                               // toggle inputs
+                               self._toggleChecked(
+                                       $inputs.filter(':checked').length !== $inputs.length,
+                                       $inputs
+                               );
+
+                               self._trigger('optgrouptoggle', e, {
+                                   inputs: nodes,
+                                   label: label,
+                                   checked: nodes[0].checked
+                               });
+                       })
+                       .delegate('label', 'mouseenter.multiselect', function(){
+                               if( !$(this).hasClass('ui-state-disabled') ){
+                                       self.labels.removeClass('ui-state-hover');
+                                       $(this).addClass('ui-state-hover').find('input').focus();
+                               }
+                       })
+                       .delegate('label', 'keydown.multiselect', function( e ){
+                               e.preventDefault();
+
+                               switch(e.which){
+                                       case 9: // tab
+                                       case 27: // esc
+                                               self.close();
+                                               break;
+                                       case 38: // up
+                                       case 40: // down
+                                       case 37: // left
+                                       case 39: // right
+                                               self._traverse(e.which, this);
+                                               break;
+                                       case 13: // enter
+                                               $(this).find('input')[0].click();
+                                               break;
+                               }
+                       })
+                       .delegate('input[type="checkbox"], input[type="radio"]', 'click.multiselect', function( e ){
+                               var $this = $(this),
+                                       val = this.value,
+                                       checked = this.checked,
+                                       tags = self.element.find('option');
+
+                               // bail if this input is disabled or the event is cancelled
+                               if( this.disabled || self._trigger('click', e, { value:val, text:this.title, checked:checked }) === false ){
+                                       e.preventDefault();
+                                       return;
+                               }
+
+                               // toggle aria state
+                               $this.attr('aria-selected', checked);
+
+                               // change state on the original option tags
+                               tags.each(function(){
+                                       if( this.value === val ){
+                                               this.selected = checked;
+                                       } else if( !self.options.multiple ){
+                                               this.selected = false;
+                                       }
+                               });
+
+                               // some additional single select-specific logic
+                               if( !self.options.multiple ){
+                                       self.labels.removeClass('ui-state-active');
+                                       $this.closest('label').toggleClass('ui-state-active', checked );
+
+                                       // close menu
+                                       self.close();
+                               }
+
+                               // fire change on the select box
+                               self.element.trigger("change");
+
+                               // setTimeout is to fix multiselect issue #14 and #47. caused by jQuery issue #3827
+                               // http://bugs.jquery.com/ticket/3827
+                               setTimeout($.proxy(self.update, self), 10);
+                       });
+
+               // close each widget when clicking on any other element/anywhere else on the page
+               $(document).bind('mousedown.multiselect', function( e ){
+                       if(self._isOpen && !$.contains(self.menu[0], e.target) && !$.contains(self.button[0], e.target) && e.target !== self.button[0]){
+                               self.close();
+                       }
+               });
+
+               // deal with form resets.  the problem here is that buttons aren't
+               // restored to their defaultValue prop on form reset, and the reset
+               // handler fires before the form is actually reset.  delaying it a bit
+               // gives the form inputs time to clear.
+               $(this.element[0].form).bind('reset.multiselect', function(){
+                       setTimeout(function(){ self.update(); }, 10);
+               });
+       },
+
+       // set button width
+       _setButtonWidth: function(){
+               var width = this.element.outerWidth(),
+                       o = this.options;
+
+               if( /\d/.test(o.minWidth) && width < o.minWidth){
+                       width = o.minWidth;
+               }
+
+               // set widths
+               this.button.width( width );
+       },
+
+       // set menu width
+       _setMenuWidth: function(){
+               var m = this.menu,
+                       width = this.button.outerWidth()-
+                               parseInt(m.css('padding-left'),10)-
+                               parseInt(m.css('padding-right'),10)-
+                               parseInt(m.css('border-right-width'),10)-
+                               parseInt(m.css('border-left-width'),10);
+
+               m.width( width || this.button.outerWidth() );
+       },
+
+       // move up or down within the menu
+       _traverse: function( which, start ){
+               var $start = $(start),
+                       moveToLast = which === 38 || which === 37,
+
+                       // select the first li that isn't an optgroup label / disabled
+                       $next = $start.parent()[moveToLast ? 'prevAll' : 'nextAll']('li:not(.ui-multiselect-disabled, .ui-multiselect-optgroup-label)')[ moveToLast ? 'last' : 'first']();
+
+               // if at the first/last element
+               if( !$next.length ){
+                       var $container = this.menu.find('ul:last');
+
+                       // move to the first/last
+                       this.menu.find('label')[ moveToLast ? 'last' : 'first' ]().trigger('mouseover');
+
+                       // set scroll position
+                       $container.scrollTop( moveToLast ? $container.height() : 0 );
+
+               } else {
+                       $next.find('label').trigger('mouseover');
+               }
+       },
+
+       // This is an internal function to toggle the checked property and
+       // other related attributes of a checkbox.
+       //
+       // The context of this function should be a checkbox; do not proxy it.
+       _toggleCheckbox: function( prop, flag ){
+               return function(){
+                       !this.disabled && (this[ prop ] = flag);
+
+                       if( flag ){
+                               this.setAttribute('aria-selected', true);
+                       } else {
+                               this.removeAttribute('aria-selected');
+                       }
+               }
+       },
+
+       _toggleChecked: function( flag, group ){
+               var $inputs = (group && group.length) ?
+                       group :
+                       this.labels.find('input'),
+
+                       self = this;
+
+               // toggle state on inputs
+               $inputs.each(this._toggleCheckbox('checked', flag));
+
+               // update button text
+               this.update();
+
+               // gather an array of the values that actually changed
+               var values = $inputs.map(function(){
+                       return this.value;
+               }).get();
+
+               // toggle state on original option tags
+               this.element
+                       .find('option')
+                       .each(function(){
+                               if( !this.disabled && $.inArray(this.value, values) > -1 ){
+                                       self._toggleCheckbox('selected', flag).call( this );
+                               }
+                       });
+
+               // trigger the change event on the select
+               if( $inputs.length ) {
+                       this.element.trigger("change");
+               }
+       },
+
+       _toggleDisabled: function( flag ){
+               this.button
+                       .attr({ 'disabled':flag, 'aria-disabled':flag })[ flag ? 'addClass' : 'removeClass' ]('ui-state-disabled');
+
+               this.menu
+                       .find('input')
+                       .attr({ 'disabled':flag, 'aria-disabled':flag })
+                       .parent()[ flag ? 'addClass' : 'removeClass' ]('ui-state-disabled');
+
+               this.element
+                       .attr({ 'disabled':flag, 'aria-disabled':flag });
+       },
+
+       // open the menu
+       open: function( e ){
+               var self = this,
+                       button = this.button,
+                       menu = this.menu,
+                       speed = this.speed,
+                       o = this.options;
+
+               // bail if the multiselectopen event returns false, this widget is disabled, or is already open
+               if( this._trigger('beforeopen') === false || button.hasClass('ui-state-disabled') || this._isOpen ){
+                       return;
+               }
+
+               var $container = menu.find('ul:last'),
+                       effect = o.show,
+                       pos = button.position();
+
+               // figure out opening effects/speeds
+               if( $.isArray(o.show) ){
+                       effect = o.show[0];
+                       speed = o.show[1] || self.speed;
+               }
+
+               // set the scroll of the checkbox container
+               $container.scrollTop(0).height(o.height);
+
+               // position and show menu
+               if( $.ui.position && !$.isEmptyObject(o.position) ){
+                       o.position.of = o.position.of || button;
+
+                       menu
+                               .show()
+                               .position( o.position )
+                               .hide()
+                               .show( effect, speed );
+
+               // if position utility is not available...
+               } else {
+                       menu.css({
+                               top: pos.top+button.outerHeight(),
+                               left: pos.left
+                       }).show( effect, speed );
+               }
+
+               // select the first option
+               // triggering both mouseover and mouseover because 1.4.2+ has a bug where triggering mouseover
+               // will actually trigger mouseenter.  the mouseenter trigger is there for when it's eventually fixed
+               this.labels.eq(0).trigger('mouseover').trigger('mouseenter').find('input').trigger('focus');
+
+               button.addClass('ui-state-active');
+               this._isOpen = true;
+               this._trigger('open');
+       },
+
+       // close the menu
+       close: function(){
+               if(this._trigger('beforeclose') === false){
+                       return;
+               }
+
+               var o = this.options, effect = o.hide, speed = this.speed;
+
+               // figure out opening effects/speeds
+               if( $.isArray(o.hide) ){
+                       effect = o.hide[0];
+                       speed = o.hide[1] || this.speed;
+               }
+
+               this.menu.hide(effect, speed);
+               this.button.removeClass('ui-state-active').trigger('blur').trigger('mouseleave');
+               this._isOpen = false;
+               this._trigger('close');
+       },
+
+       enable: function(){
+               this._toggleDisabled(false);
+       },
+
+       disable: function(){
+               this._toggleDisabled(true);
+       },
+
+       checkAll: function( e ){
+               this._toggleChecked(true);
+               this._trigger('checkAll');
+       },
+
+       uncheckAll: function(){
+               this._toggleChecked(false);
+               this._trigger('uncheckAll');
+       },
+
+       getChecked: function(){
+               return this.menu.find('input').filter(':checked');
+       },
+
+       destroy: function(){
+               // remove classes + data
+               $.Widget.prototype.destroy.call( this );
+
+               this.button.remove();
+               this.menu.remove();
+               this.element.show();
+
+               return this;
+       },
+
+       isOpen: function(){
+               return this._isOpen;
+       },
+
+       widget: function(){
+               return this.menu;
+       },
+
+       // react to option changes after initialization
+       _setOption: function( key, value ){
+               var menu = this.menu;
+
+               switch(key){
+                       case 'header':
+                               menu.find('div.ui-multiselect-header')[ value ? 'show' : 'hide' ]();
+                               break;
+                       case 'checkAllText':
+                               menu.find('a.ui-multiselect-all span').eq(-1).text(value);
+                               break;
+                       case 'uncheckAllText':
+                               menu.find('a.ui-multiselect-none span').eq(-1).text(value);
+                               break;
+                       case 'height':
+                               menu.find('ul:last').height( parseInt(value,10) );
+                               break;
+                       case 'minWidth':
+                               this.options[ key ] = parseInt(value,10);
+                               this._setButtonWidth();
+                               this._setMenuWidth();
+                               break;
+                       case 'selectedText':
+                       case 'selectedList':
+                       case 'noneSelectedText':
+                               this.options[key] = value; // these all needs to update immediately for the update() call
+                               this.update();
+                               break;
+                       case 'classes':
+                               menu.add(this.button).removeClass(this.options.classes).addClass(value);
+                               break;
+               }
+
+               $.Widget.prototype._setOption.apply( this, arguments );
+       }
+});
+
+})(jQuery);
index 9542170df54f570c0f9aebd2b299c0f6199535c3..9b7778007641012a58db22e27f8be11ced410fea 100644 (file)
@@ -115,7 +115,7 @@ class OC{
                OC_Util::addScript( "jquery-showpassword" );
                OC_Util::addScript( "jquery-tipsy" );
                OC_Util::addScript( "js" );
-               OC_Util::addScript( "multiselect" );
+               //OC_Util::addScript( "multiselect" );
                OC_Util::addScript('search','result');
                OC_Util::addStyle( "styles" );
                OC_Util::addStyle( "multiselect" );