Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F5962409
ui.multiselect.js
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
ui.multiselect.js
View Options
/*
* jQuery UI Multiselect
*
* Authors:
* Michael Aufreiter (quasipartikel.at)
* Yanick Rochon (yanick.rochon[at]gmail[dot]com)
*
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://www.quasipartikel.at/multiselect/
*
*
* Depends:
* ui.core.js
* ui.sortable.js
* ui.draggable.js
*
* Optional:
* localization (http://plugins.jquery.com/project/localisation)
* scrollTo (http://plugins.jquery.com/project/ScrollTo)
*
* Todo:
* Make batch actions faster
* Implement dynamic insertion through remote calls
*/
(
function
(
$
,
mw
)
{
$
.
widget
(
"ui.multiselect"
,
{
options
:
{
sortable
:
true
,
searchable
:
true
,
doubleClickable
:
true
,
animated
:
'fast'
,
show
:
'slideDown'
,
hide
:
'slideUp'
,
dividerLocation
:
0.6
,
availableFirst
:
false
,
nodeComparator
:
function
(
node1
,
node2
)
{
var
text1
=
node1
.
text
(),
text2
=
node2
.
text
();
return
text1
===
text2
?
0
:
(
text1
<
text2
?
-
1
:
1
);
}
},
_create
:
function
()
{
var
countStr
=
mw
.
message
(
'centralnotice-items-selected'
,
0
).
escaped
(),
that
;
this
.
element
.
hide
();
this
.
id
=
this
.
element
.
attr
(
"id"
);
this
.
container
=
$
(
'<div class="ui-multiselect ui-helper-clearfix ui-widget"></div>'
).
insertAfter
(
this
.
element
);
this
.
count
=
0
;
// number of currently selected options
this
.
selectedContainer
=
$
(
'<div class="selected"></div>'
).
appendTo
(
this
.
container
);
this
.
availableContainer
=
$
(
'<div class="available"></div>'
)[
this
.
options
.
availableFirst
?
'prependTo'
:
'appendTo'
](
this
.
container
);
this
.
selectedActions
=
$
(
'<div class="actions ui-widget-header ui-helper-clearfix"><span class="count">'
+
countStr
+
'</span><a href="#" class="remove-all">'
+
mw
.
message
(
'centralnotice-remove-all'
).
escaped
()
+
'</a></div>'
).
appendTo
(
this
.
selectedContainer
);
this
.
availableActions
=
$
(
'<div class="actions ui-widget-header ui-helper-clearfix"><input type="text" class="search empty ui-widget-content ui-corner-all"></input><a href="#" class="add-all">'
+
mw
.
message
(
'centralnotice-select-all'
).
escaped
()
+
'</a></div>'
).
appendTo
(
this
.
availableContainer
);
this
.
selectedList
=
$
(
'<ul class="selected connected-list"><li class="ui-helper-hidden-accessible"></li></ul>'
).
bind
(
'selectstart'
,
function
(){
return
false
;}).
appendTo
(
this
.
selectedContainer
);
this
.
availableList
=
$
(
'<ul class="available connected-list"><li class="ui-helper-hidden-accessible"></li></ul>'
).
bind
(
'selectstart'
,
function
(){
return
false
;}).
appendTo
(
this
.
availableContainer
);
that
=
this
;
// set dimensions
this
.
container
.
width
(
this
.
element
.
width
()
+
1
);
this
.
selectedContainer
.
width
(
Math
.
floor
(
this
.
element
.
width
()
*
this
.
options
.
dividerLocation
));
this
.
availableContainer
.
width
(
Math
.
floor
(
this
.
element
.
width
()
*
(
1
-
this
.
options
.
dividerLocation
)));
// fix list height to match <option> depending on their individual header's heights
this
.
selectedList
.
height
(
Math
.
max
(
this
.
element
.
height
()
-
this
.
selectedActions
.
height
(),
1
));
this
.
availableList
.
height
(
Math
.
max
(
this
.
element
.
height
()
-
this
.
availableActions
.
height
(),
1
));
if
(
!
this
.
options
.
animated
)
{
this
.
options
.
show
=
'show'
;
this
.
options
.
hide
=
'hide'
;
}
// init lists
this
.
_populateLists
(
this
.
element
.
find
(
'option'
));
// make selection sortable
if
(
this
.
options
.
sortable
)
{
this
.
selectedList
.
sortable
({
placeholder
:
'ui-state-highlight'
,
axis
:
'y'
,
update
:
function
()
{
// apply the new sort order to the original selectbox
that
.
selectedList
.
find
(
'li'
).
each
(
function
()
{
if
(
$
(
this
).
data
(
'optionLink'
))
{
$
(
this
).
data
(
'optionLink'
).
remove
().
appendTo
(
that
.
element
);
}
});
},
receive
:
function
(
event
,
ui
)
{
ui
.
item
.
data
(
'optionLink'
).
prop
(
'selected'
,
true
);
// increment count
that
.
count
+=
1
;
that
.
_updateCount
();
// workaround, because there's no way to reference
// the new element, see http://dev.jqueryui.com/ticket/4303
that
.
selectedList
.
children
(
'.ui-draggable'
).
each
(
function
()
{
$
(
this
).
removeClass
(
'ui-draggable'
);
$
(
this
).
data
(
'optionLink'
,
ui
.
item
.
data
(
'optionLink'
));
$
(
this
).
data
(
'idx'
,
ui
.
item
.
data
(
'idx'
));
that
.
_applyItemState
(
$
(
this
),
true
);
});
// workaround according to http://dev.jqueryui.com/ticket/4088
setTimeout
(
function
()
{
ui
.
item
.
remove
();
},
1
);
}
});
}
// set up livesearch
if
(
this
.
options
.
searchable
)
{
this
.
_registerSearchEvents
(
this
.
availableContainer
.
find
(
'input.search'
));
}
else
{
$
(
'.search'
).
hide
();
}
// batch actions
this
.
container
.
find
(
".remove-all"
).
click
(
function
()
{
that
.
_populateLists
(
that
.
element
.
find
(
'option'
).
prop
(
'selected'
,
false
));
return
false
;
});
this
.
container
.
find
(
".add-all"
).
click
(
function
()
{
var
options
=
that
.
element
.
find
(
'option'
).
not
(
":selected"
);
if
(
that
.
availableList
.
children
(
'li:hidden'
).
length
>
1
)
{
that
.
availableList
.
children
(
'li'
).
each
(
function
(
i
)
{
if
(
$
(
this
).
is
(
":visible"
))
$
(
options
[
i
-
1
]).
prop
(
'selected'
,
true
);
});
}
else
{
options
.
prop
(
'selected'
,
true
);
}
that
.
_populateLists
(
that
.
element
.
find
(
'option'
));
return
false
;
});
},
destroy
:
function
()
{
this
.
element
.
show
();
this
.
container
.
remove
();
$
.
Widget
.
prototype
.
destroy
.
apply
(
this
,
arguments
);
},
_populateLists
:
function
(
options
)
{
this
.
selectedList
.
children
(
'.ui-element'
).
remove
();
this
.
availableList
.
children
(
'.ui-element'
).
remove
();
this
.
count
=
0
;
var
that
=
this
;
$
(
options
.
map
(
function
(
i
)
{
var
item
=
that
.
_getOptionNode
(
this
).
appendTo
(
this
.
selected
?
that
.
selectedList
:
that
.
availableList
).
show
();
if
(
this
.
selected
)
that
.
count
+=
1
;
that
.
_applyItemState
(
item
,
this
.
selected
);
item
.
data
(
'idx'
,
i
);
return
item
[
0
];
}));
// update count
this
.
_updateCount
();
that
.
_filter
.
apply
(
this
.
availableContainer
.
find
(
'input.search'
),
[
that
.
availableList
]);
},
_updateCount
:
function
()
{
this
.
element
.
trigger
(
'change'
);
this
.
selectedContainer
.
find
(
'span.count'
).
text
(
mw
.
message
(
'centralnotice-items-selected'
,
this
.
count
));
},
_getOptionNode
:
function
(
option
)
{
option
=
$
(
option
);
var
node
=
$
(
'<li class="ui-state-default ui-element" title="'
+
option
.
text
()
+
'"><span class="ui-icon"></span>'
+
option
.
text
()
+
'<a href="#" class="action"><span class="ui-corner-all ui-icon"></span></a></li>'
).
hide
();
node
.
data
(
'optionLink'
,
option
);
return
node
;
},
// clones an item with associated data
// didn't find a smarter away around this
_cloneWithData
:
function
(
clonee
)
{
var
clone
=
clonee
.
clone
(
false
,
false
);
clone
.
data
(
'optionLink'
,
clonee
.
data
(
'optionLink'
));
clone
.
data
(
'idx'
,
clonee
.
data
(
'idx'
));
return
clone
;
},
_setSelected
:
function
(
item
,
selected
)
{
item
.
data
(
'optionLink'
).
prop
(
'selected'
,
selected
);
if
(
selected
)
{
var
selectedItem
=
this
.
_cloneWithData
(
item
);
item
[
this
.
options
.
hide
](
this
.
options
.
animated
,
function
()
{
$
(
this
).
remove
();
});
selectedItem
.
appendTo
(
this
.
selectedList
).
hide
()[
this
.
options
.
show
](
this
.
options
.
animated
);
this
.
_applyItemState
(
selectedItem
,
true
);
return
selectedItem
;
}
else
{
// look for successor based on initial option index
var
items
=
this
.
availableList
.
find
(
'li'
),
comparator
=
this
.
options
.
nodeComparator
;
var
succ
=
null
,
i
=
item
.
data
(
'idx'
),
direction
=
comparator
(
item
,
$
(
items
[
i
]));
// TODO: test needed for dynamic list populating
if
(
direction
)
{
while
(
i
>=
0
&&
i
<
items
.
length
)
{
i
+=
(
direction
>
0
)
?
1
:
-
1
;
if
(
direction
!=
comparator
(
item
,
$
(
items
[
i
]))
)
{
// going up, go back one item down, otherwise leave as is
succ
=
items
[
direction
>
0
?
i
:
i
+
1
];
break
;
}
}
}
else
{
succ
=
items
[
i
];
}
var
availableItem
=
this
.
_cloneWithData
(
item
);
if
(
succ
)
{
availableItem
.
insertBefore
(
$
(
succ
));
}
else
{
availableItem
.
appendTo
(
this
.
availableList
);
}
item
[
this
.
options
.
hide
](
this
.
options
.
animated
,
function
()
{
$
(
this
).
remove
();
});
availableItem
.
hide
()[
this
.
options
.
show
](
this
.
options
.
animated
);
this
.
_applyItemState
(
availableItem
,
false
);
return
availableItem
;
}
},
_applyItemState
:
function
(
item
,
selected
)
{
if
(
selected
)
{
if
(
this
.
options
.
sortable
)
item
.
children
(
'span'
).
addClass
(
'ui-icon-arrowthick-2-n-s'
).
removeClass
(
'ui-helper-hidden'
).
addClass
(
'ui-icon'
);
else
item
.
children
(
'span'
).
removeClass
(
'ui-icon-arrowthick-2-n-s'
).
addClass
(
'ui-helper-hidden'
).
removeClass
(
'ui-icon'
);
item
.
find
(
'a.action span'
).
addClass
(
'ui-icon-minus'
).
removeClass
(
'ui-icon-plus'
);
this
.
_registerRemoveEvents
(
item
.
find
(
'a.action'
));
}
else
{
item
.
children
(
'span'
).
removeClass
(
'ui-icon-arrowthick-2-n-s'
).
addClass
(
'ui-helper-hidden'
).
removeClass
(
'ui-icon'
);
item
.
find
(
'a.action span'
).
addClass
(
'ui-icon-plus'
).
removeClass
(
'ui-icon-minus'
);
this
.
_registerAddEvents
(
item
.
find
(
'a.action'
));
}
this
.
_registerDoubleClickEvents
(
item
);
this
.
_registerHoverEvents
(
item
);
},
// taken from John Resig's liveUpdate script
_filter
:
function
(
list
)
{
var
input
=
$
(
this
);
var
rows
=
list
.
children
(
'li'
),
cache
=
rows
.
map
(
function
(){
return
$
(
this
).
text
().
toLowerCase
();
});
var
term
=
$
.
trim
(
input
.
val
().
toLowerCase
()),
scores
=
[];
if
(
!
term
)
{
rows
.
show
();
}
else
{
rows
.
hide
();
cache
.
each
(
function
(
i
)
{
if
(
this
.
indexOf
(
term
)
>-
1
)
{
scores
.
push
(
i
);
}
});
$
.
each
(
scores
,
function
()
{
$
(
rows
[
this
]).
show
();
});
}
},
_registerDoubleClickEvents
:
function
(
elements
)
{
if
(
!
this
.
options
.
doubleClickable
)
return
;
elements
.
dblclick
(
function
(
ev
)
{
if
(
$
(
ev
.
target
).
closest
(
'.action'
).
length
===
0
)
{
// This may be triggered with rapid clicks on actions as well. In that
// case don't trigger an additional click.
elements
.
find
(
'a.action'
).
click
();
}
});
},
_registerHoverEvents
:
function
(
elements
)
{
elements
.
removeClass
(
'ui-state-hover'
);
elements
.
mouseover
(
function
()
{
$
(
this
).
addClass
(
'ui-state-hover'
);
});
elements
.
mouseout
(
function
()
{
$
(
this
).
removeClass
(
'ui-state-hover'
);
});
},
_registerAddEvents
:
function
(
elements
)
{
var
that
=
this
;
elements
.
click
(
function
()
{
that
.
_setSelected
(
$
(
this
).
parent
(),
true
);
that
.
count
+=
1
;
that
.
_updateCount
();
return
false
;
});
// make draggable
if
(
this
.
options
.
sortable
)
{
elements
.
each
(
function
()
{
$
(
this
).
parent
().
draggable
({
connectToSortable
:
that
.
selectedList
,
helper
:
function
()
{
var
selectedItem
=
that
.
_cloneWithData
(
$
(
this
)).
width
(
$
(
this
).
width
()
-
50
);
selectedItem
.
width
(
$
(
this
).
width
());
return
selectedItem
;
},
appendTo
:
that
.
container
,
containment
:
that
.
container
,
revert
:
'invalid'
});
});
}
},
_registerRemoveEvents
:
function
(
elements
)
{
var
that
=
this
;
elements
.
click
(
function
()
{
that
.
_setSelected
(
$
(
this
).
parent
(),
false
);
that
.
count
-=
1
;
that
.
_updateCount
();
return
false
;
});
},
_registerSearchEvents
:
function
(
input
)
{
var
that
=
this
;
input
.
focus
(
function
()
{
$
(
this
).
addClass
(
'ui-state-active'
);
})
.
blur
(
function
()
{
$
(
this
).
removeClass
(
'ui-state-active'
);
})
.
keypress
(
function
(
e
)
{
if
(
e
.
keyCode
===
13
)
{
return
false
;
}
})
.
keyup
(
function
()
{
that
.
_filter
.
apply
(
this
,
[
that
.
availableList
]);
});
}
});
})(
jQuery
,
mediaWiki
);
File Metadata
Details
Attached
Mime Type
text/html
Expires
Sat, Oct 3, 08:51 (1 w, 4 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
cd/a6/c85857fe6c91ea4eed7dd0753860
Default Alt Text
ui.multiselect.js (11 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment