Permalink
Browse files

[gsoc2009/admin-ui] Some love for autocomplete.

- A new, nicer m2m autocomplete
- Backend autocomplete view returns JSON instead of a funky parsed format
- Upgraded the FKey autocomplete plugin



git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/admin-ui@11795 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
1 parent 379fecb commit 2ea3b4e058e13aaa17f813872ac1dba0892a3c40 @zain zain committed Dec 5, 2009
@@ -0,0 +1,110 @@
+ul.token-input-list {
+ overflow: hidden;
+ height: auto !important;
+ height: 1%;
+ width: 400px;
+ border: 1px solid #999;
+ cursor: text;
+ font-size: 12px;
+ font-family: Verdana;
+ z-index: 999;
+ margin: 0;
+ padding: 0 !important;
+ background-color: #fff;
+}
+
+ul.token-input-list li {
+ list-style-type: none;
+}
+
+ul.token-input-list li input {
+ border: 0;
+ width: 350px;
+ padding: 3px 8px;
+ background-color: white;
+}
+
+li.token-input-token {
+ overflow: hidden;
+ height: auto !important;
+ height: 1%;
+ margin: 3px;
+ padding: 3px 5px;
+ background-color: #d0efa0;
+ color: #000;
+ font-weight: bold;
+ cursor: default;
+ display: block;
+}
+
+li.token-input-token p {
+ float: left;
+ padding: 0;
+ margin: 0;
+}
+
+li.token-input-token span {
+ float: right;
+ color: #777;
+ cursor: pointer;
+}
+
+li.token-input-selected-token {
+ background-color: #08844e;
+ color: #fff;
+}
+
+li.token-input-selected-token span {
+ color: #bbb;
+}
+
+div.token-input-dropdown {
+ position: absolute;
+ width: 400px;
+ background-color: #fff;
+ overflow: hidden;
+ border-left: 1px solid #ccc;
+ border-right: 1px solid #ccc;
+ border-bottom: 1px solid #ccc;
+ cursor: default;
+ font-size: 12px;
+ font-family: Verdana;
+ z-index: 1;
+ margin-left: 106px;
+}
+
+div.token-input-dropdown p {
+ margin: 0;
+ padding: 5px;
+ font-weight: bold;
+ color: #777;
+}
+
+div.token-input-dropdown ul {
+ margin: 0;
+ padding: 0;
+}
+
+div.token-input-dropdown ul li {
+ background-color: #fff;
+ padding: 3px;
+ list-style-type: none;
+}
+
+div.token-input-dropdown ul li.token-input-dropdown-item {
+ background-color: #fafafa;
+}
+
+div.token-input-dropdown ul li.token-input-dropdown-item2 {
+ background-color: #fff;
+}
+
+div.token-input-dropdown ul li em {
+ font-weight: bold;
+ font-style: normal;
+}
+
+div.token-input-dropdown ul li.token-input-selected-dropdown-item {
+ background-color: #d0efa0;
+}
+
@@ -1,14 +1,13 @@
/*
- * Autocomplete - jQuery plugin 1.0.2
+ * jQuery Autocomplete plugin 1.1
*
- * Copyright (c) 2007 Dylan Verheul, Dan G. Switzer, Anjesh Tuladhar, Jörn Zaefferer
+ * Copyright (c) 2009 Jörn Zaefferer
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
- * Revision: $Id: jquery.autocomplete.js 5747 2008-06-25 18:30:55Z joern.zaefferer $
- *
+ * Revision: $Id: jquery.autocomplete.js 14 2009-08-22 10:29:29Z joern.zaefferer $
*/
;(function($) {
@@ -90,6 +89,9 @@ $.Autocompleter = function(input, options) {
// only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all
$input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) {
+ // a keypress means the input has focus
+ // avoids issue where input had focus before the autocomplete was applied
+ hasFocus = 1;
// track last key pressed
lastKeyPressCode = event.keyCode;
switch(event.keyCode) {
@@ -209,7 +211,21 @@ $.Autocompleter = function(input, options) {
if ( options.multiple ) {
var words = trimWords($input.val());
if ( words.length > 1 ) {
- v = words.slice(0, words.length - 1).join( options.multipleSeparator ) + options.multipleSeparator + v;
+ var seperator = options.multipleSeparator.length;
+ var cursorAt = $(input).selection().start;
+ var wordAt, progress = 0;
+ $.each(words, function(i, word) {
+ progress += word.length;
+ if (cursorAt <= progress) {
+ wordAt = i;
+ return false;
+ }
+ progress += seperator;
+ });
+ words[wordAt] = v;
+ // TODO this should set the cursor to the right position, but it gets overriden somewhere
+ //$.Autocompleter.Selection(input, progress + seperator, progress + seperator);
+ v = words.join( options.multipleSeparator );
}
v += options.multipleSeparator;
}
@@ -246,22 +262,27 @@ $.Autocompleter = function(input, options) {
};
function trimWords(value) {
- if ( !value ) {
+ if (!value)
return [""];
- }
- var words = value.split( options.multipleSeparator );
- var result = [];
- $.each(words, function(i, value) {
- if ( $.trim(value) )
- result[i] = $.trim(value);
+ if (!options.multiple)
+ return [$.trim(value)];
+ return $.map(value.split(options.multipleSeparator), function(word) {
+ return $.trim(value).length ? $.trim(word) : null;
});
- return result;
}
function lastWord(value) {
if ( !options.multiple )
return value;
var words = trimWords(value);
+ if (words.length == 1)
+ return words[0];
+ var cursorAt = $(input).selection().start;
+ if (cursorAt == value.length) {
+ words = trimWords(value)
+ } else {
+ words = trimWords(value.replace(value.substring(cursorAt), ""));
+ }
return words[words.length - 1];
}
@@ -275,7 +296,7 @@ $.Autocompleter = function(input, options) {
// fill in the value (keep the case the user has typed)
$input.val($input.val() + sValue.substring(lastWord(previousValue).length));
// select the portion of the value not typed by the user (so the next character will erase)
- $.Autocompleter.Selection(input, previousValue.length, previousValue.length + sValue.length);
+ $(input).selection(previousValue.length, previousValue.length + sValue.length);
}
};
@@ -299,15 +320,14 @@ $.Autocompleter = function(input, options) {
var words = trimWords($input.val()).slice(0, -1);
$input.val( words.join(options.multipleSeparator) + (words.length ? options.multipleSeparator : "") );
}
- else
+ else {
$input.val( "" );
+ $input.trigger("result", null);
+ }
}
}
);
}
- if (wasVisible)
- // position cursor at end of input field
- $.Autocompleter.Selection(input, input.value.length, input.value.length);
};
function receiveData(q, data) {
@@ -421,6 +441,9 @@ $.Autocompleter.Cache = function(options) {
if (!options.matchCase)
s = s.toLowerCase();
var i = s.indexOf(sub);
+ if (options.matchContains == "word"){
+ i = s.toLowerCase().search("\\b" + sub.toLowerCase());
+ }
if (i == -1) return false;
return i == 0 || options.matchContains;
};
@@ -738,22 +761,48 @@ $.Autocompleter.Select = function (options, input, select, config) {
};
};
-$.Autocompleter.Selection = function(field, start, end) {
- if( field.createTextRange ){
- var selRange = field.createTextRange();
- selRange.collapse(true);
- selRange.moveStart("character", start);
- selRange.moveEnd("character", end);
- selRange.select();
- } else if( field.setSelectionRange ){
- field.setSelectionRange(start, end);
- } else {
- if( field.selectionStart ){
- field.selectionStart = start;
- field.selectionEnd = end;
+$.fn.selection = function(start, end) {
+ if (start !== undefined) {
+ return this.each(function() {
+ if( this.createTextRange ){
+ var selRange = this.createTextRange();
+ if (end === undefined || start == end) {
+ selRange.move("character", start);
+ selRange.select();
+ } else {
+ selRange.collapse(true);
+ selRange.moveStart("character", start);
+ selRange.moveEnd("character", end);
+ selRange.select();
+ }
+ } else if( this.setSelectionRange ){
+ this.setSelectionRange(start, end);
+ } else if( this.selectionStart ){
+ this.selectionStart = start;
+ this.selectionEnd = end;
+ }
+ });
+ }
+ var field = this[0];
+ if ( field.createTextRange ) {
+ var range = document.selection.createRange(),
+ orig = field.value,
+ teststring = "<->",
+ textLength = range.text.length;
+ range.text = teststring;
+ var caretAt = field.value.indexOf(teststring);
+ field.value = orig;
+ this.selection(caretAt, caretAt + textLength);
+ return {
+ start: caretAt,
+ end: caretAt + textLength
+ }
+ } else if( field.selectionStart !== undefined ){
+ return {
+ start: field.selectionStart,
+ end: field.selectionEnd
}
}
- field.focus();
};
})(jQuery);
Oops, something went wrong.

0 comments on commit 2ea3b4e

Please sign in to comment.