Projects
Kolab:3.4
roundcubemail
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 75
View file
jquery.tagedit.patch
Deleted
@@ -1,863 +0,0 @@ -From 788d37db0d6dbcb44f5de7b679418dfed8daf9d1 Mon Sep 17 00:00:00 2001 -From: Aleksander Machniak <alec@alec.pl> -Date: Thu, 8 Jan 2015 10:09:25 -0500 -Subject: [PATCH] Integrate jquery.tagedit with jqueryui plugin - ---- - plugins/jqueryui/jqueryui.php | 21 + - plugins/jqueryui/js/jquery.tagedit.js | 683 ++++++++++++++++++++++++++++++ - plugins/jqueryui/themes/larry/tagedit.css | 122 ++++++ - 3 files changed, 826 insertions(+) - create mode 100644 plugins/jqueryui/js/jquery.tagedit.js - create mode 100644 plugins/jqueryui/themes/larry/tagedit.css - -diff --git a/plugins/jqueryui/jqueryui.php b/plugins/jqueryui/jqueryui.php -index 2dfa8ad..1511ac5 100644 ---- a/plugins/jqueryui/jqueryui.php -+++ b/plugins/jqueryui/jqueryui.php -@@ -108,6 +108,27 @@ public static function miniColors() - $rcube->output->set_env('mscolors', self::get_color_values()); - } - -+ public static function tagedit() -+ { -+ if (in_array('tagedit', self::$features)) { -+ return; -+ } -+ -+ self::$features[] = 'tagedit'; -+ -+ $script = 'plugins/jqueryui/js/jquery.tagedit.js'; -+ $rcube = rcube::get_instance(); -+ $ui_theme = self::$ui_theme; -+ $css = "plugins/jqueryui/themes/$ui_theme/tagedit.css"; -+ -+ if (!file_exists(INSTALL_PATH . $css)) { -+ $css = "plugins/jqueryui/themes/larry/tagedit.css"; -+ } -+ -+ $rcube->output->include_css($css); -+ $rcube->output->add_header(html::tag('script', array('type' => "text/javascript", 'src' => $script))); -+ } -+ - /** - * Return a (limited) list of color values to be used for calendar and category coloring - * -diff --git a/plugins/jqueryui/js/jquery.tagedit.js b/plugins/jqueryui/js/jquery.tagedit.js -new file mode 100644 -index 0000000..baab701 ---- /dev/null -+++ b/plugins/jqueryui/js/jquery.tagedit.js -@@ -0,0 +1,683 @@ -+/* -+* Tagedit - jQuery Plugin -+* The Plugin can be used to edit tags from a database the easy way -+* -+* Examples and documentation at: tagedit.webwork-albrecht.de -+* -+* License: -+* This work is licensed under a MIT License -+* -+* @licstart The following is the entire license notice for the -+* JavaScript code in this file. -+* -+* Copyright (c) 2010 Oliver Albrecht <info@webwork-albrecht.de> -+* Copyright (c) 2014 Thomas BrĂ¼derli <thomas@roundcube.net> -+* -+* Licensed under the MIT licenses -+* -+* Permission is hereby granted, free of charge, to any person obtaining -+* a copy of this software and associated documentation files (the -+* "Software"), to deal in the Software without restriction, including -+* without limitation the rights to use, copy, modify, merge, publish, -+* distribute, sublicense, and/or sell copies of the Software, and to -+* permit persons to whom the Software is furnished to do so, subject to -+* the following conditions: -+* -+* The above copyright notice and this permission notice shall be -+* included in all copies or substantial portions of the Software. -+* -+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -+* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -+* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -+* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+* -+* @licend The above is the entire license notice -+* for the JavaScript code in this file. -+* -+* @author Oliver Albrecht Mial: info@webwork-albrecht.de Twitter: @webworka -+* @version 1.5.2 (06/2014) -+* Requires: jQuery v1.4+, jQueryUI v1.8+, jQuerry.autoGrowInput -+* -+* Example of usage: -+* -+* $( "input.tag" ).tagedit(); -+* -+* Possible options: -+* -+* autocompleteURL: '', // url for a autocompletion -+* deleteEmptyItems: true, // Deletes items with empty value -+* deletedPostfix: '-d', // will be put to the Items that are marked as delete -+* addedPostfix: '-a', // will be put to the Items that are choosem from the database -+* additionalListClass: '', // put a classname here if the wrapper ul shoud receive a special class -+* allowEdit: true, // Switch on/off edit entries -+* allowDelete: true, // Switch on/off deletion of entries. Will be ignored if allowEdit = false -+* allowAdd: true, // switch on/off the creation of new entries -+* direction: 'ltr' // Sets the writing direction for Outputs and Inputs -+* animSpeed: 500 // Sets the animation speed for effects -+* autocompleteOptions: {}, // Setting Options for the jquery UI Autocomplete (http://jqueryui.com/demos/autocomplete/) -+* breakKeyCodes: [ 13, 44 ], // Sets the characters to break on to parse the tags (defaults: return, comma) -+* checkNewEntriesCaseSensitive: false, // If there is a new Entry, it is checked against the autocompletion list. This Flag controlls if the check is (in-)casesensitive -+* texts: { // some texts -+* removeLinkTitle: 'Remove from list.', -+* saveEditLinkTitle: 'Save changes.', -+* deleteLinkTitle: 'Delete this tag from database.', -+* deleteConfirmation: 'Are you sure to delete this entry?', -+* deletedElementTitle: 'This Element will be deleted.', -+* breakEditLinkTitle: 'Cancel' -+* } -+*/ -+ -+(function($) { -+ -+ $.fn.tagedit = function(options) { -+ /** -+ * Merge Options with defaults -+ */ -+ options = $.extend(true, { -+ // default options here -+ autocompleteURL: null, -+ checkToDeleteURL: null, -+ deletedPostfix: '-d', -+ addedPostfix: '-a', -+ additionalListClass: '', -+ allowEdit: true, -+ allowDelete: true, -+ allowAdd: true, -+ direction: 'ltr', -+ animSpeed: 500, -+ autocompleteOptions: { -+ select: function( event, ui ) { -+ $(this).val(ui.item.value).trigger('transformToTag', [ui.item.id]); -+ return false; -+ } -+ }, -+ breakKeyCodes: [ 13, 44 ], -+ checkNewEntriesCaseSensitive: false, -+ texts: { -+ removeLinkTitle: 'Remove from list.', -+ saveEditLinkTitle: 'Save changes.', -+ deleteLinkTitle: 'Delete this tag from database.', -+ deleteConfirmation: 'Are you sure to delete this entry?', -+ deletedElementTitle: 'This Element will be deleted.', -+ breakEditLinkTitle: 'Cancel', -+ forceDeleteConfirmation: 'There are more records using this tag, are you sure do you want to remove it?' -+ }, -+ tabindex: false -+ }, options || {}); -+ -+ // no action if there are no elements -+ if(this.length == 0) { -+ return; -+ } -+ -+ // set the autocompleteOptions source -+ if(options.autocompleteURL) { -+ options.autocompleteOptions.source = options.autocompleteURL; -+ } -+ -+ // Set the direction of the inputs -+ var direction= this.attr('dir'); -+ if(direction && direction.length > 0) { -+ options.direction = this.attr('dir'); -+ } -+ -+ var elements = this; -+ var focusItem = null; -+ -+ var baseNameRegexp = new RegExp("^(.*)\\[([0-9]*?("+options.deletedPostfix+"|"+options.addedPostfix+")?)?\]$", "i"); -+ -+ var baseName = elements.eq(0).attr('name').match(baseNameRegexp); -+ if(baseName && baseName.length == 4) { -+ baseName = baseName[1]; -+ } -+ else { -+ // Elementname does not match the expected format, exit -+ alert('elementname dows not match the expected format (regexp: '+baseNameRegexp+')') -+ return; -+ } -+ -+ // read tabindex from source element -+ var ti; -+ if (!options.tabindex && (ti = elements.eq(0).attr('tabindex'))) -+ options.tabindex = ti; -+ -+ // init elements -+ inputsToList(); -+ -+ /** -+ * Creates the tageditinput from a list of textinputs -+ * -+ */ -+ function inputsToList() { -+ var html = '<ul class="tagedit-list '+options.additionalListClass+'">'; -+ -+ elements.each(function(i) { -+ var element_name = $(this).attr('name').match(baseNameRegexp); -+ if(element_name && element_name.length == 4 && (options.deleteEmptyItems == false || $(this).val().length > 0)) { -+ if(element_name[1].length > 0) { -+ var elementId = typeof element_name[2] != 'undefined'? element_name[2]: '', -+ domId = 'tagedit-' + baseName + '-' + (elementId || i); -+ -+ html += '<li class="tagedit-listelement tagedit-listelement-old" aria-labelledby="'+domId+'">'; -+ html += '<span dir="'+options.direction+'" id="'+domId+'">' + $(this).val() + '</span>'; -+ html += '<input type="hidden" name="'+baseName+'['+elementId+']" value="'+$(this).val()+'" />'; -+ if (options.allowDelete) -+ html += '<a class="tagedit-close" title="'+options.texts.removeLinkTitle+'" aria-label="'+options.texts.removeLinkTitle+' '+$(this).val()+'">x</a>'; -+ html += '</li>'; -+ } -+ } -+ }); -+ -+ // replace Elements with the list and save the list in the local variable elements -+ elements.last().after(html) -+ var newList = elements.last().next(); -+ elements.remove(); -+ elements = newList; -+ -+ // Check if some of the elementshav to be marked as deleted -+ if(options.deletedPostfix.length > 0) { -+ elements.find('input[name$="'+options.deletedPostfix+'\]"]').each(function() { -+ markAsDeleted($(this).parent()); -+ }); -+ } -+ -+ // put an input field at the End -+ // Put an empty element at the end -+ html = '<li class="tagedit-listelement tagedit-listelement-new">'; -+ if (options.allowAdd) -+ html += '<input type="text" name="'+baseName+'[]" value="" id="tagedit-input" disabled="disabled" class="tagedit-input-disabled" dir="'+options.direction+'"/>'; -+ html += '</li>'; -+ html += '</ul>'; -+ -+ elements -+ .append(html) -+ .attr('tabindex', options.tabindex) // set tabindex to <ul> to recieve focus -+ -+ // Set function on the input -+ .find('#tagedit-input') -+ .attr('tabindex', options.tabindex) -+ .each(function() { -+ $(this).autoGrowInput({comfortZone: 15, minWidth: 15, maxWidth: 20000}); -+ -+ // Event is triggert in case of choosing an item from the autocomplete, or finish the input -+ $(this).bind('transformToTag', function(event, id) { -+ var oldValue = (typeof id != 'undefined' && (id.length > 0 || id > 0)); -+ -+ var checkAutocomplete = oldValue == true || options.autocompleteOptions.noCheck ? false : true; -+ // check if the Value ist new -+ var isNewResult = isNew($(this).val(), checkAutocomplete); -+ if(isNewResult[0] === true || (isNewResult[0] === false && typeof isNewResult[1] == 'string')) { -+ -+ if(oldValue == false && typeof isNewResult[1] == 'string') { -+ oldValue = true; -+ id = isNewResult[1]; -+ } -+ -+ if(options.allowAdd == true || oldValue) { -+ var domId = 'tagedit-' + baseName + '-' + id; -+ // Make a new tag in front the input -+ html = '<li class="tagedit-listelement tagedit-listelement-old" aria-labelledby="'+domId+'">'; -+ html += '<span dir="'+options.direction+'" id="'+domId+'">' + $(this).val() + '</span>'; -+ var name = oldValue? baseName + '['+id+options.addedPostfix+']' : baseName + '[]'; -+ html += '<input type="hidden" name="'+name+'" value="'+$(this).val()+'" />'; -+ html += '<a class="tagedit-close" title="'+options.texts.removeLinkTitle+'" aria-label="'+options.texts.removeLinkTitle+' '+$(this).val()+'">x</a>'; -+ html += '</li>'; -+ -+ $(this).parent().before(html); -+ } -+ } -+ $(this).val(''); -+ -+ // close autocomplete -+ if(options.autocompleteOptions.source) { -+ if($(this).is(':ui-autocomplete')) -+ $(this).autocomplete( "close" ); -+ } -+ -+ }) -+ .keydown(function(event) { -+ var code = event.keyCode > 0? event.keyCode : event.which; -+ -+ switch(code) { -+ case 46: -+ if (!focusItem) -+ break; -+ case 8: // BACKSPACE -+ if(focusItem) { -+ focusItem.fadeOut(options.animSpeed, function() { -+ $(this).remove(); -+ }) -+ unfocusItem(); -+ event.preventDefault(); -+ return false; -+ } -+ else if($(this).val().length == 0) { -+ // delete Last Tag -+ var elementToRemove = elements.find('li.tagedit-listelement-old').last(); -+ elementToRemove.fadeOut(options.animSpeed, function() {elementToRemove.remove();}) -+ event.preventDefault(); -+ return false; -+ } -+ break; -+ case 9: // TAB -+ if($(this).val().length > 0 && $('ul.ui-autocomplete #ui-active-menuitem').length == 0) { -+ $(this).trigger('transformToTag'); -+ event.preventDefault(); -+ return false; -+ } -+ break; -+ case 37: // LEFT -+ case 39: // RIGHT -+ if($(this).val().length == 0) { -+ // select previous Tag -+ var inc = code == 37 ? -1 : 1, -+ items = elements.find('li.tagedit-listelement-old') -+ x = items.length, next = 0; -+ items.each(function(i, elem) { -+ if ($(elem).hasClass('tagedit-listelement-focus')) { -+ x = i; -+ return true; -+ } -+ }); -+ unfocusItem(); -+ next = Math.max(0, x + inc); -+ if (items.get(next)) { -+ focusItem = items.eq(next).addClass('tagedit-listelement-focus'); -+ $(this).attr('aria-activedescendant', focusItem.attr('aria-labelledby')) -+ -+ if(options.autocompleteOptions.source != false) { -+ $(this).autocomplete('close').autocomplete('disable'); -+ } -+ } -+ event.preventDefault(); -+ return false; -+ } -+ break; -+ default: -+ // ignore input if an item is focused -+ if (focusItem !== null) { -+ event.preventDefault(); -+ event.bubble = false; -+ return false; -+ } -+ } -+ return true; -+ }) -+ .keypress(function(event) { -+ var code = event.keyCode > 0? event.keyCode : event.which; -+ if($.inArray(code, options.breakKeyCodes) > -1) { -+ if($(this).val().length > 0 && $('ul.ui-autocomplete #ui-active-menuitem').length == 0) { -+ $(this).trigger('transformToTag'); -+ } -+ event.preventDefault(); -+ return false; -+ } -+ else if($(this).val().length > 0){ -+ unfocusItem(); -+ } -+ return true; -+ }) -+ .bind('paste', function(e){ -+ var that = $(this); -+ if (e.type == 'paste'){ -+ setTimeout(function(){ -+ that.trigger('transformToTag'); -+ }, 1); -+ } -+ }) -+ .blur(function() { -+ if($(this).val().length == 0) { -+ // disable the field to prevent sending with the form -+ $(this).attr('disabled', 'disabled').addClass('tagedit-input-disabled'); -+ } -+ else { -+ // Delete entry after a timeout -+ var input = $(this); -+ $(this).data('blurtimer', window.setTimeout(function() {input.val('');}, 500)); -+ } -+ unfocusItem(); -+ // restore tabindex when widget looses focus -+ if (options.tabindex) -+ elements.attr('tabindex', options.tabindex); -+ }) -+ .focus(function() { -+ window.clearTimeout($(this).data('blurtimer')); -+ // remove tabindex on <ul> because #tagedit-input now has it -+ elements.attr('tabindex', '-1'); -+ }); -+ -+ if(options.autocompleteOptions.source != false) { -+ $(this).autocomplete(options.autocompleteOptions); -+ } -+ }) -+ .end() -+ .click(function(event) { -+ switch(event.target.tagName) { -+ case 'A': -+ $(event.target).parent().fadeOut(options.animSpeed, function() { -+ $(event.target).parent().remove(); -+ elements.find('#tagedit-input').focus(); -+ }); -+ break; -+ case 'INPUT': -+ case 'SPAN': -+ case 'LI': -+ if($(event.target).hasClass('tagedit-listelement-deleted') == false && -+ $(event.target).parent('li').hasClass('tagedit-listelement-deleted') == false) { -+ // Don't edit an deleted Items -+ return doEdit(event); -+ } -+ default: -+ $(this).find('#tagedit-input') -+ .removeAttr('disabled') -+ .removeClass('tagedit-input-disabled') -+ .focus(); -+ } -+ return false; -+ }) -+ // forward focus event (on tabbing through the form) -+ .focus(function(e){ $(this).click(); }) -+ } -+ -+ /** -+ * Remove class and reference to currently focused tag item -+ */ -+ function unfocusItem() { -+ if(focusItem){ -+ if(options.autocompleteOptions.source != false) { -+ elements.find('#tagedit-input').autocomplete('enable'); -+ } -+ focusItem.removeClass('tagedit-listelement-focus'); -+ focusItem = null; -+ elements.find('#tagedit-input').removeAttr('aria-activedescendant'); -+ } -+ } -+ -+ /** -+ * Sets all Actions and events for editing an Existing Tag. -+ * -+ * @param event {object} The original Event that was given -+ * return {boolean} -+ */ -+ function doEdit(event) { -+ if(options.allowEdit == false) { -+ // Do nothing -+ return; -+ } -+ -+ var element = event.target.tagName == 'SPAN'? $(event.target).parent() : $(event.target); -+ -+ var closeTimer = null; -+ -+ // Event that is fired if the User finishes the edit of a tag -+ element.bind('finishEdit', function(event, doReset) { -+ window.clearTimeout(closeTimer); -+ -+ var textfield = $(this).find(':text'); -+ var isNewResult = isNew(textfield.val(), true); -+ if(textfield.val().length > 0 && (typeof doReset == 'undefined' || doReset === false) && (isNewResult[0] == true)) { -+ // This is a new Value and we do not want to do a reset. Set the new value -+ $(this).find(':hidden').val(textfield.val()); -+ $(this).find('span').html(textfield.val()); -+ } -+ -+ textfield.remove(); -+ $(this).find('a.tagedit-save, a.tagedit-break, a.tagedit-delete').remove(); // Workaround. This normaly has to be done by autogrow Plugin -+ $(this).removeClass('tagedit-listelement-edit').unbind('finishEdit'); -+ return false; -+ }); -+ -+ var hidden = element.find(':hidden'); -+ html = '<input type="text" name="tmpinput" autocomplete="off" value="'+hidden.val()+'" class="tagedit-edit-input" dir="'+options.direction+'"/>'; -+ html += '<a class="tagedit-save" title="'+options.texts.saveEditLinkTitle+'">o</a>'; -+ html += '<a class="tagedit-break" title="'+options.texts.breakEditLinkTitle+'">x</a>'; -+ -+ // If the Element is one from the Database, it can be deleted -+ if(options.allowDelete == true && element.find(':hidden').length > 0 && -+ typeof element.find(':hidden').attr('name').match(baseNameRegexp)[3] != 'undefined') { -+ html += '<a class="tagedit-delete" title="'+options.texts.deleteLinkTitle+'">d</a>'; -+ } -+ -+ hidden.after(html); -+ element -+ .addClass('tagedit-listelement-edit') -+ .find('a.tagedit-save') -+ .click(function() { -+ $(this).parent().trigger('finishEdit'); -+ return false; -+ }) -+ .end() -+ .find('a.tagedit-break') -+ .click(function() { -+ $(this).parent().trigger('finishEdit', [true]); -+ return false; -+ }) -+ .end() -+ .find('a.tagedit-delete') -+ .click(function() { -+ window.clearTimeout(closeTimer); -+ if(confirm(options.texts.deleteConfirmation)) { -+ var canDelete = checkToDelete($(this).parent()); -+ if (!canDelete && confirm(options.texts.forceDeleteConfirmation)) { -+ markAsDeleted($(this).parent()); -+ } -+ -+ if(canDelete) { -+ markAsDeleted($(this).parent()); -+ } -+ -+ $(this).parent().find(':text').trigger('finishEdit', [true]); -+ } -+ else { -+ $(this).parent().find(':text').trigger('finishEdit', [true]); -+ } -+ return false; -+ }) -+ .end() -+ .find(':text') -+ .focus() -+ .autoGrowInput({comfortZone: 10, minWidth: 15, maxWidth: 20000}) -+ .keypress(function(event) { -+ switch(event.keyCode) { -+ case 13: // RETURN -+ event.preventDefault(); -+ $(this).parent().trigger('finishEdit'); -+ return false; -+ case 27: // ESC -+ event.preventDefault(); -+ $(this).parent().trigger('finishEdit', [true]); -+ return false; -+ } -+ return true; -+ }) -+ .blur(function() { -+ var that = $(this); -+ closeTimer = window.setTimeout(function() {that.parent().trigger('finishEdit', [true])}, 500); -+ }); -+ } -+ -+ /** -+ * Verifies if the tag select to be deleted is used by other records using an Ajax request. -+ * -+ * @param element -+ * @returns {boolean} -+ */ -+ function checkToDelete(element) { -+ // if no URL is provide will not verify -+ if(options.checkToDeleteURL === null) { -+ return false; -+ } -+ -+ var inputName = element.find('input:hidden').attr('name'); -+ var idPattern = new RegExp('\\d'); -+ var tagId = inputName.match(idPattern); -+ var checkResult = false; -+ -+ $.ajax({ -+ async : false, -+ url : options.checkToDeleteURL, -+ dataType: 'json', -+ type : 'POST', -+ data : { 'tagId' : tagId}, -+ complete: function (XMLHttpRequest, textStatus) { -+ -+ // Expected JSON Object: { "success": Boolean, "allowDelete": Boolean} -+ var result = $.parseJSON(XMLHttpRequest.responseText); -+ if(result.success === true){ -+ checkResult = result.allowDelete; -+ } -+ } -+ }); -+ -+ return checkResult; -+ } -+ -+ /** -+ * Marks a single Tag as deleted. -+ * -+ * @param element {object} -+ */ -+ function markAsDeleted(element) { -+ element -+ .trigger('finishEdit', [true]) -+ .addClass('tagedit-listelement-deleted') -+ .attr('title', options.deletedElementTitle); -+ element.find(':hidden').each(function() { -+ var nameEndRegexp = new RegExp('('+options.addedPostfix+'|'+options.deletedPostfix+')?\]'); -+ var name = $(this).attr('name').replace(nameEndRegexp, options.deletedPostfix+']'); -+ $(this).attr('name', name); -+ }); -+ -+ } -+ -+ /** -+ * Checks if a tag is already choosen. -+ * -+ * @param value {string} -+ * @param checkAutocomplete {boolean} optional Check also the autocomplet values -+ * @returns {Array} First item is a boolean, telling if the item should be put to the list, second is optional the ID from autocomplete list -+ */ -+ function isNew(value, checkAutocomplete) { -+ checkAutocomplete = typeof checkAutocomplete == 'undefined'? false : checkAutocomplete; -+ var autoCompleteId = null; -+ -+ var compareValue = options.checkNewEntriesCaseSensitive == true? value : value.toLowerCase(); -+ -+ var isNew = true; -+ elements.find('li.tagedit-listelement-old input:hidden').each(function() { -+ var elementValue = options.checkNewEntriesCaseSensitive == true? $(this).val() : $(this).val().toLowerCase(); -+ if(elementValue == compareValue) { -+ isNew = false; -+ } -+ }); -+ -+ if (isNew == true && checkAutocomplete == true && options.autocompleteOptions.source != false) { -+ var result = []; -+ if ($.isArray(options.autocompleteOptions.source)) { -+ result = options.autocompleteOptions.source; -+ } -+ else if ($.isFunction(options.autocompleteOptions.source)) { -+ options.autocompleteOptions.source({term: value}, function (data) {result = data}); -+ } -+ else if (typeof options.autocompleteOptions.source === "string") { -+ // Check also autocomplete values -+ var autocompleteURL = options.autocompleteOptions.source; -+ if (autocompleteURL.match(/\?/)) { -+ autocompleteURL += '&'; -+ } else { -+ autocompleteURL += '?'; -+ } -+ autocompleteURL += 'term=' + value; -+ $.ajax({ -+ async: false, -+ url: autocompleteURL, -+ dataType: 'json', -+ complete: function (XMLHttpRequest, textStatus) { -+ result = $.parseJSON(XMLHttpRequest.responseText); -+ } -+ }); -+ } -+ -+ // If there is an entry for that already in the autocomplete, don't use it (Check could be case sensitive or not) -+ for (var i = 0; i < result.length; i++) { -+ var resultValue = result[i].label? result[i].label : result[i]; -+ var label = options.checkNewEntriesCaseSensitive == true? resultValue : resultValue.toLowerCase(); -+ if (label == compareValue) { -+ isNew = false; -+ autoCompleteId = typeof result[i] == 'string' ? i : result[i].id; -+ break; -+ } -+ } -+ } -+ -+ return new Array(isNew, autoCompleteId); -+ } -+ } -+})(jQuery); -+ -+(function($){ -+ -+// jQuery autoGrowInput plugin by James Padolsey -+// See related thread: http://stackoverflow.com/questions/931207/is-there-a-jquery-autogrow-plugin-for-text-fields -+ -+$.fn.autoGrowInput = function(o) { -+ -+ o = $.extend({ -+ maxWidth: 1000, -+ minWidth: 0, -+ comfortZone: 70 -+ }, o); -+ -+ this.filter('input:text').each(function(){ -+ -+ var minWidth = o.minWidth || $(this).width(), -+ val = '', -+ input = $(this), -+ testSubject = $('<tester/>').css({ -+ position: 'absolute', -+ top: -9999, -+ left: -9999, -+ width: 'auto', -+ fontSize: input.css('fontSize'), -+ fontFamily: input.css('fontFamily'), -+ fontWeight: input.css('fontWeight'), -+ letterSpacing: input.css('letterSpacing'), -+ whiteSpace: 'nowrap' -+ }), -+ check = function() { -+ -+ if (val === (val = input.val())) {return;} -+ -+ // Enter new content into testSubject -+ var escaped = val.replace(/&/g, '&').replace(/\s/g,' ').replace(/</g, '<').replace(/>/g, '>'); -+ testSubject.html(escaped); -+ -+ // Calculate new width + whether to change -+ var testerWidth = testSubject.width(), -+ newWidth = (testerWidth + o.comfortZone) >= minWidth ? testerWidth + o.comfortZone : minWidth, -+ currentWidth = input.width(), -+ isValidWidthChange = (newWidth < currentWidth && newWidth >= minWidth) -+ || (newWidth > minWidth && newWidth < o.maxWidth); -+ -+ // Animate width -+ if (isValidWidthChange) { -+ input.width(newWidth); -+ } -+ -+ }; -+ -+ testSubject.insertAfter(input); -+ -+ $(this).bind('keyup keydown blur update', check); -+ -+ check(); -+ }); -+ -+ return this; -+ -+}; -+ -+})(jQuery); -\ No newline at end of file -diff --git a/plugins/jqueryui/themes/larry/tagedit.css b/plugins/jqueryui/themes/larry/tagedit.css -new file mode 100644 -index 0000000..600481c ---- /dev/null -+++ b/plugins/jqueryui/themes/larry/tagedit.css -@@ -0,0 +1,122 @@ -+/** -+ * Styles of the tagedit inputsforms -+ */ -+.tagedit-list { -+ width: 100%; -+ margin: 0; -+ padding: 4px 4px 0 5px; -+ overflow: auto; -+ min-height: 26px; -+ background: #fff; -+ border: 1px solid #b2b2b2; -+ border-radius: 4px; -+ box-shadow: inset 0 0 2px 1px rgba(0,0,0, 0.1); -+ -moz-box-shadow: inset 0 0 2px 1px rgba(0,0,0, 0.1); -+ -webkit-box-shadow: inset 0 0 2px 1px rgba(0,0,0, 0.1); -+ -o-box-shadow: inset 0 0 2px 1px rgba(0,0,0, 0.1); -+} -+.tagedit-list li.tagedit-listelement { -+ list-style-type: none; -+ float: left; -+ margin: 0 4px 4px 0; -+ padding: 0; -+} -+ -+/* New Item input */ -+.tagedit-list li.tagedit-listelement-new input { -+ border: 0; -+ height: 100%; -+ padding: 4px 1px; -+ width: 15px; -+ background: #fff; -+ border-radius: 0; -+ box-shadow: none; -+ -moz-box-shadow: none; -+ -webkit-box-shadow: none; -+ -o-box-shadow: none; -+} -+.tagedit-list li.tagedit-listelement-new input:focus { -+ box-shadow: none; -+ -moz-box-shadow: none; -+ -webkit-box-shadow: none; -+ -o-box-shadow: none; -+ outline: none; -+} -+.tagedit-list li.tagedit-listelement-new input.tagedit-input-disabled { -+ display: none; -+} -+ -+/* Item that is put to the List */ -+.tagedit span.tag-element, -+.tagedit-list li.tagedit-listelement-old { -+ padding: 3px 6px 1px 6px; -+ background: #ddeef5; -+ background: -moz-linear-gradient(top, #edf6fa 0%, #d6e9f3 100%); -+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#edf6fa), color-stop(100%,#d6e9f3)); -+ background: -o-linear-gradient(top, #edf6fa 0%, #d6e9f3 100%); -+ background: -ms-linear-gradient(top, #edf6fa 0%, #d6e9f3 100%); -+ background: linear-gradient(top, #edf6fa 0%, #d6e9f3 100%); -+ border: 1px solid #c2dae5; -+ -moz-border-radius: 4px; -+ -webkit-border-radius: 4px; -+ border-radius: 4px; -+ color: #0d5165; -+ line-height: 1.3em; -+} -+ -+.tagedit-list li.tagedit-listelement-focus { -+ border-color: #4787b1; -+ -moz-box-shadow: 0 0 3px 1px rgba(71,135,177, 0.8); -+ -webkit-box-shadow: 0 0 3px 1px rgba(71,135,177, 0.8); -+ -o-box-shadow: 0 0 3px 1px rgba(71,135,177, 0.8); -+ box-shadow: 0 0 3px 1px rgba(71,135,177, 0.8); -+} -+ -+.tagedit span.tag-element { -+ margin-right: 0.6em; -+ padding: 2px 6px; -+/* cursor: pointer; */ -+} -+ -+.tagedit span.tag-element.inherit { -+ color: #666; -+ background: #f2f2f2; -+ border-color: #ddd; -+} -+ -+.tagedit-list li.tagedit-listelement-old a.tagedit-close, -+.tagedit-list li.tagedit-listelement-old a.tagedit-break, -+.tagedit-list li.tagedit-listelement-old a.tagedit-delete, -+.tagedit-list li.tagedit-listelement-old a.tagedit-save { -+ text-indent: -2000px; -+ display: inline-block; -+ position: relative; -+ top: -1px; -+ width: 16px; -+ height: 16px; -+ margin: 0 -4px 0 6px; -+ background: url('data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAAOCAYAAAD0f5bSAAAAgUlEQVQoz2NgQAKzdxwWAOIEIG5AwiC+AAM2AJQIAOL3QPwfCwaJB6BrSMChGB0nwDQYwATP3nn4f+Ge4ygKQXyQOJKYAUjTepjAm09fwBimEUTDxJA0rWdANxWmaMXB0xiGwDADurthGkEAmwbqaCLFeWQFBOlBTlbkkp2MSE2wAA8R50rWvqeRAAAAAElFTkSuQmCC') left 1px no-repeat; -+ cursor: pointer; -+} -+ -+.tagedit-list li.tagedit-listelement-old span { -+ display: inline-block; -+ height: 15px; -+} -+ -+/** Special hacks for IE7 **/ -+ -+html.ie7 .tagedit span.tag-element, -+html.ie7 .tagedit-list li.tagedit-listelement-old { -+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#edf6fa', endColorstr='#d6e9f3', GradientType=0); -+} -+ -+html.ie7 .tagedit-list li.tagedit-listelement span { -+ position: relative; -+ top: -3px; -+} -+ -+html.ie7 .tagedit-list li.tagedit-listelement-old a.tagedit-close { -+ left: 5px; -+} -+
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.