multiselectjs_rails 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE.txt +20 -0
- data/README.md +5 -0
- data/lib/multiselectjs_rails.rb +8 -0
- data/lib/multiselectjs_rails/version.rb +3 -0
- data/vendor/assets/javascripts/locale/ui-multiselect-de.js +11 -0
- data/vendor/assets/javascripts/locale/ui-multiselect-en.js +11 -0
- data/vendor/assets/javascripts/locale/ui-multiselect-es.js +11 -0
- data/vendor/assets/javascripts/locale/ui-multiselect-fr.js +11 -0
- data/vendor/assets/javascripts/locale/ui-multiselect-it.js +13 -0
- data/vendor/assets/javascripts/plugins/localisation/jquery.localisation-min.js +7 -0
- data/vendor/assets/javascripts/plugins/localisation/jquery.localisation-pack.js +7 -0
- data/vendor/assets/javascripts/plugins/localisation/jquery.localisation.js +99 -0
- data/vendor/assets/javascripts/plugins/scrollTo/README.txt +37 -0
- data/vendor/assets/javascripts/plugins/scrollTo/changes.txt +82 -0
- data/vendor/assets/javascripts/plugins/scrollTo/jquery.scrollTo-min.js +11 -0
- data/vendor/assets/javascripts/plugins/scrollTo/jquery.scrollTo.js +207 -0
- data/vendor/assets/javascripts/ui.multiselect.js +480 -0
- data/vendor/assets/stylesheets/ui.multiselect.css +31 -0
- metadata +101 -0
data/MIT-LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Michael Aufreiter, http://www.quasipartikel.at
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
/* http://keith-wood.name/localisation.html
|
2
|
+
Localisation assistance for jQuery v1.0.4.
|
3
|
+
Written by Keith Wood (kbwood{at}iinet.com.au) June 2007.
|
4
|
+
Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
|
5
|
+
MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
|
6
|
+
Please attribute the author if you use it. */
|
7
|
+
(function($){$.localise=function(c,d,e,f,g){if(typeof d!='object'&&typeof d!='string'){g=f;f=e;e=d;d=''}if(typeof e!='boolean'){g=f;f=e;e=false}if(typeof f!='string'&&!isArray(f)){g=f;f=['','']}var h={async:$.ajaxSettings.async,timeout:$.ajaxSettings.timeout};d=(typeof d!='string'?d||{}:{language:d,loadBase:e,path:f,timeout:g});var j=(!d.path?['','']:(isArray(d.path)?d.path:[d.path,d.path]));$.ajaxSetup({async:false,timeout:(d.timeout||500)});var k=function(a,b){if(d.loadBase){$.getScript(j[0]+a+'.js')}if(b.length>=2){$.getScript(j[1]+a+'-'+b.substring(0,2)+'.js')}if(b.length>=5){$.getScript(j[1]+a+'-'+b.substring(0,5)+'.js')}};var l=normaliseLang(d.language||$.localise.defaultLanguage);c=(isArray(c)?c:[c]);for(i=0;i<c.length;i++){k(c[i],l)}$.ajaxSetup(h)};$.localize=$.localise;$.localise.defaultLanguage=normaliseLang(navigator.language||navigator.userLanguage);function normaliseLang(a){a=a.replace(/_/,'-').toLowerCase();if(a.length>3){a=a.substring(0,3)+a.substring(3).toUpperCase()}return a}function isArray(a){return(a&&a.constructor==Array)}})(jQuery);
|
@@ -0,0 +1,7 @@
|
|
1
|
+
/* http://keith-wood.name/localisation.html
|
2
|
+
Localisation assistance for jQuery v1.0.4.
|
3
|
+
Written by Keith Wood (kbwood{at}iinet.com.au) June 2007.
|
4
|
+
Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
|
5
|
+
MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
|
6
|
+
Please attribute the author if you use it. */
|
7
|
+
eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(7($){$.m=7(c,d,e,f,g){4(8 d!=\'E\'&&8 d!=\'r\'){g=f;f=e;e=d;d=\'\'}4(8 e!=\'F\'){g=f;f=e;e=x}4(8 f!=\'r\'&&!n(f)){g=f;f=[\'\',\'\']}o h={s:$.y.s,9:$.y.9};d=(8 d!=\'r\'?d||{}:{t:d,z:e,6:f,9:g});o j=(!d.6?[\'\',\'\']:(n(d.6)?d.6:[d.6,d.6]));$.A({s:x,9:(d.9||G)});o k=7(a,b){4(d.z){$.u(j[0]+a+\'.v\')}4(b.p>=2){$.u(j[1]+a+\'-\'+b.q(0,2)+\'.v\')}4(b.p>=5){$.u(j[1]+a+\'-\'+b.q(0,5)+\'.v\')}};o l=w(d.t||$.m.B);c=(n(c)?c:[c]);H(i=0;i<c.p;i++){k(c[i],l)}$.A(h)};$.I=$.m;$.m.B=w(C.t||C.J);7 w(a){a=a.K(/L/,\'-\').M();4(a.p>3){a=a.q(0,3)+a.q(3).N()}D a}7 n(a){D(a&&a.O==P)}})(Q);',53,53,'||||if||path|function|typeof|timeout|||||||||||||localise|isArray|var|length|substring|string|async|language|getScript|js|normaliseLang|false|ajaxSettings|loadBase|ajaxSetup|defaultLanguage|navigator|return|object|boolean|500|for|localize|userLanguage|replace|_|toLowerCase|toUpperCase|constructor|Array|jQuery'.split('|'),0,{}))
|
@@ -0,0 +1,99 @@
|
|
1
|
+
/* http://keith-wood.name/localisation.html
|
2
|
+
Localisation assistance for jQuery v1.0.4.
|
3
|
+
Written by Keith Wood (kbwood{at}iinet.com.au) June 2007.
|
4
|
+
Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
|
5
|
+
MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
|
6
|
+
Please attribute the author if you use it. */
|
7
|
+
|
8
|
+
(function($) { // Hide scope, no $ conflict
|
9
|
+
|
10
|
+
/* Load applicable localisation package(s) for one or more jQuery packages.
|
11
|
+
Assumes that the localisations are named <base>-<lang>.js
|
12
|
+
and loads them in order from least to most specific.
|
13
|
+
For example, $.localise('mypackage');
|
14
|
+
with the browser set to 'en-US' would attempt to load
|
15
|
+
mypackage-en.js and mypackage-en-US.js.
|
16
|
+
Also accepts an array of package names to process.
|
17
|
+
Optionally specify whether or not to include the base file,
|
18
|
+
the desired language, and/or the timeout period, e.g.
|
19
|
+
$.localise(['mypackage1', 'yourpackage'],
|
20
|
+
{loadBase: true; language: 'en-AU', timeout: 300});
|
21
|
+
@param packages (string or string[]) names of package(s) to load
|
22
|
+
@param settings omit for the current browser language or
|
23
|
+
(string) code for the language to load (aa[-AA]) or
|
24
|
+
(object} options for the call with
|
25
|
+
language (string) the code for the language
|
26
|
+
loadBase (boolean) true to also load the base package or false (default) to not
|
27
|
+
path (string or string[2]) the paths to the JavaScript,
|
28
|
+
either as both or [base, localisations]
|
29
|
+
timeout (number) the time period in milliseconds (default 500)
|
30
|
+
@param loadBase (boolean, optional) true to also load the base package or false (default) to not -
|
31
|
+
omit this if settings is an object
|
32
|
+
@param path (string or string[2], optional) the paths to the JavaScript,
|
33
|
+
either as both or [base, localisations] -
|
34
|
+
omit this if settings is an object
|
35
|
+
@param timeout (number, optional) the time period in milliseconds (default 500) -
|
36
|
+
omit this if settings is an object */
|
37
|
+
$.localise = function(packages, settings, loadBase, path, timeout) {
|
38
|
+
if (typeof settings != 'object' && typeof settings != 'string') {
|
39
|
+
timeout = path;
|
40
|
+
path = loadBase;
|
41
|
+
loadBase = settings;
|
42
|
+
settings = '';
|
43
|
+
}
|
44
|
+
if (typeof loadBase != 'boolean') {
|
45
|
+
timeout = path;
|
46
|
+
path = loadBase;
|
47
|
+
loadBase = false;
|
48
|
+
}
|
49
|
+
if (typeof path != 'string' && !isArray(path)) {
|
50
|
+
timeout = path;
|
51
|
+
path = ['', ''];
|
52
|
+
}
|
53
|
+
var saveSettings = {async: $.ajaxSettings.async, timeout: $.ajaxSettings.timeout};
|
54
|
+
settings = (typeof settings != 'string' ? settings || {} :
|
55
|
+
{language: settings, loadBase: loadBase, path: path, timeout: timeout});
|
56
|
+
var paths = (!settings.path ? ['', ''] :
|
57
|
+
(isArray(settings.path) ? settings.path : [settings.path, settings.path]));
|
58
|
+
$.ajaxSetup({async: false, timeout: (settings.timeout || 500)});
|
59
|
+
var localiseOne = function(package, lang) {
|
60
|
+
if (settings.loadBase) {
|
61
|
+
$.getScript(paths[0] + package + '.js');
|
62
|
+
}
|
63
|
+
if (lang.length >= 2) {
|
64
|
+
$.getScript(paths[1] + package + '-' + lang.substring(0, 2) + '.js');
|
65
|
+
}
|
66
|
+
if (lang.length >= 5) {
|
67
|
+
$.getScript(paths[1] + package + '-' + lang.substring(0, 5) + '.js');
|
68
|
+
}
|
69
|
+
};
|
70
|
+
var lang = normaliseLang(settings.language || $.localise.defaultLanguage);
|
71
|
+
packages = (isArray(packages) ? packages : [packages]);
|
72
|
+
for (i = 0; i < packages.length; i++) {
|
73
|
+
localiseOne(packages[i], lang);
|
74
|
+
}
|
75
|
+
$.ajaxSetup(saveSettings);
|
76
|
+
};
|
77
|
+
|
78
|
+
// Localise it!
|
79
|
+
$.localize = $.localise;
|
80
|
+
|
81
|
+
/* Retrieve the default language set for the browser. */
|
82
|
+
$.localise.defaultLanguage = normaliseLang(navigator.language /* Mozilla */ ||
|
83
|
+
navigator.userLanguage /* IE */);
|
84
|
+
|
85
|
+
/* Ensure language code is in the format aa-AA. */
|
86
|
+
function normaliseLang(lang) {
|
87
|
+
lang = lang.replace(/_/, '-').toLowerCase();
|
88
|
+
if (lang.length > 3) {
|
89
|
+
lang = lang.substring(0, 3) + lang.substring(3).toUpperCase();
|
90
|
+
}
|
91
|
+
return lang;
|
92
|
+
}
|
93
|
+
|
94
|
+
/* Determine whether an object is an array. */
|
95
|
+
function isArray(a) {
|
96
|
+
return (a && a.constructor == Array);
|
97
|
+
}
|
98
|
+
|
99
|
+
})(jQuery);
|
@@ -0,0 +1,37 @@
|
|
1
|
+
jQuery.ScrollTo 1.4
|
2
|
+
|
3
|
+
* Apart from the target and duration, the plugin can receive a hash of settings. Documentation and examples are included in the source file.
|
4
|
+
|
5
|
+
* If you are interested in animated "same-page-scrolling" using anchors(<a href="#some_id">...), check http://jquery.com/plugins/project/LocalScroll
|
6
|
+
|
7
|
+
* The target can be specified as:
|
8
|
+
* A Number/String specifying a position using px or just the number.
|
9
|
+
* A string selector that will be relative, to the element that is going to be scrolled, and must match at least one child.
|
10
|
+
* A DOM element, logically child of the element to scroll.
|
11
|
+
* A hash { top:x, left:y }, x and y can be any kind of number/string like described above.
|
12
|
+
|
13
|
+
* The plugin supports relative animations
|
14
|
+
|
15
|
+
* 'em' and '%' are not supported as part of the target, because they won't work with jQuery.fn.animate.
|
16
|
+
|
17
|
+
* The plugin might fail to scroll an element, to an inner node that is nested in more scrollable elements. This seems like an odd situation anyway.
|
18
|
+
|
19
|
+
* Both axes ( x, y -> left, top ) can be scrolled, you can send 'x', 'y', 'xy' or 'yx' as 'axis' inside the settings.
|
20
|
+
|
21
|
+
* If 2 axis are scrolled, there's an option to queue the animations, so that the second will start once the first ended ('xy' and 'yx' will have different effects)
|
22
|
+
|
23
|
+
* The option 'margin' can be setted to true, then the margin of the target element, will be taken into account and will be deducted.
|
24
|
+
|
25
|
+
* 'margin' will only be valid, if the target is a selector, a DOM element, or a jQuery Object.
|
26
|
+
|
27
|
+
* The option 'offset' allows to scroll less or more than the actual target by a defined amount of pixels. Can be a number(both axes) or { top:x, left:y }.
|
28
|
+
|
29
|
+
* The option 'over' lets you add or deduct a fraction of the element's height and width from the final position. so over:0.5 will scroll to the middle of the object. can be specified with {top:x, left:y}
|
30
|
+
|
31
|
+
* Don't forget the callback event is now called 'onAfter', and if queuing is activated, then 'onAfterFirst' can be used.
|
32
|
+
|
33
|
+
* If the first axis to be scrolled, is already positioned, that animation will be skipped, to avoid a delay in the animation.
|
34
|
+
|
35
|
+
* The call to the plugin can be made in 2 different ways: $().scrollTo( target, duration, settings ) or $().scrollTo( target, settings ). Where one of the settings is 'duration'.
|
36
|
+
|
37
|
+
* If you find any bug, or you have any advice, don't hesitate to open a ticket/request at http://jquery.com/plugins/project/ScrollTo .
|
@@ -0,0 +1,82 @@
|
|
1
|
+
1.4.1
|
2
|
+
[Feature]
|
3
|
+
- The target can be 'max' to scroll to the end while keeping it elegant.
|
4
|
+
[Enhancement]
|
5
|
+
- Default duration is 0 for jquery +1.3. Means sync animation
|
6
|
+
- The plugin works on all major browsers, on compat & quirks modes, including iframes.
|
7
|
+
- In addition to window/document, if html or body are received, the plugin will choose the right one.
|
8
|
+
[Fix]
|
9
|
+
- The Regex accepts floating numbers, Thanks Ramin
|
10
|
+
- Using jQuery.nodeName where neccessary so that this works on xml+xhtml
|
11
|
+
- The max() internal function wasn't completely accurrate, now it is 98% (except for IE on quirks mode and it's not too noticeable).
|
12
|
+
|
13
|
+
1.4
|
14
|
+
[Fix]
|
15
|
+
- Fixed the problem when scrolling the window to absolute positioned elements on Safari.
|
16
|
+
- Fixed the problem on Opera 9.5 when scrolling the window. That it always scrolls to 0.
|
17
|
+
[Feature]
|
18
|
+
- Added the settings object as 2nd argument to the onAfter callback.
|
19
|
+
- The 3rd argument of scrollTo can be just a function and it's used as the onAfter.
|
20
|
+
- Added full support for iframes (even max scroll calculation).
|
21
|
+
- Instead of $.scrollTo, $(window).scrollTo() and $(document).scrollTo() can be used.
|
22
|
+
- Added $().scrollable() that returns the real element to scroll, f.e: $(window).scrollable() == [body|html], works for iframes.
|
23
|
+
[Enhancement]
|
24
|
+
- Cleaned the code a bit, specially the comments
|
25
|
+
|
26
|
+
1.3.3
|
27
|
+
[Change]
|
28
|
+
- Changed the licensing from GPL to GPL+MIT.
|
29
|
+
|
30
|
+
1.3.2
|
31
|
+
[Enhancement]
|
32
|
+
- Small improvements to make the code shorter.
|
33
|
+
[Change]
|
34
|
+
- Removed the last argument received by onAfter as it was the same as the 'this' but jqueryfied.
|
35
|
+
|
36
|
+
1.3.1
|
37
|
+
[Feature]
|
38
|
+
- Exposed $.scrollTo.window() to get the element that needs to be animated, to scroll the window.
|
39
|
+
- Added option 'over'.
|
40
|
+
[Enhancement]
|
41
|
+
- Made the code as short as possible.
|
42
|
+
[Change]
|
43
|
+
- Changed the arguments received by onAfter
|
44
|
+
|
45
|
+
1.3
|
46
|
+
[Enhancement]
|
47
|
+
- Added semicolon to the start, for safe file concatenation
|
48
|
+
- Added a limit check, values below 0 or over the maximum are fixed.
|
49
|
+
- Now it should work faster, only one of html or body go through all the processing, instead of both for all browsers.
|
50
|
+
[Fix]
|
51
|
+
- Fixed the behavior for Opera, which seemed to react to both changes on <html> and <body>.
|
52
|
+
- The border is also reduced, when 'margin' is set to true.
|
53
|
+
[Change]
|
54
|
+
- The option speed has been renamed to duration.
|
55
|
+
[Feature]
|
56
|
+
- The duration can be specified with a number as 2nd argument, and the rest of the settings as the third ( like $().animate )
|
57
|
+
- Remade the demo
|
58
|
+
|
59
|
+
1.2.4
|
60
|
+
[Enhancement]
|
61
|
+
- The target can be in the form of { top:x, left:y } allowing different position for each axis.
|
62
|
+
[Feature]
|
63
|
+
- The option 'offset' has been added, to scroll behind or past the target. Can be a number(both axes) or { top:x, left:y }.
|
64
|
+
|
65
|
+
1.2.3
|
66
|
+
[Feature]
|
67
|
+
- Exposed the defaults.
|
68
|
+
[Enhancement]
|
69
|
+
- Made the callback functions receive more parameters.
|
70
|
+
|
71
|
+
1.2.2
|
72
|
+
[Fix]
|
73
|
+
- Fixed a bug, I didn't have to add the scrolled amount if it was body or html.
|
74
|
+
|
75
|
+
1.2
|
76
|
+
[Change]
|
77
|
+
- The option 'onafter' is now called 'onAfter'.
|
78
|
+
[Feature]
|
79
|
+
- Two axes can be scrolled together, this is set with the option 'axis'.
|
80
|
+
- In case 2 axes are chosen, the scrolling can be queued: one scrolls, and then the other.
|
81
|
+
- There's an intermediary event, 'onAfterFirst' called in case the axes are queued, after the first ends.
|
82
|
+
- If the option 'margin' is set to true, the plugin will take in account, the margin of the target(no use if target is a value).
|
@@ -0,0 +1,11 @@
|
|
1
|
+
/**
|
2
|
+
* jQuery.ScrollTo - Easy element scrolling using jQuery.
|
3
|
+
* Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
|
4
|
+
* Dual licensed under MIT and GPL.
|
5
|
+
* Date: 3/9/2009
|
6
|
+
* @author Ariel Flesler
|
7
|
+
* @version 1.4.1
|
8
|
+
*
|
9
|
+
* http://flesler.blogspot.com/2007/10/jqueryscrollto.html
|
10
|
+
*/
|
11
|
+
;(function($){var m=$.scrollTo=function(b,h,f){$(window).scrollTo(b,h,f)};m.defaults={axis:'xy',duration:parseFloat($.fn.jquery)>=1.3?0:1};m.window=function(b){return $(window).scrollable()};$.fn.scrollable=function(){return this.map(function(){var b=this,h=!b.nodeName||$.inArray(b.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!h)return b;var f=(b.contentWindow||b).document||b.ownerDocument||b;return $.browser.safari||f.compatMode=='BackCompat'?f.body:f.documentElement})};$.fn.scrollTo=function(l,j,a){if(typeof j=='object'){a=j;j=0}if(typeof a=='function')a={onAfter:a};if(l=='max')l=9e9;a=$.extend({},m.defaults,a);j=j||a.speed||a.duration;a.queue=a.queue&&a.axis.length>1;if(a.queue)j/=2;a.offset=n(a.offset);a.over=n(a.over);return this.scrollable().each(function(){var k=this,o=$(k),d=l,p,g={},q=o.is('html,body');switch(typeof d){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px)?$/.test(d)){d=n(d);break}d=$(d,this);case'object':if(d.is||d.style)p=(d=$(d)).offset()}$.each(a.axis.split(''),function(b,h){var f=h=='x'?'Left':'Top',i=f.toLowerCase(),c='scroll'+f,r=k[c],s=h=='x'?'Width':'Height';if(p){g[c]=p[i]+(q?0:r-o.offset()[i]);if(a.margin){g[c]-=parseInt(d.css('margin'+f))||0;g[c]-=parseInt(d.css('border'+f+'Width'))||0}g[c]+=a.offset[i]||0;if(a.over[i])g[c]+=d[s.toLowerCase()]()*a.over[i]}else g[c]=d[i];if(/^\d+$/.test(g[c]))g[c]=g[c]<=0?0:Math.min(g[c],u(s));if(!b&&a.queue){if(r!=g[c])t(a.onAfterFirst);delete g[c]}});t(a.onAfter);function t(b){o.animate(g,j,a.easing,b&&function(){b.call(this,l,a)})};function u(b){var h='scroll'+b;if(!q)return k[h];var f='client'+b,i=k.ownerDocument.documentElement,c=k.ownerDocument.body;return Math.max(i[h],c[h])-Math.min(i[f],c[f])}}).end()};function n(b){return typeof b=='object'?b:{top:b,left:b}}})(jQuery);
|
@@ -0,0 +1,207 @@
|
|
1
|
+
/**
|
2
|
+
* jQuery.ScrollTo
|
3
|
+
* Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
|
4
|
+
* Dual licensed under MIT and GPL.
|
5
|
+
* Date: 3/9/2009
|
6
|
+
*
|
7
|
+
* @projectDescription Easy element scrolling using jQuery.
|
8
|
+
* http://flesler.blogspot.com/2007/10/jqueryscrollto.html
|
9
|
+
* Works with jQuery +1.2.6. Tested on FF 2/3, IE 6/7, Opera 9.5/6, Safari 3, Chrome 1 on WinXP.
|
10
|
+
*
|
11
|
+
* @author Ariel Flesler
|
12
|
+
* @version 1.4.1
|
13
|
+
*
|
14
|
+
* @id jQuery.scrollTo
|
15
|
+
* @id jQuery.fn.scrollTo
|
16
|
+
* @param {String, Number, DOMElement, jQuery, Object} target Where to scroll the matched elements.
|
17
|
+
* The different options for target are:
|
18
|
+
* - A number position (will be applied to all axes).
|
19
|
+
* - A string position ('44', '100px', '+=90', etc ) will be applied to all axes
|
20
|
+
* - A jQuery/DOM element ( logically, child of the element to scroll )
|
21
|
+
* - A string selector, that will be relative to the element to scroll ( 'li:eq(2)', etc )
|
22
|
+
* - A hash { top:x, left:y }, x and y can be any kind of number/string like above.
|
23
|
+
* @param {Number} duration The OVERALL length of the animation, this argument can be the settings object instead.
|
24
|
+
* @param {Object,Function} settings Optional set of settings or the onAfter callback.
|
25
|
+
* @option {String} axis Which axis must be scrolled, use 'x', 'y', 'xy' or 'yx'.
|
26
|
+
* @option {Number} duration The OVERALL length of the animation.
|
27
|
+
* @option {String} easing The easing method for the animation.
|
28
|
+
* @option {Boolean} margin If true, the margin of the target element will be deducted from the final position.
|
29
|
+
* @option {Object, Number} offset Add/deduct from the end position. One number for both axes or { top:x, left:y }.
|
30
|
+
* @option {Object, Number} over Add/deduct the height/width multiplied by 'over', can be { top:x, left:y } when using both axes.
|
31
|
+
* @option {Boolean} queue If true, and both axis are given, the 2nd axis will only be animated after the first one ends.
|
32
|
+
* @option {Function} onAfter Function to be called after the scrolling ends.
|
33
|
+
* @option {Function} onAfterFirst If queuing is activated, this function will be called after the first scrolling ends.
|
34
|
+
* @return {jQuery} Returns the same jQuery object, for chaining.
|
35
|
+
*
|
36
|
+
* @desc Scroll to a fixed position
|
37
|
+
* @example $('div').scrollTo( 340 );
|
38
|
+
*
|
39
|
+
* @desc Scroll relatively to the actual position
|
40
|
+
* @example $('div').scrollTo( '+=340px', { axis:'y' } );
|
41
|
+
*
|
42
|
+
* @dec Scroll using a selector (relative to the scrolled element)
|
43
|
+
* @example $('div').scrollTo( 'p.paragraph:eq(2)', 500, { easing:'swing', queue:true, axis:'xy' } );
|
44
|
+
*
|
45
|
+
* @ Scroll to a DOM element (same for jQuery object)
|
46
|
+
* @example var second_child = document.getElementById('container').firstChild.nextSibling;
|
47
|
+
* $('#container').scrollTo( second_child, { duration:500, axis:'x', onAfter:function(){
|
48
|
+
* alert('scrolled!!');
|
49
|
+
* }});
|
50
|
+
*
|
51
|
+
* @desc Scroll on both axes, to different values
|
52
|
+
* @example $('div').scrollTo( { top: 300, left:'+=200' }, { axis:'xy', offset:-20 } );
|
53
|
+
*/
|
54
|
+
;(function( $ ){
|
55
|
+
|
56
|
+
var $scrollTo = $.scrollTo = function( target, duration, settings ){
|
57
|
+
$(window).scrollTo( target, duration, settings );
|
58
|
+
};
|
59
|
+
|
60
|
+
$scrollTo.defaults = {
|
61
|
+
axis:'xy',
|
62
|
+
duration: parseFloat($.fn.jquery) >= 1.3 ? 0 : 1
|
63
|
+
};
|
64
|
+
|
65
|
+
// Returns the element that needs to be animated to scroll the window.
|
66
|
+
// Kept for backwards compatibility (specially for localScroll & serialScroll)
|
67
|
+
$scrollTo.window = function( scope ){
|
68
|
+
return $(window).scrollable();
|
69
|
+
};
|
70
|
+
|
71
|
+
// Hack, hack, hack... stay away!
|
72
|
+
// Returns the real elements to scroll (supports window/iframes, documents and regular nodes)
|
73
|
+
$.fn.scrollable = function(){
|
74
|
+
return this.map(function(){
|
75
|
+
var elem = this,
|
76
|
+
isWin = !elem.nodeName || $.inArray( elem.nodeName.toLowerCase(), ['iframe','#document','html','body'] ) != -1;
|
77
|
+
|
78
|
+
if( !isWin )
|
79
|
+
return elem;
|
80
|
+
|
81
|
+
var doc = (elem.contentWindow || elem).document || elem.ownerDocument || elem;
|
82
|
+
|
83
|
+
return $.browser.safari || doc.compatMode == 'BackCompat' ?
|
84
|
+
doc.body :
|
85
|
+
doc.documentElement;
|
86
|
+
});
|
87
|
+
};
|
88
|
+
|
89
|
+
$.fn.scrollTo = function( target, duration, settings ){
|
90
|
+
if( typeof duration == 'object' ){
|
91
|
+
settings = duration;
|
92
|
+
duration = 0;
|
93
|
+
}
|
94
|
+
if( typeof settings == 'function' )
|
95
|
+
settings = { onAfter:settings };
|
96
|
+
|
97
|
+
if( target == 'max' )
|
98
|
+
target = 9e9;
|
99
|
+
|
100
|
+
settings = $.extend( {}, $scrollTo.defaults, settings );
|
101
|
+
// Speed is still recognized for backwards compatibility
|
102
|
+
duration = duration || settings.speed || settings.duration;
|
103
|
+
// Make sure the settings are given right
|
104
|
+
settings.queue = settings.queue && settings.axis.length > 1;
|
105
|
+
|
106
|
+
if( settings.queue )
|
107
|
+
// Let's keep the overall duration
|
108
|
+
duration /= 2;
|
109
|
+
settings.offset = both( settings.offset );
|
110
|
+
settings.over = both( settings.over );
|
111
|
+
|
112
|
+
return this.scrollable().each(function(){
|
113
|
+
var elem = this,
|
114
|
+
$elem = $(elem),
|
115
|
+
targ = target, toff, attr = {},
|
116
|
+
win = $elem.is('html,body');
|
117
|
+
|
118
|
+
switch( typeof targ ){
|
119
|
+
// A number will pass the regex
|
120
|
+
case 'number':
|
121
|
+
case 'string':
|
122
|
+
if( /^([+-]=)?\d+(\.\d+)?(px)?$/.test(targ) ){
|
123
|
+
targ = both( targ );
|
124
|
+
// We are done
|
125
|
+
break;
|
126
|
+
}
|
127
|
+
// Relative selector, no break!
|
128
|
+
targ = $(targ,this);
|
129
|
+
case 'object':
|
130
|
+
// DOMElement / jQuery
|
131
|
+
if( targ.is || targ.style )
|
132
|
+
// Get the real position of the target
|
133
|
+
toff = (targ = $(targ)).offset();
|
134
|
+
}
|
135
|
+
$.each( settings.axis.split(''), function( i, axis ){
|
136
|
+
var Pos = axis == 'x' ? 'Left' : 'Top',
|
137
|
+
pos = Pos.toLowerCase(),
|
138
|
+
key = 'scroll' + Pos,
|
139
|
+
old = elem[key],
|
140
|
+
Dim = axis == 'x' ? 'Width' : 'Height';
|
141
|
+
|
142
|
+
if( toff ){// jQuery / DOMElement
|
143
|
+
attr[key] = toff[pos] + ( win ? 0 : old - $elem.offset()[pos] );
|
144
|
+
|
145
|
+
// If it's a dom element, reduce the margin
|
146
|
+
if( settings.margin ){
|
147
|
+
attr[key] -= parseInt(targ.css('margin'+Pos)) || 0;
|
148
|
+
attr[key] -= parseInt(targ.css('border'+Pos+'Width')) || 0;
|
149
|
+
}
|
150
|
+
|
151
|
+
attr[key] += settings.offset[pos] || 0;
|
152
|
+
|
153
|
+
if( settings.over[pos] )
|
154
|
+
// Scroll to a fraction of its width/height
|
155
|
+
attr[key] += targ[Dim.toLowerCase()]() * settings.over[pos];
|
156
|
+
}else
|
157
|
+
attr[key] = targ[pos];
|
158
|
+
|
159
|
+
// Number or 'number'
|
160
|
+
if( /^\d+$/.test(attr[key]) )
|
161
|
+
// Check the limits
|
162
|
+
attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max(Dim) );
|
163
|
+
|
164
|
+
// Queueing axes
|
165
|
+
if( !i && settings.queue ){
|
166
|
+
// Don't waste time animating, if there's no need.
|
167
|
+
if( old != attr[key] )
|
168
|
+
// Intermediate animation
|
169
|
+
animate( settings.onAfterFirst );
|
170
|
+
// Don't animate this axis again in the next iteration.
|
171
|
+
delete attr[key];
|
172
|
+
}
|
173
|
+
});
|
174
|
+
|
175
|
+
animate( settings.onAfter );
|
176
|
+
|
177
|
+
function animate( callback ){
|
178
|
+
$elem.animate( attr, duration, settings.easing, callback && function(){
|
179
|
+
callback.call(this, target, settings);
|
180
|
+
});
|
181
|
+
};
|
182
|
+
|
183
|
+
// Max scrolling position, works on quirks mode
|
184
|
+
// It only fails (not too badly) on IE, quirks mode.
|
185
|
+
function max( Dim ){
|
186
|
+
var scroll = 'scroll'+Dim;
|
187
|
+
|
188
|
+
if( !win )
|
189
|
+
return elem[scroll];
|
190
|
+
|
191
|
+
var size = 'client' + Dim,
|
192
|
+
html = elem.ownerDocument.documentElement,
|
193
|
+
body = elem.ownerDocument.body;
|
194
|
+
|
195
|
+
return Math.max( html[scroll], body[scroll] )
|
196
|
+
- Math.min( html[size] , body[size] );
|
197
|
+
|
198
|
+
};
|
199
|
+
|
200
|
+
}).end();
|
201
|
+
};
|
202
|
+
|
203
|
+
function both( val ){
|
204
|
+
return typeof val == 'object' ? val : { top:val, left:val };
|
205
|
+
};
|
206
|
+
|
207
|
+
})( jQuery );
|
@@ -0,0 +1,480 @@
|
|
1
|
+
/*
|
2
|
+
* jQuery UI Multiselect
|
3
|
+
*
|
4
|
+
* Authors:
|
5
|
+
* Michael Aufreiter (quasipartikel.at)
|
6
|
+
* Yanick Rochon (yanick.rochon[at]gmail[dot]com)
|
7
|
+
*
|
8
|
+
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
9
|
+
* and GPL (GPL-LICENSE.txt) licenses.
|
10
|
+
*
|
11
|
+
* http://www.quasipartikel.at/multiselect/
|
12
|
+
*
|
13
|
+
*
|
14
|
+
* Depends:
|
15
|
+
* ui.core.js
|
16
|
+
* ui.sortable.js
|
17
|
+
*
|
18
|
+
* Optional:
|
19
|
+
* localization (http://plugins.jquery.com/project/localisation)
|
20
|
+
* scrollTo (http://plugins.jquery.com/project/ScrollTo)
|
21
|
+
*
|
22
|
+
* Todo:
|
23
|
+
* Make batch actions faster
|
24
|
+
* Implement dynamic insertion through remote calls
|
25
|
+
*/
|
26
|
+
|
27
|
+
|
28
|
+
(function($) {
|
29
|
+
|
30
|
+
$.widget("ui.multiselect", {
|
31
|
+
options: {
|
32
|
+
sortable: true,
|
33
|
+
dragToAdd: true,
|
34
|
+
searchable: true,
|
35
|
+
doubleClickable: true,
|
36
|
+
animated: 'fast',
|
37
|
+
show: 'slideDown',
|
38
|
+
hide: 'slideUp',
|
39
|
+
dividerLocation: 0.6,
|
40
|
+
selectedContainerOnLeft: true,
|
41
|
+
width: null,
|
42
|
+
height: null,
|
43
|
+
nodeComparator: function(node1,node2) {
|
44
|
+
var text1 = node1.text(),
|
45
|
+
text2 = node2.text();
|
46
|
+
return text1 == text2 ? 0 : (text1 < text2 ? -1 : 1);
|
47
|
+
},
|
48
|
+
includeRemoveAll: true,
|
49
|
+
includeAddAll: true,
|
50
|
+
pressEnterKeyToAddAll: false
|
51
|
+
},
|
52
|
+
_create: function() {
|
53
|
+
this.element.hide();
|
54
|
+
this.id = this.element.attr("id");
|
55
|
+
this.container = $('<div class="ui-multiselect ui-helper-clearfix ui-widget"></div>').insertAfter(this.element);
|
56
|
+
this.count = 0; // number of currently selected options
|
57
|
+
this.selectedContainer = $('<div class="selected"></div>');
|
58
|
+
if (this.options.selectedContainerOnLeft) {
|
59
|
+
this.selectedContainer.appendTo(this.container);
|
60
|
+
this.availableContainer = $('<div class="available"></div>').appendTo(this.container);
|
61
|
+
this.availableContainer.addClass('right-column');
|
62
|
+
}
|
63
|
+
else
|
64
|
+
{
|
65
|
+
this.availableContainer = $('<div class="available"></div>').appendTo(this.container);
|
66
|
+
this.selectedContainer.appendTo(this.container);
|
67
|
+
this.selectedContainer.addClass('right-column');
|
68
|
+
}
|
69
|
+
this.selectedActions = $('<div class="actions ui-widget-header ui-helper-clearfix"><span class="count">0 '+$.ui.multiselect.locale.itemsCount+'</span>'+(this.options.includeRemoveAll?'<a href="#" class="remove-all">'+$.ui.multiselect.locale.removeAll+'</a>':'<span class="remove-all"> </span>')+'</div>').appendTo(this.selectedContainer);
|
70
|
+
this.availableActions = $('<div class="actions ui-widget-header ui-helper-clearfix"><input type="text" class="search empty ui-widget-content ui-corner-all"/>'+(this.options.includeAddAll?'<a href="#" class="add-all">'+$.ui.multiselect.locale.addAll+'</a>':'<span class="add-all"> </span>')+'</div>').appendTo(this.availableContainer);
|
71
|
+
this.selectedList = $('<ul class="selected connected-list"><li class="ui-helper-hidden-accessible"></li></ul>').bind('selectstart', function(){return false;}).appendTo(this.selectedContainer);
|
72
|
+
this.availableList = $('<ul class="available connected-list"><li class="ui-helper-hidden-accessible"></li></ul>').bind('selectstart', function(){return false;}).appendTo(this.availableContainer);
|
73
|
+
|
74
|
+
var that = this;
|
75
|
+
|
76
|
+
var width = this.options.width;
|
77
|
+
if (!width) {
|
78
|
+
width = this.element.width();
|
79
|
+
}
|
80
|
+
var height = this.options.height;
|
81
|
+
if (!height) {
|
82
|
+
height = this.element.height();
|
83
|
+
}
|
84
|
+
|
85
|
+
// set dimensions
|
86
|
+
this.container.width(width-2);
|
87
|
+
if (this.options.selectedContainerOnLeft) {
|
88
|
+
this.selectedContainer.width(Math.floor(width*this.options.dividerLocation)-1);
|
89
|
+
this.availableContainer.width(Math.floor(width*(1-this.options.dividerLocation))-2);
|
90
|
+
}
|
91
|
+
else
|
92
|
+
{
|
93
|
+
this.selectedContainer.width(Math.floor(width*this.options.dividerLocation)-2);
|
94
|
+
this.availableContainer.width(Math.floor(width*(1-this.options.dividerLocation))-1);
|
95
|
+
}
|
96
|
+
|
97
|
+
// fix list height to match <option> depending on their individual header's heights
|
98
|
+
this.selectedList.height(Math.max(height-this.selectedActions.height(),1));
|
99
|
+
this.availableList.height(Math.max(height-this.availableActions.height(),1));
|
100
|
+
|
101
|
+
if ( !this.options.animated ) {
|
102
|
+
this.options.show = 'show';
|
103
|
+
this.options.hide = 'hide';
|
104
|
+
}
|
105
|
+
|
106
|
+
// init lists
|
107
|
+
this._populateLists(this.element.find('option'));
|
108
|
+
|
109
|
+
// make selection sortable
|
110
|
+
if (this.options.sortable) {
|
111
|
+
this.selectedList.sortable({
|
112
|
+
placeholder: 'ui-state-highlight',
|
113
|
+
axis: 'y',
|
114
|
+
update: function(event, ui) {
|
115
|
+
// apply the new sort order to the original selectbox
|
116
|
+
that.selectedList.find('li').each(function() {
|
117
|
+
if ($(this).data('optionLink'))
|
118
|
+
$(this).data('optionLink').remove().appendTo(that.element);
|
119
|
+
});
|
120
|
+
},
|
121
|
+
beforeStop: function (event, ui) {
|
122
|
+
// This lets us recognize which item was just added to
|
123
|
+
// the list in receive, per the workaround for not being
|
124
|
+
// able to reference the new element.
|
125
|
+
ui.item.addClass('dropped');
|
126
|
+
},
|
127
|
+
receive: function(event, ui) {
|
128
|
+
ui.item.data('optionLink').attr('selected', true);
|
129
|
+
// increment count
|
130
|
+
that.count += 1;
|
131
|
+
that._updateCount();
|
132
|
+
// workaround, because there's no way to reference
|
133
|
+
// the new element, see http://dev.jqueryui.com/ticket/4303
|
134
|
+
that.selectedList.children('.dropped').each(function() {
|
135
|
+
$(this).removeClass('dropped');
|
136
|
+
$(this).data('optionLink', ui.item.data('optionLink'));
|
137
|
+
$(this).data('idx', ui.item.data('idx'));
|
138
|
+
that._applyItemState($(this), true);
|
139
|
+
});
|
140
|
+
|
141
|
+
// workaround according to http://dev.jqueryui.com/ticket/4088
|
142
|
+
setTimeout(function() { ui.item.remove(); }, 1);
|
143
|
+
},
|
144
|
+
stop: function (event, ui) { that.element.change(); }
|
145
|
+
});
|
146
|
+
}
|
147
|
+
|
148
|
+
// set up livesearch
|
149
|
+
if (this.options.searchable) {
|
150
|
+
this._registerSearchEvents(this.availableContainer.find('input.search'));
|
151
|
+
} else {
|
152
|
+
$('.search').hide();
|
153
|
+
}
|
154
|
+
|
155
|
+
// batch actions
|
156
|
+
this.container.find(".remove-all").click(function() {
|
157
|
+
that._populateLists(that.element.find('option').removeAttr('selected'));
|
158
|
+
that.element.trigger('change');
|
159
|
+
return false;
|
160
|
+
});
|
161
|
+
|
162
|
+
this.container.find(".add-all").click(function() {
|
163
|
+
var options = that.element.find('option').not(":selected");
|
164
|
+
if (that.availableList.children('li:hidden').length > 1) {
|
165
|
+
that.availableList.children('li').each(function(i) {
|
166
|
+
if ($(this).is(":visible")) $(options[i-1]).attr('selected', 'selected');
|
167
|
+
});
|
168
|
+
} else {
|
169
|
+
options.attr('selected', 'selected');
|
170
|
+
}
|
171
|
+
that._populateLists(that.element.find('option'));
|
172
|
+
that.element.trigger('change');
|
173
|
+
if (that.options.pressEnterKeyToAddAll) {
|
174
|
+
//clear input after add all
|
175
|
+
$('input.search').val("");
|
176
|
+
}
|
177
|
+
|
178
|
+
return false;
|
179
|
+
});
|
180
|
+
},
|
181
|
+
destroy: function() {
|
182
|
+
this.element.show();
|
183
|
+
this.container.remove();
|
184
|
+
|
185
|
+
$.Widget.prototype.destroy.apply(this, arguments);
|
186
|
+
},
|
187
|
+
addOption: function(option) {
|
188
|
+
// Append the option
|
189
|
+
option = $(option);
|
190
|
+
var select = this.element;
|
191
|
+
select.append(option);
|
192
|
+
|
193
|
+
var item = this._getOptionNode(option).appendTo(option.attr('selected') ? this.selectedList : this.availableList).show();
|
194
|
+
|
195
|
+
if (option.attr('selected')) {
|
196
|
+
this.count += 1;
|
197
|
+
}
|
198
|
+
this._applyItemState(item, option.attr('selected'));
|
199
|
+
item.data('idx', this.count);
|
200
|
+
|
201
|
+
// update count
|
202
|
+
this._updateCount();
|
203
|
+
this._filter.apply(this.availableContainer.find('input.search'), [this.availableList]);
|
204
|
+
},
|
205
|
+
// Redisplay the lists of selected/available options.
|
206
|
+
// Call this after you've selected/unselected some options programmatically.
|
207
|
+
// GRIPE This is O(n) where n is the length of the list - seems like
|
208
|
+
// there must be a smarter way of doing this, but I have not been able
|
209
|
+
// to come up with one. I see no way to detect programmatic setting of
|
210
|
+
// the option's selected property, and without that, it seems like we
|
211
|
+
// can't have a general-case listener that does its thing every time an
|
212
|
+
// option is selected.
|
213
|
+
refresh: function() {
|
214
|
+
// Redisplay our lists.
|
215
|
+
this._populateLists(this.element.find('option'));
|
216
|
+
},
|
217
|
+
_populateLists: function(options) {
|
218
|
+
this.selectedList.children('.ui-element').remove();
|
219
|
+
this.availableList.children('.ui-element').remove();
|
220
|
+
this.count = 0;
|
221
|
+
|
222
|
+
var that = this;
|
223
|
+
var groups = $(this.element).find("optgroup").map(function(i) {
|
224
|
+
return that._getOptionGroup($(this));
|
225
|
+
});
|
226
|
+
groups.appendTo(this.selectedList.add(this.availableList));
|
227
|
+
|
228
|
+
var items = $(options.map(function(i) {
|
229
|
+
var item = that._getOptionNode(this).appendTo(that._getOptionList(this)).show();
|
230
|
+
|
231
|
+
if (this.selected) that.count += 1;
|
232
|
+
that._applyItemState(item, this.selected);
|
233
|
+
item.data('idx', i);
|
234
|
+
return item[0];
|
235
|
+
}));
|
236
|
+
|
237
|
+
// update count
|
238
|
+
this._updateCount();
|
239
|
+
that._filter.apply(this.availableContainer.find('input.search'), [that.availableList]);
|
240
|
+
},
|
241
|
+
_getOptionList: function(option) {
|
242
|
+
var selected = option.selected;
|
243
|
+
option = $(option);
|
244
|
+
var $list = selected ? this.selectedList : this.availableList;
|
245
|
+
var $group = option.closest("optgroup");
|
246
|
+
if ($group.length === 0) {
|
247
|
+
return $list;
|
248
|
+
} else {
|
249
|
+
var $groupList = $list.find("ul[title='" + $group.attr("label") + "']");
|
250
|
+
if ($groupList.length === 0) {
|
251
|
+
$groupList = $("<ul class='ui-state-default ui-element available' title='" + $group.attr("label") + "'>" + $group.attr("label") + "</ul>").appendTo($list);
|
252
|
+
}
|
253
|
+
$groupList.show();
|
254
|
+
return $groupList;
|
255
|
+
}
|
256
|
+
},
|
257
|
+
_getOptionGroup : function(optgroup) {
|
258
|
+
var groupNode = $("<ul class='ui-state-default ui-element available' title='" + optgroup.attr("label") + "'>" + optgroup.attr("label") + "</ul>").hide();
|
259
|
+
return groupNode[0];
|
260
|
+
},
|
261
|
+
_updateCount: function() {
|
262
|
+
this.selectedContainer.find('span.count').text(this.count+" "+$.ui.multiselect.locale.itemsCount);
|
263
|
+
},
|
264
|
+
_getOptionNode: function(option) {
|
265
|
+
option = $(option);
|
266
|
+
var node = $('<li class="ui-state-default ui-element" title="'+option.text()+'"><span class="ui-icon"/>'+option.text()+'<a href="#" class="action"><span class="ui-corner-all ui-icon"/></a></li>').hide();
|
267
|
+
node.data('optionLink', option);
|
268
|
+
return node;
|
269
|
+
},
|
270
|
+
// clones an item with associated data
|
271
|
+
// didn't find a smarter away around this
|
272
|
+
_cloneWithData: function(clonee) {
|
273
|
+
var clone = clonee.clone(false,false);
|
274
|
+
clone.data('optionLink', clonee.data('optionLink'));
|
275
|
+
clone.data('idx', clonee.data('idx'));
|
276
|
+
return clone;
|
277
|
+
},
|
278
|
+
_setSelected: function(item, selected) {
|
279
|
+
var temp = item.data('optionLink').attr('selected', selected);
|
280
|
+
var parent = temp.parent();
|
281
|
+
temp.detach().appendTo(parent);
|
282
|
+
this.element.trigger('change');
|
283
|
+
|
284
|
+
if (selected) {
|
285
|
+
var selectedItem = this._cloneWithData(item);
|
286
|
+
item[this.options.hide](this.options.animated, function() {
|
287
|
+
if (item.siblings().length === 0) {
|
288
|
+
item.closest("ul[title]").hide();
|
289
|
+
}
|
290
|
+
$(this).remove();
|
291
|
+
});
|
292
|
+
// get group to add it to...
|
293
|
+
var $list = this._getOptionList(selectedItem.data("optionLink")[0]);
|
294
|
+
selectedItem.appendTo($list).hide()[this.options.show](this.options.animated);
|
295
|
+
|
296
|
+
this._applyItemState(selectedItem, true);
|
297
|
+
return selectedItem;
|
298
|
+
} else {
|
299
|
+
|
300
|
+
// look for successor based on initial option index
|
301
|
+
var items = this.availableList.find('li'), comparator = this.options.nodeComparator;
|
302
|
+
var succ = null, i = item.data('idx'), direction = comparator(item, $(items[i]));
|
303
|
+
|
304
|
+
// TODO: test needed for dynamic list populating
|
305
|
+
if ( direction ) {
|
306
|
+
while (i>=0 && i<items.length) {
|
307
|
+
direction > 0 ? i++ : i--;
|
308
|
+
if ( direction != comparator(item, $(items[i])) ) {
|
309
|
+
// going up, go back one item down, otherwise leave as is
|
310
|
+
succ = items[direction > 0 ? i : i+1];
|
311
|
+
var group1 = item.closest("ul[title]"),
|
312
|
+
group2 = $(succ).closest("ul[title]");
|
313
|
+
if (group1.length !== 0 && group2.length !== 0) {
|
314
|
+
if (group1.attr("title") !== group2.attr("title")) {
|
315
|
+
succ = null;
|
316
|
+
}
|
317
|
+
}
|
318
|
+
break;
|
319
|
+
}
|
320
|
+
}
|
321
|
+
} else {
|
322
|
+
succ = items[i];
|
323
|
+
}
|
324
|
+
|
325
|
+
var availableItem = this._cloneWithData(item);
|
326
|
+
var $list = this._getOptionList(availableItem.data("optionLink")[0]);
|
327
|
+
succ ? availableItem.insertBefore($(succ)) : availableItem.appendTo($list);
|
328
|
+
item[this.options.hide](this.options.animated, function() {
|
329
|
+
if (item.siblings().length === 0) {
|
330
|
+
item.closest("ul[title]").hide();
|
331
|
+
}
|
332
|
+
$(this).remove();
|
333
|
+
});
|
334
|
+
availableItem.hide()[this.options.show](this.options.animated);
|
335
|
+
|
336
|
+
this._applyItemState(availableItem, false);
|
337
|
+
return availableItem;
|
338
|
+
}
|
339
|
+
},
|
340
|
+
_applyItemState: function(item, selected) {
|
341
|
+
if (selected) {
|
342
|
+
if (this.options.sortable)
|
343
|
+
item.children('span').addClass('ui-icon-arrowthick-2-n-s').removeClass('ui-helper-hidden').addClass('ui-icon');
|
344
|
+
else
|
345
|
+
item.children('span').removeClass('ui-icon-arrowthick-2-n-s').addClass('ui-helper-hidden').removeClass('ui-icon');
|
346
|
+
item.find('a.action span').addClass('ui-icon-minus').removeClass('ui-icon-plus');
|
347
|
+
this._registerRemoveEvents(item.find('a.action'));
|
348
|
+
|
349
|
+
} else {
|
350
|
+
item.children('span').removeClass('ui-icon-arrowthick-2-n-s').addClass('ui-helper-hidden').removeClass('ui-icon');
|
351
|
+
item.find('a.action span').addClass('ui-icon-plus').removeClass('ui-icon-minus');
|
352
|
+
this._registerAddEvents(item.find('a.action'));
|
353
|
+
}
|
354
|
+
|
355
|
+
this._registerDoubleClickEvents(item);
|
356
|
+
this._registerHoverEvents(item);
|
357
|
+
},
|
358
|
+
// taken from John Resig's liveUpdate script
|
359
|
+
_filter: function(list) {
|
360
|
+
var input = $(this);
|
361
|
+
var rows = list.find('li'),
|
362
|
+
cache = rows.map(function(){
|
363
|
+
|
364
|
+
return $(this).text().toLowerCase();
|
365
|
+
});
|
366
|
+
|
367
|
+
var term = $.trim(input.val().toLowerCase()), scores = [];
|
368
|
+
|
369
|
+
if (!term) {
|
370
|
+
rows.show();
|
371
|
+
} else {
|
372
|
+
rows.hide();
|
373
|
+
|
374
|
+
cache.each(function(i) {
|
375
|
+
if (this.indexOf(term)>-1) { scores.push(i); }
|
376
|
+
});
|
377
|
+
|
378
|
+
$.each(scores, function() {
|
379
|
+
$(rows[this]).show();
|
380
|
+
});
|
381
|
+
}
|
382
|
+
},
|
383
|
+
_registerDoubleClickEvents: function(elements) {
|
384
|
+
if (!this.options.doubleClickable) return;
|
385
|
+
elements.dblclick(function() {
|
386
|
+
elements.find('a.action').click();
|
387
|
+
});
|
388
|
+
},
|
389
|
+
_registerHoverEvents: function(elements) {
|
390
|
+
elements.removeClass('ui-state-hover');
|
391
|
+
elements.mouseover(function() {
|
392
|
+
$(this).addClass('ui-state-hover');
|
393
|
+
});
|
394
|
+
elements.mouseout(function() {
|
395
|
+
$(this).removeClass('ui-state-hover');
|
396
|
+
});
|
397
|
+
},
|
398
|
+
_registerAddEvents: function(elements) {
|
399
|
+
var that = this;
|
400
|
+
elements.click(function() {
|
401
|
+
var item = that._setSelected($(this).parent(), true);
|
402
|
+
that.count += 1;
|
403
|
+
that._updateCount();
|
404
|
+
|
405
|
+
// Prevent extra clicks from triggering bogus add events, if a user
|
406
|
+
// tries clicking during the removal process.
|
407
|
+
$(this).unbind('click');
|
408
|
+
|
409
|
+
return false;
|
410
|
+
});
|
411
|
+
|
412
|
+
// make draggable
|
413
|
+
if (this.options.sortable && this.options.dragToAdd) {
|
414
|
+
elements.each(function() {
|
415
|
+
$(this).parent().draggable({
|
416
|
+
connectToSortable: that.selectedList,
|
417
|
+
helper: function() {
|
418
|
+
var selectedItem = that._cloneWithData($(this)).width($(this).width() - 50);
|
419
|
+
selectedItem.width($(this).width());
|
420
|
+
return selectedItem;
|
421
|
+
},
|
422
|
+
appendTo: that.container,
|
423
|
+
containment: that.container,
|
424
|
+
revert: 'invalid'
|
425
|
+
});
|
426
|
+
});
|
427
|
+
}
|
428
|
+
},
|
429
|
+
_registerRemoveEvents: function(elements) {
|
430
|
+
var that = this;
|
431
|
+
elements.click(function() {
|
432
|
+
that._setSelected($(this).parent(), false);
|
433
|
+
that.count -= 1;
|
434
|
+
that._updateCount();
|
435
|
+
|
436
|
+
// Prevent extra clicks from triggering bogus remove events, if a
|
437
|
+
// user tries clicking during the removal process.
|
438
|
+
$(this).unbind('click');
|
439
|
+
|
440
|
+
return false;
|
441
|
+
});
|
442
|
+
},
|
443
|
+
_registerSearchEvents: function(input) {
|
444
|
+
var that = this;
|
445
|
+
|
446
|
+
input.focus(function() {
|
447
|
+
$(this).addClass('ui-state-active');
|
448
|
+
})
|
449
|
+
.blur(function() {
|
450
|
+
$(this).removeClass('ui-state-active');
|
451
|
+
})
|
452
|
+
.keypress(function(e) {
|
453
|
+
if (e.keyCode == 13) {
|
454
|
+
if (that.options.pressEnterKeyToAddAll) {
|
455
|
+
//on Enter, if a filter is present add all, then clear the input
|
456
|
+
var str = $('input.search').val();
|
457
|
+
if (str !== undefined && str !== null && str !== "") {
|
458
|
+
$('a.add-all').click();
|
459
|
+
$('input.search').val("");
|
460
|
+
}
|
461
|
+
}
|
462
|
+
return false;
|
463
|
+
}
|
464
|
+
})
|
465
|
+
.keyup(function() {
|
466
|
+
that._filter.apply(this, [that.availableList]);
|
467
|
+
});
|
468
|
+
}
|
469
|
+
});
|
470
|
+
|
471
|
+
$.extend($.ui.multiselect, {
|
472
|
+
locale: {
|
473
|
+
addAll:'Add all',
|
474
|
+
removeAll:'Remove all',
|
475
|
+
itemsCount:'items selected'
|
476
|
+
}
|
477
|
+
});
|
478
|
+
|
479
|
+
|
480
|
+
})(jQuery);
|
@@ -0,0 +1,31 @@
|
|
1
|
+
/* Multiselect
|
2
|
+
----------------------------------*/
|
3
|
+
|
4
|
+
.ui-multiselect { border: solid 1px; font-size: 0.8em; }
|
5
|
+
.ui-multiselect ul { -moz-user-select: none; }
|
6
|
+
.ui-multiselect li { margin: 0; padding: 0; cursor: default; line-height: 20px; height: 20px; font-size: 11px; list-style: none; padding-right: 18px; overflow: hidden; word-wrap: break-word; }
|
7
|
+
.ui-multiselect li a { color: #999; text-decoration: none; padding: 0; display: block; float: left; cursor: pointer;}
|
8
|
+
.ui-multiselect li.ui-draggable-dragging { padding-left: 10px; }
|
9
|
+
|
10
|
+
.ui-multiselect div.selected { position: relative; padding: 0; margin: 0; border: 0; float:left; }
|
11
|
+
.ui-multiselect ul.selected { position: relative; padding: 0; overflow: auto; overflow-x: hidden; background: #fff; margin: 0; list-style: none; border: 0; position: relative; width: 100%; }
|
12
|
+
|
13
|
+
.ui-multiselect div.available { position: relative; padding: 0; margin: 0; border: 0; float:left; }
|
14
|
+
.ui-multiselect ul.available { position: relative; padding: 0; overflow: auto; overflow-x: hidden; background: #fff; margin: 0; list-style: none; border: 0; width: 100%; }
|
15
|
+
.ui-multiselect ul.available li { padding-left: 10px; }
|
16
|
+
|
17
|
+
.ui-multiselect div.right-column { border-left: 1px solid; }
|
18
|
+
|
19
|
+
.ui-multiselect .ui-state-default { border: none; margin-bottom: 1px; position: relative; padding-left: 20px;}
|
20
|
+
.ui-multiselect .ui-state-hover { border: none; }
|
21
|
+
.ui-multiselect .ui-widget-header {border: none; font-size: 11px; margin-bottom: 1px;}
|
22
|
+
|
23
|
+
.ui-multiselect .add-all { float: right; padding: 7px;}
|
24
|
+
.ui-multiselect .remove-all { float: right; padding: 7px;}
|
25
|
+
.ui-multiselect .search { float: left; padding: 4px;}
|
26
|
+
.ui-multiselect .count { float: left; padding: 7px;}
|
27
|
+
|
28
|
+
.ui-multiselect li span.ui-icon-arrowthick-2-n-s { position: absolute; left: 2px; }
|
29
|
+
.ui-multiselect li a.action { position: absolute; right: 2px; top: 2px; }
|
30
|
+
|
31
|
+
.ui-multiselect input.search { height: 14px; padding: 1px; opacity: 0.5; margin: 4px; width: 100px; }
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: multiselectjs_rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Scott M Parrish
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-02 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: railties
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '3.1'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '3.1'
|
46
|
+
description: ! 'A Rails 3.1 Engine to include javascritp and css files from https://github.com/crdeutsch/multiselect '
|
47
|
+
email:
|
48
|
+
- anithri@gmail.com
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- lib/multiselectjs_rails/version.rb
|
54
|
+
- lib/multiselectjs_rails.rb
|
55
|
+
- vendor/assets/stylesheets/ui.multiselect.css
|
56
|
+
- vendor/assets/javascripts/ui.multiselect.js
|
57
|
+
- vendor/assets/javascripts/locale/ui-multiselect-fr.js
|
58
|
+
- vendor/assets/javascripts/locale/ui-multiselect-de.js
|
59
|
+
- vendor/assets/javascripts/locale/ui-multiselect-en.js
|
60
|
+
- vendor/assets/javascripts/locale/ui-multiselect-es.js
|
61
|
+
- vendor/assets/javascripts/locale/ui-multiselect-it.js
|
62
|
+
- vendor/assets/javascripts/plugins/scrollTo/jquery.scrollTo-min.js
|
63
|
+
- vendor/assets/javascripts/plugins/scrollTo/README.txt
|
64
|
+
- vendor/assets/javascripts/plugins/scrollTo/jquery.scrollTo.js
|
65
|
+
- vendor/assets/javascripts/plugins/scrollTo/changes.txt
|
66
|
+
- vendor/assets/javascripts/plugins/localisation/jquery.localisation.js
|
67
|
+
- vendor/assets/javascripts/plugins/localisation/jquery.localisation-pack.js
|
68
|
+
- vendor/assets/javascripts/plugins/localisation/jquery.localisation-min.js
|
69
|
+
- MIT-LICENSE.txt
|
70
|
+
- README.md
|
71
|
+
homepage: https://github.com/anithri/multiselectjs_rails
|
72
|
+
licenses: []
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
segments:
|
84
|
+
- 0
|
85
|
+
hash: 368088046168383247
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ! '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
segments:
|
93
|
+
- 0
|
94
|
+
hash: 368088046168383247
|
95
|
+
requirements: []
|
96
|
+
rubyforge_project: multiselectjs_rails
|
97
|
+
rubygems_version: 1.8.21
|
98
|
+
signing_key:
|
99
|
+
specification_version: 3
|
100
|
+
summary: A Rails Engine for vendor/assets of multiselect javascript library"
|
101
|
+
test_files: []
|