populate-me 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/example/config.ru +6 -0
- data/lib/populate_me/admin/__assets__/css/asmselect.css +63 -0
- data/lib/populate_me/admin/__assets__/css/jquery-ui.min.css +6 -0
- data/lib/populate_me/admin/__assets__/css/main.css +30 -4
- data/lib/populate_me/admin/__assets__/js/asmselect.js +412 -0
- data/lib/populate_me/admin/__assets__/js/jquery-ui.min.js +7 -0
- data/lib/populate_me/admin/__assets__/js/main.js +3 -0
- data/lib/populate_me/admin/views/page.erb +11 -7
- data/lib/populate_me/document.rb +16 -3
- data/lib/populate_me/document_mixins/admin_adapter.rb +1 -3
- data/lib/populate_me/document_mixins/outcasting.rb +29 -3
- data/lib/populate_me/document_mixins/schema.rb +13 -0
- data/lib/populate_me/document_mixins/typecasting.rb +8 -0
- data/lib/populate_me/document_mixins/validation.rb +1 -1
- data/lib/populate_me/version.rb +1 -1
- data/test/test_document_outcasting.rb +211 -0
- data/test/test_document_schema.rb +42 -0
- data/test/test_document_typecasting.rb +10 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ff6598db649ef34bc8d9d944eba83353d4efd8c
|
4
|
+
data.tar.gz: 6a6811373d3f8e17bad20d968888ca628d4561e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 04e3e69f706b562e5e5d193a279851d7fa6836b45eb5f80da2dc3c560011d02f37eece21dedba802f4cb1be3c7dcf62f8e2092d2824be61a26767bbe24929eb3
|
7
|
+
data.tar.gz: 5365b1d443fbaadd2b3b44caf932a187546dc174f858c9a53bcae53ff200c7cda44445aca8913a8d8620ca0c12fa6ddcdc8bea029d01db55f792ab254a5bd74c
|
data/example/config.ru
CHANGED
@@ -59,7 +59,13 @@ end
|
|
59
59
|
class Article < PopulateMe::Document
|
60
60
|
field :title
|
61
61
|
field :content, type: :text
|
62
|
+
field :yes_or_no, type: :select, select_options: [:yes,:no]
|
63
|
+
field :tags, type: :select, multiple: true, select_options: ['art','sport','science']
|
62
64
|
position_field
|
65
|
+
|
66
|
+
after :save do
|
67
|
+
puts self.inspect
|
68
|
+
end
|
63
69
|
end
|
64
70
|
|
65
71
|
# Admin ##########
|
@@ -0,0 +1,63 @@
|
|
1
|
+
.asmContainer {
|
2
|
+
/* container that surrounds entire asmSelect widget */
|
3
|
+
}
|
4
|
+
|
5
|
+
.asmSelect {
|
6
|
+
/* the newly created regular 'select' */
|
7
|
+
display: inline;
|
8
|
+
}
|
9
|
+
|
10
|
+
.asmOptionDisabled {
|
11
|
+
/* disabled options in new select */
|
12
|
+
color: #999;
|
13
|
+
}
|
14
|
+
|
15
|
+
.asmHighlight {
|
16
|
+
/* the highlight span */
|
17
|
+
padding: 0;
|
18
|
+
margin: 0 0 0 1em;
|
19
|
+
}
|
20
|
+
|
21
|
+
.asmList {
|
22
|
+
/* html list that contains selected items */
|
23
|
+
margin: 0.25em 0 1em 0;
|
24
|
+
position: relative;
|
25
|
+
display: block;
|
26
|
+
padding-left: 0;
|
27
|
+
list-style: none;
|
28
|
+
}
|
29
|
+
|
30
|
+
.asmListItem {
|
31
|
+
/* li item from the html list above */
|
32
|
+
position: relative;
|
33
|
+
margin-left: 0;
|
34
|
+
padding-left: 0;
|
35
|
+
list-style: none;
|
36
|
+
background: #ddd;
|
37
|
+
border: 1px solid #bbb;
|
38
|
+
width: 100%;
|
39
|
+
margin: 0 0 -1px 0;
|
40
|
+
line-height: 1em;
|
41
|
+
}
|
42
|
+
|
43
|
+
.asmListItem:hover {
|
44
|
+
background-color: #e5e5e5;
|
45
|
+
}
|
46
|
+
|
47
|
+
.asmListItemLabel {
|
48
|
+
/* this is a span that surrounds the text in the item, except for the remove link */
|
49
|
+
padding: 5px;
|
50
|
+
display: block;
|
51
|
+
}
|
52
|
+
|
53
|
+
.asmListSortable .asmListItemLabel {
|
54
|
+
cursor: move;
|
55
|
+
}
|
56
|
+
|
57
|
+
.asmListItemRemove {
|
58
|
+
/* the remove link in each list item */
|
59
|
+
position: absolute;
|
60
|
+
right: 0;
|
61
|
+
top: 0;
|
62
|
+
padding: 5px;
|
63
|
+
}
|
@@ -66,7 +66,7 @@ button { cursor: pointer; }
|
|
66
66
|
margin-bottom: 1em;
|
67
67
|
}
|
68
68
|
|
69
|
-
button.admin-delete, button.admin-delete-nested, .handle {
|
69
|
+
button.admin-delete, button.admin-delete-nested, .handle-button {
|
70
70
|
display: inline-block; vertical-align: middle;
|
71
71
|
font-size: 1em; line-height: 1em;
|
72
72
|
width: auto; height: auto;
|
@@ -78,14 +78,19 @@ button.admin-delete, button.admin-delete-nested {
|
|
78
78
|
color: #dc322f;
|
79
79
|
background-color: transparent;
|
80
80
|
}
|
81
|
-
button.admin-delete:focus, button.admin-delete-nested:focus, .handle:focus {
|
81
|
+
button.admin-delete:focus, button.admin-delete-nested:focus, .handle-button:focus {
|
82
82
|
outline: 0;
|
83
83
|
}
|
84
84
|
.handle {
|
85
85
|
cursor: move;
|
86
|
-
|
86
|
+
cursor: -moz-grab;
|
87
|
+
cursor: -webkit-grab;
|
88
|
+
cursor: grab;
|
87
89
|
}
|
88
|
-
.handle:
|
90
|
+
.handle:active {
|
91
|
+
cursor: -moz-grabbing;
|
92
|
+
cursor: -webkit-grabbing;
|
93
|
+
cursor: grabbing;
|
89
94
|
}
|
90
95
|
|
91
96
|
[type=submit] {
|
@@ -161,6 +166,27 @@ fieldset {
|
|
161
166
|
color: #dc322f;
|
162
167
|
}
|
163
168
|
|
169
|
+
/* asmSelect */
|
170
|
+
|
171
|
+
.asmListItem {
|
172
|
+
background-color: #ffffff;
|
173
|
+
border: 1px solid #fdf6e3;
|
174
|
+
}
|
175
|
+
.asmListItem:hover { background-color: #eee8d5; }
|
176
|
+
.asmListItemLabel { padding-right: 2em; }
|
177
|
+
.asmListSortable .asmListItemLabel {
|
178
|
+
cursor: move;
|
179
|
+
cursor: -moz-grab;
|
180
|
+
cursor: -webkit-grab;
|
181
|
+
cursor: grab;
|
182
|
+
}
|
183
|
+
.asmListSortable .asmListItemLabel:active {
|
184
|
+
cursor: -moz-grabbing;
|
185
|
+
cursor: -webkit-grabbing;
|
186
|
+
cursor: grabbing;
|
187
|
+
}
|
188
|
+
.asmListItemRemove, .asmListItemRemove:hover { color: #dc322f; }
|
189
|
+
|
164
190
|
|
165
191
|
/\
|
166
192
|
/ *\
|
@@ -0,0 +1,412 @@
|
|
1
|
+
/*
|
2
|
+
* Alternate Select Multiple (asmSelect) 1.0.4a beta - jQuery Plugin
|
3
|
+
* http://www.ryancramer.com/projects/asmselect/
|
4
|
+
*
|
5
|
+
* Copyright (c) 2009 by Ryan Cramer - http://www.ryancramer.com
|
6
|
+
*
|
7
|
+
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
8
|
+
* and GPL (GPL-LICENSE.txt) licenses.
|
9
|
+
*
|
10
|
+
*/
|
11
|
+
|
12
|
+
// The references to $.browser where commented out because it
|
13
|
+
// breaks with newer version of jQuery.
|
14
|
+
|
15
|
+
(function($) {
|
16
|
+
|
17
|
+
$.fn.asmSelect = function(customOptions) {
|
18
|
+
|
19
|
+
var options = {
|
20
|
+
|
21
|
+
listType: 'ol', // Ordered list 'ol', or unordered list 'ul'
|
22
|
+
sortable: false, // Should the list be sortable?
|
23
|
+
highlight: false, // Use the highlight feature?
|
24
|
+
animate: false, // Animate the the adding/removing of items in the list?
|
25
|
+
addItemTarget: 'bottom', // Where to place new selected items in list: top or bottom
|
26
|
+
hideWhenAdded: false, // Hide the option when added to the list? works only in FF
|
27
|
+
debugMode: false, // Debug mode keeps original select visible
|
28
|
+
|
29
|
+
removeLabel: 'remove', // Text used in the "remove" link
|
30
|
+
highlightAddedLabel: 'Added: ', // Text that precedes highlight of added item
|
31
|
+
highlightRemovedLabel: 'Removed: ', // Text that precedes highlight of removed item
|
32
|
+
|
33
|
+
containerClass: 'asmContainer', // Class for container that wraps this widget
|
34
|
+
selectClass: 'asmSelect', // Class for the newly created <select>
|
35
|
+
optionDisabledClass: 'asmOptionDisabled', // Class for items that are already selected / disabled
|
36
|
+
listClass: 'asmList', // Class for the list ($ol)
|
37
|
+
listSortableClass: 'asmListSortable', // Another class given to the list when it is sortable
|
38
|
+
listItemClass: 'asmListItem', // Class for the <li> list items
|
39
|
+
listItemLabelClass: 'asmListItemLabel', // Class for the label text that appears in list items
|
40
|
+
removeClass: 'asmListItemRemove', // Class given to the "remove" link
|
41
|
+
highlightClass: 'asmHighlight' // Class given to the highlight <span>
|
42
|
+
|
43
|
+
};
|
44
|
+
|
45
|
+
$.extend(options, customOptions);
|
46
|
+
|
47
|
+
return this.each(function(index) {
|
48
|
+
|
49
|
+
var $original = $(this); // the original select multiple
|
50
|
+
var $container; // a container that is wrapped around our widget
|
51
|
+
var $select; // the new select we have created
|
52
|
+
var $ol; // the list that we are manipulating
|
53
|
+
var buildingSelect = false; // is the new select being constructed right now?
|
54
|
+
var ieClick = false; // in IE, has a click event occurred? ignore if not
|
55
|
+
var ignoreOriginalChangeEvent = false; // originalChangeEvent bypassed when this is true
|
56
|
+
|
57
|
+
function init() {
|
58
|
+
|
59
|
+
// initialize the alternate select multiple
|
60
|
+
|
61
|
+
// this loop ensures uniqueness, in case of existing asmSelects placed by ajax (1.0.3)
|
62
|
+
while($("#" + options.containerClass + index).size() > 0) index++;
|
63
|
+
|
64
|
+
$select = $("<select></select>")
|
65
|
+
.addClass(options.selectClass)
|
66
|
+
.attr('name', options.selectClass + index)
|
67
|
+
.attr('id', options.selectClass + index);
|
68
|
+
|
69
|
+
$selectRemoved = $("<select></select>");
|
70
|
+
|
71
|
+
$ol = $("<" + options.listType + "></" + options.listType + ">")
|
72
|
+
.addClass(options.listClass)
|
73
|
+
.attr('id', options.listClass + index);
|
74
|
+
|
75
|
+
$container = $("<div></div>")
|
76
|
+
.addClass(options.containerClass)
|
77
|
+
.attr('id', options.containerClass + index);
|
78
|
+
|
79
|
+
buildSelect();
|
80
|
+
|
81
|
+
$select.change(selectChangeEvent)
|
82
|
+
.click(selectClickEvent);
|
83
|
+
|
84
|
+
$original.change(originalChangeEvent)
|
85
|
+
.wrap($container).before($select).before($ol);
|
86
|
+
|
87
|
+
if(options.sortable) makeSortable();
|
88
|
+
|
89
|
+
// if($.browser.msie && $.browser.version < 8) $ol.css('display', 'inline-block'); // Thanks Matthew Hutton
|
90
|
+
}
|
91
|
+
|
92
|
+
function makeSortable() {
|
93
|
+
|
94
|
+
// make any items in the selected list sortable
|
95
|
+
// requires jQuery UI sortables, draggables, droppables
|
96
|
+
|
97
|
+
$ol.sortable({
|
98
|
+
items: 'li.' + options.listItemClass,
|
99
|
+
handle: '.' + options.listItemLabelClass,
|
100
|
+
axis: 'y',
|
101
|
+
update: function(e, data) {
|
102
|
+
|
103
|
+
var updatedOptionId;
|
104
|
+
|
105
|
+
$(this).children("li").each(function(n) {
|
106
|
+
|
107
|
+
$option = $('#' + $(this).attr('rel'));
|
108
|
+
|
109
|
+
if($(this).is(".ui-sortable-helper")) {
|
110
|
+
updatedOptionId = $option.attr('id');
|
111
|
+
return;
|
112
|
+
}
|
113
|
+
|
114
|
+
$original.append($option);
|
115
|
+
});
|
116
|
+
|
117
|
+
if(updatedOptionId) triggerOriginalChange(updatedOptionId, 'sort');
|
118
|
+
}
|
119
|
+
|
120
|
+
}).addClass(options.listSortableClass);
|
121
|
+
}
|
122
|
+
|
123
|
+
function selectChangeEvent(e) {
|
124
|
+
|
125
|
+
// an item has been selected on the regular select we created
|
126
|
+
// check to make sure it's not an IE screwup, and add it to the list
|
127
|
+
|
128
|
+
// if($.browser.msie && $.browser.version < 7 && !ieClick) return;
|
129
|
+
var id = $(this).children("option:selected").slice(0,1).attr('rel');
|
130
|
+
addListItem(id);
|
131
|
+
ieClick = false;
|
132
|
+
triggerOriginalChange(id, 'add'); // for use by user-defined callbacks
|
133
|
+
}
|
134
|
+
|
135
|
+
function selectClickEvent() {
|
136
|
+
|
137
|
+
// IE6 lets you scroll around in a select without it being pulled down
|
138
|
+
// making sure a click preceded the change() event reduces the chance
|
139
|
+
// if unintended items being added. there may be a better solution?
|
140
|
+
|
141
|
+
ieClick = true;
|
142
|
+
}
|
143
|
+
|
144
|
+
function originalChangeEvent(e) {
|
145
|
+
|
146
|
+
// select or option change event manually triggered
|
147
|
+
// on the original <select multiple>, so rebuild ours
|
148
|
+
|
149
|
+
if(ignoreOriginalChangeEvent) {
|
150
|
+
ignoreOriginalChangeEvent = false;
|
151
|
+
return;
|
152
|
+
}
|
153
|
+
|
154
|
+
$select.empty();
|
155
|
+
$ol.empty();
|
156
|
+
buildSelect();
|
157
|
+
|
158
|
+
// opera has an issue where it needs a force redraw, otherwise
|
159
|
+
// the items won't appear until something else forces a redraw
|
160
|
+
// if($.browser.opera) $ol.hide().fadeIn("fast");
|
161
|
+
}
|
162
|
+
|
163
|
+
function buildSelect() {
|
164
|
+
|
165
|
+
// build or rebuild the new select that the user
|
166
|
+
// will select items from
|
167
|
+
|
168
|
+
buildingSelect = true;
|
169
|
+
|
170
|
+
// add a first option to be the home option / default selectLabel
|
171
|
+
$select.prepend("<option>" + $original.attr('title') + "</option>");
|
172
|
+
|
173
|
+
$original.children("option").each(function(n) {
|
174
|
+
|
175
|
+
var $t = $(this);
|
176
|
+
var id;
|
177
|
+
|
178
|
+
if(!$t.attr('id')) $t.attr('id', 'asm' + index + 'option' + n);
|
179
|
+
id = $t.attr('id');
|
180
|
+
|
181
|
+
if($t.is(":selected")) {
|
182
|
+
addListItem(id);
|
183
|
+
addSelectOption(id, true);
|
184
|
+
} else {
|
185
|
+
addSelectOption(id);
|
186
|
+
}
|
187
|
+
});
|
188
|
+
|
189
|
+
if(!options.debugMode) $original.hide(); // IE6 requires this on every buildSelect()
|
190
|
+
selectFirstItem();
|
191
|
+
buildingSelect = false;
|
192
|
+
}
|
193
|
+
|
194
|
+
function addSelectOption(optionId, disabled) {
|
195
|
+
|
196
|
+
// add an <option> to the <select>
|
197
|
+
// used only by buildSelect()
|
198
|
+
|
199
|
+
if(disabled == undefined) var disabled = false;
|
200
|
+
|
201
|
+
var $O = $('#' + optionId);
|
202
|
+
var $option = $("<option>" + $O.text() + "</option>")
|
203
|
+
.val($O.val())
|
204
|
+
.attr('rel', optionId);
|
205
|
+
|
206
|
+
if(disabled) disableSelectOption($option);
|
207
|
+
|
208
|
+
$select.append($option);
|
209
|
+
}
|
210
|
+
|
211
|
+
function selectFirstItem() {
|
212
|
+
|
213
|
+
// select the firm item from the regular select that we created
|
214
|
+
|
215
|
+
$select.children(":eq(0)").attr("selected", true);
|
216
|
+
}
|
217
|
+
|
218
|
+
function disableSelectOption($option) {
|
219
|
+
|
220
|
+
// make an option disabled, indicating that it's already been selected
|
221
|
+
// because safari is the only browser that makes disabled items look 'disabled'
|
222
|
+
// we apply a class that reproduces the disabled look in other browsers
|
223
|
+
|
224
|
+
$option.addClass(options.optionDisabledClass)
|
225
|
+
.attr("selected", false)
|
226
|
+
.attr("disabled", true);
|
227
|
+
|
228
|
+
if(options.hideWhenAdded) $option.hide();
|
229
|
+
// if($.browser.msie) $select.hide().show(); // this forces IE to update display
|
230
|
+
if(true) $select.hide().show(); // this forces IE to update display
|
231
|
+
}
|
232
|
+
|
233
|
+
function enableSelectOption($option) {
|
234
|
+
|
235
|
+
// given an already disabled select option, enable it
|
236
|
+
|
237
|
+
$option.removeClass(options.optionDisabledClass)
|
238
|
+
.attr("disabled", false);
|
239
|
+
|
240
|
+
if(options.hideWhenAdded) $option.show();
|
241
|
+
// if($.browser.msie) $select.hide().show(); // this forces IE to update display
|
242
|
+
if(true) $select.hide().show(); // this forces IE to update display
|
243
|
+
}
|
244
|
+
|
245
|
+
function addListItem(optionId) {
|
246
|
+
|
247
|
+
// add a new item to the html list
|
248
|
+
|
249
|
+
var $O = $('#' + optionId);
|
250
|
+
|
251
|
+
if(!$O) return; // this is the first item, selectLabel
|
252
|
+
|
253
|
+
var $removeLink = $("<a></a>")
|
254
|
+
.attr("href", "#")
|
255
|
+
.addClass(options.removeClass)
|
256
|
+
.prepend(options.removeLabel)
|
257
|
+
.click(function() {
|
258
|
+
dropListItem($(this).parent('li').attr('rel'));
|
259
|
+
return false;
|
260
|
+
});
|
261
|
+
|
262
|
+
var $itemLabel = $("<span></span>")
|
263
|
+
.addClass(options.listItemLabelClass)
|
264
|
+
.html($O.html());
|
265
|
+
|
266
|
+
var $item = $("<li></li>")
|
267
|
+
.attr('rel', optionId)
|
268
|
+
.addClass(options.listItemClass)
|
269
|
+
.append($itemLabel)
|
270
|
+
.append($removeLink)
|
271
|
+
.hide();
|
272
|
+
|
273
|
+
if(!buildingSelect) {
|
274
|
+
if($O.is(":selected")) return; // already have it
|
275
|
+
$O.attr('selected', true);
|
276
|
+
}
|
277
|
+
|
278
|
+
if(options.addItemTarget == 'top' && !buildingSelect) {
|
279
|
+
$ol.prepend($item);
|
280
|
+
if(options.sortable) $original.prepend($O);
|
281
|
+
} else {
|
282
|
+
$ol.append($item);
|
283
|
+
if(options.sortable) $original.append($O);
|
284
|
+
}
|
285
|
+
|
286
|
+
addListItemShow($item);
|
287
|
+
|
288
|
+
disableSelectOption($("[rel=" + optionId + "]", $select));
|
289
|
+
|
290
|
+
if(!buildingSelect) {
|
291
|
+
setHighlight($item, options.highlightAddedLabel);
|
292
|
+
selectFirstItem();
|
293
|
+
if(options.sortable) $ol.sortable("refresh");
|
294
|
+
}
|
295
|
+
|
296
|
+
}
|
297
|
+
|
298
|
+
function addListItemShow($item) {
|
299
|
+
|
300
|
+
// reveal the currently hidden item with optional animation
|
301
|
+
// used only by addListItem()
|
302
|
+
|
303
|
+
if(options.animate && !buildingSelect) {
|
304
|
+
$item.animate({
|
305
|
+
opacity: "show",
|
306
|
+
height: "show"
|
307
|
+
}, 100, "swing", function() {
|
308
|
+
$item.animate({
|
309
|
+
height: "+=2px"
|
310
|
+
}, 50, "swing", function() {
|
311
|
+
$item.animate({
|
312
|
+
height: "-=2px"
|
313
|
+
}, 25, "swing");
|
314
|
+
});
|
315
|
+
});
|
316
|
+
} else {
|
317
|
+
$item.show();
|
318
|
+
}
|
319
|
+
}
|
320
|
+
|
321
|
+
function dropListItem(optionId, highlightItem) {
|
322
|
+
|
323
|
+
// remove an item from the html list
|
324
|
+
|
325
|
+
if(highlightItem == undefined) var highlightItem = true;
|
326
|
+
var $O = $('#' + optionId);
|
327
|
+
|
328
|
+
$O.attr('selected', false);
|
329
|
+
$item = $ol.children("li[rel=" + optionId + "]");
|
330
|
+
|
331
|
+
dropListItemHide($item);
|
332
|
+
enableSelectOption($("[rel=" + optionId + "]", options.removeWhenAdded ? $selectRemoved : $select));
|
333
|
+
|
334
|
+
if(highlightItem) setHighlight($item, options.highlightRemovedLabel);
|
335
|
+
|
336
|
+
triggerOriginalChange(optionId, 'drop');
|
337
|
+
|
338
|
+
}
|
339
|
+
|
340
|
+
function dropListItemHide($item) {
|
341
|
+
|
342
|
+
// remove the currently visible item with optional animation
|
343
|
+
// used only by dropListItem()
|
344
|
+
|
345
|
+
if(options.animate && !buildingSelect) {
|
346
|
+
|
347
|
+
$prevItem = $item.prev("li");
|
348
|
+
|
349
|
+
$item.animate({
|
350
|
+
opacity: "hide",
|
351
|
+
height: "hide"
|
352
|
+
}, 100, "linear", function() {
|
353
|
+
$prevItem.animate({
|
354
|
+
height: "-=2px"
|
355
|
+
}, 50, "swing", function() {
|
356
|
+
$prevItem.animate({
|
357
|
+
height: "+=2px"
|
358
|
+
}, 100, "swing");
|
359
|
+
});
|
360
|
+
$item.remove();
|
361
|
+
});
|
362
|
+
|
363
|
+
} else {
|
364
|
+
$item.remove();
|
365
|
+
}
|
366
|
+
}
|
367
|
+
|
368
|
+
function setHighlight($item, label) {
|
369
|
+
|
370
|
+
// set the contents of the highlight area that appears
|
371
|
+
// directly after the <select> single
|
372
|
+
// fade it in quickly, then fade it out
|
373
|
+
|
374
|
+
if(!options.highlight) return;
|
375
|
+
|
376
|
+
$select.next("#" + options.highlightClass + index).remove();
|
377
|
+
|
378
|
+
var $highlight = $("<span></span>")
|
379
|
+
.hide()
|
380
|
+
.addClass(options.highlightClass)
|
381
|
+
.attr('id', options.highlightClass + index)
|
382
|
+
.html(label + $item.children("." + options.listItemLabelClass).slice(0,1).text());
|
383
|
+
|
384
|
+
$select.after($highlight);
|
385
|
+
|
386
|
+
$highlight.fadeIn("fast", function() {
|
387
|
+
setTimeout(function() { $highlight.fadeOut("slow"); }, 50);
|
388
|
+
});
|
389
|
+
}
|
390
|
+
|
391
|
+
function triggerOriginalChange(optionId, type) {
|
392
|
+
|
393
|
+
// trigger a change event on the original select multiple
|
394
|
+
// so that other scripts can pick them up
|
395
|
+
|
396
|
+
ignoreOriginalChangeEvent = true;
|
397
|
+
$option = $("#" + optionId);
|
398
|
+
|
399
|
+
$original.trigger('change', [{
|
400
|
+
'option': $option,
|
401
|
+
'value': $option.val(),
|
402
|
+
'id': optionId,
|
403
|
+
'item': $ol.children("[rel=" + optionId + "]"),
|
404
|
+
'type': type
|
405
|
+
}]);
|
406
|
+
}
|
407
|
+
|
408
|
+
init();
|
409
|
+
});
|
410
|
+
};
|
411
|
+
|
412
|
+
})(jQuery);
|
@@ -0,0 +1,7 @@
|
|
1
|
+
/*! jQuery UI - v1.12.1 - 2018-02-23
|
2
|
+
* http://jqueryui.com
|
3
|
+
* Includes: widget.js, data.js, scroll-parent.js, widgets/sortable.js, widgets/mouse.js
|
4
|
+
* Copyright jQuery Foundation and other contributors; Licensed MIT */
|
5
|
+
|
6
|
+
(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)})(function(t){t.ui=t.ui||{},t.ui.version="1.12.1";var e=0,i=Array.prototype.slice;t.cleanData=function(e){return function(i){var s,n,o;for(o=0;null!=(n=i[o]);o++)try{s=t._data(n,"events"),s&&s.remove&&t(n).triggerHandler("remove")}catch(a){}e(i)}}(t.cleanData),t.widget=function(e,i,s){var n,o,a,r={},l=e.split(".")[0];e=e.split(".")[1];var h=l+"-"+e;return s||(s=i,i=t.Widget),t.isArray(s)&&(s=t.extend.apply(null,[{}].concat(s))),t.expr[":"][h.toLowerCase()]=function(e){return!!t.data(e,h)},t[l]=t[l]||{},n=t[l][e],o=t[l][e]=function(t,e){return this._createWidget?(arguments.length&&this._createWidget(t,e),void 0):new o(t,e)},t.extend(o,n,{version:s.version,_proto:t.extend({},s),_childConstructors:[]}),a=new i,a.options=t.widget.extend({},a.options),t.each(s,function(e,s){return t.isFunction(s)?(r[e]=function(){function t(){return i.prototype[e].apply(this,arguments)}function n(t){return i.prototype[e].apply(this,t)}return function(){var e,i=this._super,o=this._superApply;return this._super=t,this._superApply=n,e=s.apply(this,arguments),this._super=i,this._superApply=o,e}}(),void 0):(r[e]=s,void 0)}),o.prototype=t.widget.extend(a,{widgetEventPrefix:n?a.widgetEventPrefix||e:e},r,{constructor:o,namespace:l,widgetName:e,widgetFullName:h}),n?(t.each(n._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete n._childConstructors):i._childConstructors.push(o),t.widget.bridge(e,o),o},t.widget.extend=function(e){for(var s,n,o=i.call(arguments,1),a=0,r=o.length;r>a;a++)for(s in o[a])n=o[a][s],o[a].hasOwnProperty(s)&&void 0!==n&&(e[s]=t.isPlainObject(n)?t.isPlainObject(e[s])?t.widget.extend({},e[s],n):t.widget.extend({},n):n);return e},t.widget.bridge=function(e,s){var n=s.prototype.widgetFullName||e;t.fn[e]=function(o){var a="string"==typeof o,r=i.call(arguments,1),l=this;return a?this.length||"instance"!==o?this.each(function(){var i,s=t.data(this,n);return"instance"===o?(l=s,!1):s?t.isFunction(s[o])&&"_"!==o.charAt(0)?(i=s[o].apply(s,r),i!==s&&void 0!==i?(l=i&&i.jquery?l.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+o+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; "+"attempted to call method '"+o+"'")}):l=void 0:(r.length&&(o=t.widget.extend.apply(null,[o].concat(r))),this.each(function(){var e=t.data(this,n);e?(e.option(o||{}),e._init&&e._init()):t.data(this,n,new s(o,this))})),l}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{classes:{},disabled:!1,create:null},_createWidget:function(i,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=e++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),this.classesElementLookup={},s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),i),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){var e=this;this._destroy(),t.each(this.classesElementLookup,function(t,i){e._removeClass(i,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var s,n,o,a=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(a={},s=e.split("."),e=s.shift(),s.length){for(n=a[e]=t.widget.extend({},this.options[e]),o=0;s.length-1>o;o++)n[s[o]]=n[s[o]]||{},n=n[s[o]];if(e=s.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];a[e]=i}return this._setOptions(a),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(e){var i,s,n;for(i in e)n=this.classesElementLookup[i],e[i]!==this.options.classes[i]&&n&&n.length&&(s=t(n.get()),this._removeClass(n,i),s.addClass(this._classes({element:s,keys:i,classes:e,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(e){function i(i,o){var a,r;for(r=0;i.length>r;r++)a=n.classesElementLookup[i[r]]||t(),a=e.add?t(t.unique(a.get().concat(e.element.get()))):t(a.not(e.element).get()),n.classesElementLookup[i[r]]=a,s.push(i[r]),o&&e.classes[i[r]]&&s.push(e.classes[i[r]])}var s=[],n=this;return e=t.extend({element:this.element,classes:this.options.classes||{}},e),this._on(e.element,{remove:"_untrackClassesElement"}),e.keys&&i(e.keys.match(/\S+/g)||[],!0),e.extra&&i(e.extra.match(/\S+/g)||[]),s.join(" ")},_untrackClassesElement:function(e){var i=this;t.each(i.classesElementLookup,function(s,n){-1!==t.inArray(e.target,n)&&(i.classesElementLookup[s]=t(n.not(e.target).get()))})},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){s="boolean"==typeof s?s:i;var n="string"==typeof t||null===t,o={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s};return o.element.toggleClass(this._classes(o),s),this},_on:function(e,i,s){var n,o=this;"boolean"!=typeof e&&(s=i,i=e,e=!1),s?(i=n=t(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),t.each(s,function(s,a){function r(){return e||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof a?o[a]:a).apply(o,arguments):void 0}"string"!=typeof a&&(r.guid=a.guid=a.guid||r.guid||t.guid++);var l=s.match(/^([\w:-]*)\s*(.*)$/),h=l[1]+o.eventNamespace,c=l[2];c?n.on(h,c,r):i.on(h,r)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.off(i).off(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){this._addClass(t(e.currentTarget),null,"ui-state-hover")},mouseleave:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){this._addClass(t(e.currentTarget),null,"ui-state-focus")},focusout:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}}),t.widget,t.extend(t.expr[":"],{data:t.expr.createPseudo?t.expr.createPseudo(function(e){return function(i){return!!t.data(i,e)}}):function(e,i,s){return!!t.data(e,s[3])}}),t.fn.scrollParent=function(e){var i=this.css("position"),s="absolute"===i,n=e?/(auto|scroll|hidden)/:/(auto|scroll)/,o=this.parents().filter(function(){var e=t(this);return s&&"static"===e.css("position")?!1:n.test(e.css("overflow")+e.css("overflow-y")+e.css("overflow-x"))}).eq(0);return"fixed"!==i&&o.length?o:t(this[0].ownerDocument||document)},t.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());var s=!1;t(document).on("mouseup",function(){s=!1}),t.widget("ui.mouse",{version:"1.12.1",options:{cancel:"input, textarea, button, select, option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.on("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).on("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.off("."+this.widgetName),this._mouseMoveDelegate&&this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(e){if(!s){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(e),this._mouseDownEvent=e;var i=this,n=1===e.which,o="string"==typeof this.options.cancel&&e.target.nodeName?t(e.target).closest(this.options.cancel).length:!1;return n&&!o&&this._mouseCapture(e)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(e)!==!1,!this._mouseStarted)?(e.preventDefault(),!0):(!0===t.data(e.target,this.widgetName+".preventClickEvent")&&t.removeData(e.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return i._mouseMove(t)},this._mouseUpDelegate=function(t){return i._mouseUp(t)},this.document.on("mousemove."+this.widgetName,this._mouseMoveDelegate).on("mouseup."+this.widgetName,this._mouseUpDelegate),e.preventDefault(),s=!0,!0)):!0}},_mouseMove:function(e){if(this._mouseMoved){if(t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button)return this._mouseUp(e);if(!e.which)if(e.originalEvent.altKey||e.originalEvent.ctrlKey||e.originalEvent.metaKey||e.originalEvent.shiftKey)this.ignoreMissingWhich=!0;else if(!this.ignoreMissingWhich)return this._mouseUp(e)}return(e.which||e.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),this._mouseDelayTimer&&(clearTimeout(this._mouseDelayTimer),delete this._mouseDelayTimer),this.ignoreMissingWhich=!1,s=!1,e.preventDefault()},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),t.widget("ui.sortable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_isOverAxis:function(t,e,i){return t>=e&&e+i>t},_isFloating:function(t){return/left|right/.test(t.css("float"))||/inline|table-cell/.test(t.css("display"))},_create:function(){this.containerCache={},this._addClass("ui-sortable"),this.refresh(),this.offset=this.element.offset(),this._mouseInit(),this._setHandleClassName(),this.ready=!0},_setOption:function(t,e){this._super(t,e),"handle"===t&&this._setHandleClassName()},_setHandleClassName:function(){var e=this;this._removeClass(this.element.find(".ui-sortable-handle"),"ui-sortable-handle"),t.each(this.items,function(){e._addClass(this.instance.options.handle?this.item.find(this.instance.options.handle):this.item,"ui-sortable-handle")})},_destroy:function(){this._mouseDestroy();for(var t=this.items.length-1;t>=0;t--)this.items[t].item.removeData(this.widgetName+"-item");return this},_mouseCapture:function(e,i){var s=null,n=!1,o=this;return this.reverting?!1:this.options.disabled||"static"===this.options.type?!1:(this._refreshItems(e),t(e.target).parents().each(function(){return t.data(this,o.widgetName+"-item")===o?(s=t(this),!1):void 0}),t.data(e.target,o.widgetName+"-item")===o&&(s=t(e.target)),s?!this.options.handle||i||(t(this.options.handle,s).find("*").addBack().each(function(){this===e.target&&(n=!0)}),n)?(this.currentItem=s,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(e,i,s){var n,o,a=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(e),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},t.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(e),this.originalPageX=e.pageX,this.originalPageY=e.pageY,a.cursorAt&&this._adjustOffsetFromHelper(a.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),a.containment&&this._setContainment(),a.cursor&&"auto"!==a.cursor&&(o=this.document.find("body"),this.storedCursor=o.css("cursor"),o.css("cursor",a.cursor),this.storedStylesheet=t("<style>*{ cursor: "+a.cursor+" !important; }</style>").appendTo(o)),a.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",a.opacity)),a.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",a.zIndex)),this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",e,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(n=this.containers.length-1;n>=0;n--)this.containers[n]._trigger("activate",e,this._uiHash(this));return t.ui.ddmanager&&(t.ui.ddmanager.current=this),t.ui.ddmanager&&!a.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this.dragging=!0,this._addClass(this.helper,"ui-sortable-helper"),this._mouseDrag(e),!0},_mouseDrag:function(e){var i,s,n,o,a=this.options,r=!1;for(this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-e.pageY<a.scrollSensitivity?this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop+a.scrollSpeed:e.pageY-this.overflowOffset.top<a.scrollSensitivity&&(this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop-a.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-e.pageX<a.scrollSensitivity?this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft+a.scrollSpeed:e.pageX-this.overflowOffset.left<a.scrollSensitivity&&(this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft-a.scrollSpeed)):(e.pageY-this.document.scrollTop()<a.scrollSensitivity?r=this.document.scrollTop(this.document.scrollTop()-a.scrollSpeed):this.window.height()-(e.pageY-this.document.scrollTop())<a.scrollSensitivity&&(r=this.document.scrollTop(this.document.scrollTop()+a.scrollSpeed)),e.pageX-this.document.scrollLeft()<a.scrollSensitivity?r=this.document.scrollLeft(this.document.scrollLeft()-a.scrollSpeed):this.window.width()-(e.pageX-this.document.scrollLeft())<a.scrollSensitivity&&(r=this.document.scrollLeft(this.document.scrollLeft()+a.scrollSpeed))),r!==!1&&t.ui.ddmanager&&!a.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e)),this.positionAbs=this._convertPositionTo("absolute"),this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),i=this.items.length-1;i>=0;i--)if(s=this.items[i],n=s.item[0],o=this._intersectsWithPointer(s),o&&s.instance===this.currentContainer&&n!==this.currentItem[0]&&this.placeholder[1===o?"next":"prev"]()[0]!==n&&!t.contains(this.placeholder[0],n)&&("semi-dynamic"===this.options.type?!t.contains(this.element[0],n):!0)){if(this.direction=1===o?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(e,s),this._trigger("change",e,this._uiHash());break}return this._contactContainers(e),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),this._trigger("sort",e,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(e,i){if(e){if(t.ui.ddmanager&&!this.options.dropBehaviour&&t.ui.ddmanager.drop(this,e),this.options.revert){var s=this,n=this.placeholder.offset(),o=this.options.axis,a={};o&&"x"!==o||(a.left=n.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollLeft)),o&&"y"!==o||(a.top=n.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,t(this.helper).animate(a,parseInt(this.options.revert,10)||500,function(){s._clear(e)})}else this._clear(e,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp(new t.Event("mouseup",{target:null})),"original"===this.options.helper?(this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")):this.currentItem.show();for(var e=this.containers.length-1;e>=0;e--)this.containers[e]._trigger("deactivate",null,this._uiHash(this)),this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",null,this._uiHash(this)),this.containers[e].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),t.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?t(this.domPosition.prev).after(this.currentItem):t(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},t(i).each(function(){var i=(t(e.item||this).attr(e.attribute||"id")||"").match(e.expression||/(.+)[\-=_](.+)/);i&&s.push((e.key||i[1]+"[]")+"="+(e.key&&e.expression?i[1]:i[2]))}),!s.length&&e.key&&s.push(e.key+"="),s.join("&")},toArray:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},i.each(function(){s.push(t(e.item||this).attr(e.attribute||"id")||"")}),s},_intersectsWith:function(t){var e=this.positionAbs.left,i=e+this.helperProportions.width,s=this.positionAbs.top,n=s+this.helperProportions.height,o=t.left,a=o+t.width,r=t.top,l=r+t.height,h=this.offset.click.top,c=this.offset.click.left,u="x"===this.options.axis||s+h>r&&l>s+h,d="y"===this.options.axis||e+c>o&&a>e+c,p=u&&d;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>t[this.floating?"width":"height"]?p:e+this.helperProportions.width/2>o&&a>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>r&&l>n-this.helperProportions.height/2},_intersectsWithPointer:function(t){var e,i,s="x"===this.options.axis||this._isOverAxis(this.positionAbs.top+this.offset.click.top,t.top,t.height),n="y"===this.options.axis||this._isOverAxis(this.positionAbs.left+this.offset.click.left,t.left,t.width),o=s&&n;return o?(e=this._getDragVerticalDirection(),i=this._getDragHorizontalDirection(),this.floating?"right"===i||"down"===e?2:1:e&&("down"===e?2:1)):!1},_intersectsWithSides:function(t){var e=this._isOverAxis(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),i=this._isOverAxis(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),s=this._getDragVerticalDirection(),n=this._getDragHorizontalDirection();return this.floating&&n?"right"===n&&i||"left"===n&&!i:s&&("down"===s&&e||"up"===s&&!e)},_getDragVerticalDirection:function(){var t=this.positionAbs.top-this.lastPositionAbs.top;return 0!==t&&(t>0?"down":"up")},_getDragHorizontalDirection:function(){var t=this.positionAbs.left-this.lastPositionAbs.left;return 0!==t&&(t>0?"right":"left")},refresh:function(t){return this._refreshItems(t),this._setHandleClassName(),this.refreshPositions(),this},_connectWith:function(){var t=this.options;return t.connectWith.constructor===String?[t.connectWith]:t.connectWith},_getItemsAsjQuery:function(e){function i(){r.push(this)}var s,n,o,a,r=[],l=[],h=this._connectWith();if(h&&e)for(s=h.length-1;s>=0;s--)for(o=t(h[s],this.document[0]),n=o.length-1;n>=0;n--)a=t.data(o[n],this.widgetFullName),a&&a!==this&&!a.options.disabled&&l.push([t.isFunction(a.options.items)?a.options.items.call(a.element):t(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a]);for(l.push([t.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):t(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),s=l.length-1;s>=0;s--)l[s][0].each(i);return t(r)},_removeCurrentsFromItems:function(){var e=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=t.grep(this.items,function(t){for(var i=0;e.length>i;i++)if(e[i]===t.item[0])return!1;return!0})},_refreshItems:function(e){this.items=[],this.containers=[this];var i,s,n,o,a,r,l,h,c=this.items,u=[[t.isFunction(this.options.items)?this.options.items.call(this.element[0],e,{item:this.currentItem}):t(this.options.items,this.element),this]],d=this._connectWith();if(d&&this.ready)for(i=d.length-1;i>=0;i--)for(n=t(d[i],this.document[0]),s=n.length-1;s>=0;s--)o=t.data(n[s],this.widgetFullName),o&&o!==this&&!o.options.disabled&&(u.push([t.isFunction(o.options.items)?o.options.items.call(o.element[0],e,{item:this.currentItem}):t(o.options.items,o.element),o]),this.containers.push(o));for(i=u.length-1;i>=0;i--)for(a=u[i][1],r=u[i][0],s=0,h=r.length;h>s;s++)l=t(r[s]),l.data(this.widgetName+"-item",a),c.push({item:l,instance:a,width:0,height:0,left:0,top:0})},refreshPositions:function(e){this.floating=this.items.length?"x"===this.options.axis||this._isFloating(this.items[0].item):!1,this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,n,o;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(n=this.options.toleranceElement?t(this.options.toleranceElement,s.item):s.item,e||(s.width=n.outerWidth(),s.height=n.outerHeight()),o=n.offset(),s.left=o.left,s.top=o.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)o=this.containers[i].element.offset(),this.containers[i].containerCache.left=o.left,this.containers[i].containerCache.top=o.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(e){e=e||this;var i,s=e.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=e.currentItem[0].nodeName.toLowerCase(),n=t("<"+s+">",e.document[0]);return e._addClass(n,"ui-sortable-placeholder",i||e.currentItem[0].className)._removeClass(n,"ui-sortable-helper"),"tbody"===s?e._createTrPlaceholder(e.currentItem.find("tr").eq(0),t("<tr>",e.document[0]).appendTo(n)):"tr"===s?e._createTrPlaceholder(e.currentItem,n):"img"===s&&n.attr("src",e.currentItem.attr("src")),i||n.css("visibility","hidden"),n},update:function(t,n){(!i||s.forcePlaceholderSize)&&(n.height()||n.height(e.currentItem.innerHeight()-parseInt(e.currentItem.css("paddingTop")||0,10)-parseInt(e.currentItem.css("paddingBottom")||0,10)),n.width()||n.width(e.currentItem.innerWidth()-parseInt(e.currentItem.css("paddingLeft")||0,10)-parseInt(e.currentItem.css("paddingRight")||0,10)))}}),e.placeholder=t(s.placeholder.element.call(e.element,e.currentItem)),e.currentItem.after(e.placeholder),s.placeholder.update(e,e.placeholder)},_createTrPlaceholder:function(e,i){var s=this;e.children().each(function(){t("<td> </td>",s.document[0]).attr("colspan",t(this).attr("colspan")||1).appendTo(i)})},_contactContainers:function(e){var i,s,n,o,a,r,l,h,c,u,d=null,p=null;for(i=this.containers.length-1;i>=0;i--)if(!t.contains(this.currentItem[0],this.containers[i].element[0]))if(this._intersectsWith(this.containers[i].containerCache)){if(d&&t.contains(this.containers[i].element[0],d.element[0]))continue;d=this.containers[i],p=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger("out",e,this._uiHash(this)),this.containers[i].containerCache.over=0);if(d)if(1===this.containers.length)this.containers[p].containerCache.over||(this.containers[p]._trigger("over",e,this._uiHash(this)),this.containers[p].containerCache.over=1);else{for(n=1e4,o=null,c=d.floating||this._isFloating(this.currentItem),a=c?"left":"top",r=c?"width":"height",u=c?"pageX":"pageY",s=this.items.length-1;s>=0;s--)t.contains(this.containers[p].element[0],this.items[s].item[0])&&this.items[s].item[0]!==this.currentItem[0]&&(l=this.items[s].item.offset()[a],h=!1,e[u]-l>this.items[s][r]/2&&(h=!0),n>Math.abs(e[u]-l)&&(n=Math.abs(e[u]-l),o=this.items[s],this.direction=h?"up":"down"));if(!o&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[p])return this.currentContainer.containerCache.over||(this.containers[p]._trigger("over",e,this._uiHash()),this.currentContainer.containerCache.over=1),void 0;o?this._rearrange(e,o,null,!0):this._rearrange(e,null,this.containers[p].element,!0),this._trigger("change",e,this._uiHash()),this.containers[p]._trigger("change",e,this._uiHash(this)),this.currentContainer=this.containers[p],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[p]._trigger("over",e,this._uiHash(this)),this.containers[p].containerCache.over=1}},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||t("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===this.document[0].body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.currentItem.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;"parent"===n.containment&&(n.containment=this.helper[0].parentNode),("document"===n.containment||"window"===n.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,"document"===n.containment?this.document.width():this.window.width()-this.helperProportions.width-this.margins.left,("document"===n.containment?this.document.height()||document.body.parentNode.scrollHeight:this.window.height()||this.document[0].body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(n.containment)||(e=t(n.containment)[0],i=t(n.containment).offset(),s="hidden"!==t(e).css("overflow"),this.containment=[i.left+(parseInt(t(e).css("borderLeftWidth"),10)||0)+(parseInt(t(e).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(t(e).css("borderTopWidth"),10)||0)+(parseInt(t(e).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(e.scrollWidth,e.offsetWidth):e.offsetWidth)-(parseInt(t(e).css("borderLeftWidth"),10)||0)-(parseInt(t(e).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(e.scrollHeight,e.offsetHeight):e.offsetHeight)-(parseInt(t(e).css("borderTopWidth"),10)||0)-(parseInt(t(e).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(n[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():o?0:n.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():o?0:n.scrollLeft())*s}
|
7
|
+
},_generatePosition:function(e){var i,s,n=this.options,o=e.pageX,a=e.pageY,r="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,l=/(html|body)/i.test(r[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(e.pageX-this.offset.click.left<this.containment[0]&&(o=this.containment[0]+this.offset.click.left),e.pageY-this.offset.click.top<this.containment[1]&&(a=this.containment[1]+this.offset.click.top),e.pageX-this.offset.click.left>this.containment[2]&&(o=this.containment[2]+this.offset.click.left),e.pageY-this.offset.click.top>this.containment[3]&&(a=this.containment[3]+this.offset.click.top)),n.grid&&(i=this.originalPageY+Math.round((a-this.originalPageY)/n.grid[1])*n.grid[1],a=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-n.grid[1]:i+n.grid[1]:i,s=this.originalPageX+Math.round((o-this.originalPageX)/n.grid[0])*n.grid[0],o=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-n.grid[0]:s+n.grid[0]:s)),{top:a-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():l?0:r.scrollTop()),left:o-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():l?0:r.scrollLeft())}},_rearrange:function(t,e,i,s){i?i[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?e.item[0]:e.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter;this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){function i(t,e,i){return function(s){i._trigger(t,s,e._uiHash(e))}}this.reverting=!1;var s,n=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(s in this._storedCSS)("auto"===this._storedCSS[s]||"static"===this._storedCSS[s])&&(this._storedCSS[s]="");this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!e&&n.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||n.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(n.push(function(t){this._trigger("remove",t,this._uiHash())}),n.push(function(t){return function(e){t._trigger("receive",e,this._uiHash(this))}}.call(this,this.currentContainer)),n.push(function(t){return function(e){t._trigger("update",e,this._uiHash(this))}}.call(this,this.currentContainer)))),s=this.containers.length-1;s>=0;s--)e||n.push(i("deactivate",this,this.containers[s])),this.containers[s].containerCache.over&&(n.push(i("out",this,this.containers[s])),this.containers[s].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,e||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.cancelHelperRemoval||(this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null),!e){for(s=0;n.length>s;s++)n[s].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!this.cancelHelperRemoval},_trigger:function(){t.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(e){var i=e||this;return{helper:i.helper,placeholder:i.placeholder||t([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:e?e.element:null}}})});
|
@@ -262,6 +262,9 @@ $(function() {
|
|
262
262
|
// Init textareas
|
263
263
|
$('textarea',c).trigger('input');
|
264
264
|
|
265
|
+
// Init multiple select with asmSelect
|
266
|
+
$('select[multiple]').asmSelect({ sortable: true, removeLabel: '×' });
|
267
|
+
|
265
268
|
}; // End - Init column
|
266
269
|
|
267
270
|
// Init finder
|
@@ -4,6 +4,8 @@
|
|
4
4
|
<head>
|
5
5
|
<meta charset="utf-8" />
|
6
6
|
<title><%= settings.meta_title %></title>
|
7
|
+
<link rel="stylesheet" href="<%= request.script_name %>/__assets__/css/jquery-ui.min.css" type="text/css" media='screen' />
|
8
|
+
<link rel="stylesheet" href="<%= request.script_name %>/__assets__/css/asmselect.css" type="text/css" media='screen' />
|
7
9
|
<link rel="stylesheet" href="<%= request.script_name %>/__assets__/css/main.css" type="text/css" media='screen' />
|
8
10
|
</head>
|
9
11
|
<body>
|
@@ -40,10 +42,7 @@
|
|
40
42
|
|
41
43
|
<script id="template-document" type="x-tmpl-mustache">
|
42
44
|
<li class='admin-list-item' data-id='{{id}}'>
|
43
|
-
<header>
|
44
|
-
{{#sort_field}}
|
45
|
-
<span class='handle' title='Drag and drop'>↕</span>
|
46
|
-
{{/sort_field}}
|
45
|
+
<header class='{{#sort_field}}handle{{/sort_field}}' title='{{#sort_field}}Drag and drop{{/sort_field}}'>
|
47
46
|
<button type='button' class='admin-delete' title='Delete' value='<%= request.script_name %>/api/{{admin_url}}'>×</button>
|
48
47
|
</header>
|
49
48
|
<a href="<%= request.script_name %>/form/{{admin_url}}" class='column-push' title='Edit'>
|
@@ -75,7 +74,7 @@
|
|
75
74
|
<script id="template-nested-form" type="x-tmpl-mustache">
|
76
75
|
<li>
|
77
76
|
<header>
|
78
|
-
<span class='handle' title='Drag and drop'>↕</span><button type='button' class='admin-delete-nested' title='Delete'>×</button>
|
77
|
+
<span class='handle handle-button' title='Drag and drop'>↕</span><button type='button' class='admin-delete-nested' title='Delete'>×</button>
|
79
78
|
</header>
|
80
79
|
{{#custom_partial_or_default}}template_form_fields{{/custom_partial_or_default}}
|
81
80
|
</li>
|
@@ -116,7 +115,10 @@
|
|
116
115
|
</script>
|
117
116
|
|
118
117
|
<script id="template-select-field" type="x-tmpl-mustache">
|
119
|
-
|
118
|
+
{{#multiple}}
|
119
|
+
<input type='hidden' name='{{input_name}}' value='nil' />
|
120
|
+
{{/multiple}}
|
121
|
+
<select name='{{input_name}}' {{#multiple}}multiple title='?'{{/multiple}}{{{build_input_attributes}}}>
|
120
122
|
{{#select_options}}
|
121
123
|
<option value='{{value}}' {{#selected}}selected{{/selected}}>{{description}}</option>
|
122
124
|
{{/select_options}}
|
@@ -150,9 +152,11 @@
|
|
150
152
|
|
151
153
|
<!-- JS -->
|
152
154
|
<script src="//code.jquery.com/jquery-1.10.2.min.js" type="text/javascript" charset="utf-8"></script>
|
155
|
+
<script src="<%= request.script_name %>/__assets__/js/jquery-ui.min.js" type="text/javascript" charset="utf-8"></script>
|
153
156
|
<script src="<%= request.script_name %>/__assets__/js/mustache.js" type="text/javascript" charset="utf-8"></script>
|
154
157
|
<script src="<%= request.script_name %>/__assets__/js/columnav.js" type="text/javascript" charset="utf-8"></script>
|
155
|
-
<script src="<%= request.script_name
|
158
|
+
<%# <script src="<%= request.script_name %1>/__assets__/js/sortable.js" type="text/javascript" charset="utf-8"></script> %>
|
159
|
+
<script src="<%= request.script_name %>/__assets__/js/asmselect.js" type="text/javascript" charset="utf-8"></script>
|
156
160
|
<script type="text/javascript">
|
157
161
|
window.admin_path = "<%= request.script_name %>";
|
158
162
|
window.index_path = "<%= settings.index_path %>";
|
data/lib/populate_me/document.rb
CHANGED
@@ -99,7 +99,7 @@ module PopulateMe
|
|
99
99
|
persistent_instance_variables.inject({'_class'=>self.class.name}) do |h,var|
|
100
100
|
k = var.to_s[1..-1]
|
101
101
|
v = instance_variable_get var
|
102
|
-
if v
|
102
|
+
if is_nested_docs?(v)
|
103
103
|
h[k] = v.map(&:to_h)
|
104
104
|
else
|
105
105
|
h[k] = v
|
@@ -118,7 +118,7 @@ module PopulateMe
|
|
118
118
|
persistent_instance_variables.map do |var|
|
119
119
|
instance_variable_get var
|
120
120
|
end.find_all do |val|
|
121
|
-
val
|
121
|
+
is_nested_docs?(val)
|
122
122
|
end.flatten
|
123
123
|
end
|
124
124
|
|
@@ -152,7 +152,7 @@ module PopulateMe
|
|
152
152
|
hash.delete('_class')
|
153
153
|
hash.each do |k,v|
|
154
154
|
getter = k.to_sym
|
155
|
-
if v
|
155
|
+
if is_nested_hash_docs?(v)
|
156
156
|
break unless respond_to?(getter)
|
157
157
|
__send__(getter).clear
|
158
158
|
v.each do |d|
|
@@ -173,6 +173,19 @@ module PopulateMe
|
|
173
173
|
end
|
174
174
|
self.settings = OpenStruct.new
|
175
175
|
|
176
|
+
private
|
177
|
+
|
178
|
+
def is_nested_docs? val
|
179
|
+
# Differenciate nested docs array from other king of array
|
180
|
+
val.is_a?(Array) and !val.empty? and val[0].is_a?(PopulateMe::Document)
|
181
|
+
end
|
182
|
+
|
183
|
+
def is_nested_hash_docs? val
|
184
|
+
# Differenciate nested docs array from other king of array
|
185
|
+
# when from a hash
|
186
|
+
val.is_a?(Array) and !val.empty? and val[0].is_a?(Hash) and val[0].has_key?('_class')
|
187
|
+
end
|
188
|
+
|
176
189
|
end
|
177
190
|
end
|
178
191
|
|
@@ -40,10 +40,8 @@ module PopulateMe
|
|
40
40
|
}
|
41
41
|
self.class.complete_field_options :_class, class_item
|
42
42
|
items = self.class.fields.inject([class_item]) do |out,(k,item)|
|
43
|
-
item = item.dup
|
44
43
|
if item[:form_field]
|
45
|
-
outcast
|
46
|
-
out << item
|
44
|
+
out << outcast(k, item, o)
|
47
45
|
end
|
48
46
|
out
|
49
47
|
end
|
@@ -8,23 +8,34 @@ module PopulateMe
|
|
8
8
|
# Therefore, it is a complement to the AdminAdapter module.
|
9
9
|
|
10
10
|
def outcast field, item, o={}
|
11
|
+
item = item.dup
|
11
12
|
item[:input_name] = "#{o[:input_name_prefix]}[#{item[:field_name]}]"
|
12
13
|
unless item[:type]==:list
|
13
14
|
WebUtils.ensure_key! item, :input_value, self.__send__(field)
|
14
15
|
end
|
15
16
|
meth = "outcast_#{item[:type]}".to_sym
|
16
|
-
|
17
|
+
if respond_to?(meth)
|
18
|
+
__send__(meth, field, item, o)
|
19
|
+
else
|
20
|
+
item
|
21
|
+
end
|
17
22
|
end
|
18
23
|
|
19
24
|
def outcast_list field, item, o={}
|
25
|
+
item = item.dup
|
20
26
|
item[:items] = self.__send__(field).map do |nested|
|
21
27
|
nested.to_admin_form(o.merge(input_name_prefix: item[:input_name]+'[]'))
|
22
28
|
end
|
29
|
+
item
|
23
30
|
end
|
24
31
|
|
25
32
|
def outcast_select field, item, o={}
|
33
|
+
item = item.dup
|
26
34
|
unless item[:select_options].nil?
|
27
|
-
|
35
|
+
if item[:multiple]==true
|
36
|
+
item[:input_name] = item[:input_name]+'[]'
|
37
|
+
end
|
38
|
+
opts = WebUtils.deep_copy(WebUtils.get_value(item[:select_options],self))
|
28
39
|
opts.map! do |opt|
|
29
40
|
if opt.is_a?(String)||opt.is_a?(Symbol)
|
30
41
|
opt = [opt.to_s.capitalize,opt]
|
@@ -32,15 +43,30 @@ module PopulateMe
|
|
32
43
|
if opt.is_a?(Array)
|
33
44
|
opt = {description: opt[0].to_s, value: opt[1].to_s}
|
34
45
|
end
|
35
|
-
|
46
|
+
if item[:input_value].respond_to?(:include?)
|
47
|
+
opt[:selected] = true if item[:input_value].include?(opt[:value])
|
48
|
+
else
|
49
|
+
opt[:selected] = true if item[:input_value]==opt[:value]
|
50
|
+
end
|
36
51
|
opt
|
37
52
|
end
|
53
|
+
if item[:multiple]
|
54
|
+
(item[:input_value]||[]).reverse.each do |iv|
|
55
|
+
opt = opts.find{|opt| opt[:value]==iv }
|
56
|
+
opts.unshift(opts.delete(opt)) unless opt.nil?
|
57
|
+
end
|
58
|
+
end
|
38
59
|
item[:select_options] = opts
|
60
|
+
item
|
61
|
+
else
|
62
|
+
item
|
39
63
|
end
|
40
64
|
end
|
41
65
|
|
42
66
|
def outcast_attachment field, item, o={}
|
67
|
+
item = item.dup
|
43
68
|
item[:url] = self.attachment(field).url
|
69
|
+
item
|
44
70
|
end
|
45
71
|
|
46
72
|
end
|
@@ -101,6 +101,19 @@ module PopulateMe
|
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
|
+
def to_select_options o={}
|
105
|
+
proc do
|
106
|
+
items = self.admin_find(query: {}, fields: [self.id_string_key, self.label_field])
|
107
|
+
output = items.sort_by do |i|
|
108
|
+
i.to_s.downcase
|
109
|
+
end.map do |i|
|
110
|
+
[i.to_s, i.id]
|
111
|
+
end
|
112
|
+
output.unshift(['?','']) if o[:allow_empty]
|
113
|
+
output
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
104
117
|
end
|
105
118
|
|
106
119
|
end
|
data/lib/populate_me/version.rb
CHANGED
@@ -0,0 +1,211 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'populate_me/document'
|
3
|
+
require 'populate_me/attachment'
|
4
|
+
|
5
|
+
class Outcasted < PopulateMe::Document
|
6
|
+
set :default_attachment_class, PopulateMe::Attachment
|
7
|
+
|
8
|
+
field :name
|
9
|
+
field :size, type: :select, select_options: [
|
10
|
+
{description: 'small', value: 's'},
|
11
|
+
{description: 'medium', value: 'm'},
|
12
|
+
{description: 'large', value: 'l'}
|
13
|
+
]
|
14
|
+
field :tags, type: :select, select_options: ['art','sport','science'], multiple: true
|
15
|
+
field :related_properties, type: :select, select_options: ['prop1','prop2','prop3'], multiple: true
|
16
|
+
field :pdf, type: :attachment
|
17
|
+
field :authors, type: :list
|
18
|
+
field :weirdo, type: :strange
|
19
|
+
|
20
|
+
def get_size_options
|
21
|
+
[
|
22
|
+
[:small, :s],
|
23
|
+
[:medium, :m],
|
24
|
+
[:large, :l]
|
25
|
+
]
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
class Outcasted::Author < PopulateMe::Document
|
31
|
+
field :name
|
32
|
+
end
|
33
|
+
|
34
|
+
describe PopulateMe::Document, 'Outcasting' do
|
35
|
+
|
36
|
+
parallelize_me!
|
37
|
+
|
38
|
+
describe '#outcast' do
|
39
|
+
|
40
|
+
it 'Keeps the original info unchanged' do
|
41
|
+
original = Outcasted.fields[:name]
|
42
|
+
output = Outcasted.new.outcast(:name, original, {input_name_prefix: 'data'})
|
43
|
+
refute original.equal?(output)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'Adds input_name_prefix to input_name' do
|
47
|
+
original = Outcasted.fields[:name]
|
48
|
+
output = Outcasted.new.outcast(:name, original, {input_name_prefix: 'data'})
|
49
|
+
assert_equal 'data[name]', output[:input_name]
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'Sets input_value to the field value' do
|
53
|
+
original = Outcasted.fields[:name]
|
54
|
+
outcasted = Outcasted.new
|
55
|
+
outcasted.name = 'Thomas'
|
56
|
+
output = outcasted.outcast(:name, original, {input_name_prefix: 'data'})
|
57
|
+
assert_equal 'Thomas', output[:input_value]
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#outcast_list' do
|
63
|
+
|
64
|
+
it 'Has no value and an empty list of items when list is empty' do
|
65
|
+
original = Outcasted.fields[:authors]
|
66
|
+
output = Outcasted.new.outcast(:authors, original, {input_name_prefix: 'data'})
|
67
|
+
assert_nil output[:input_value]
|
68
|
+
assert_equal [], output[:items]
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'Nests the items in the list with their own nested prefix' do
|
72
|
+
original = Outcasted.fields[:authors]
|
73
|
+
outcasted = Outcasted.new
|
74
|
+
outcasted.authors.push(Outcasted::Author.new(name: 'Bob'))
|
75
|
+
outcasted.authors.push(Outcasted::Author.new(name: 'Mould'))
|
76
|
+
output = outcasted.outcast(:authors, original, {input_name_prefix: 'data'})
|
77
|
+
assert_nil output[:input_value]
|
78
|
+
assert_equal 2, output[:items].size
|
79
|
+
first_item = output[:items][0][:fields]
|
80
|
+
assert_equal 'data[authors][][name]', first_item[1][:input_name]
|
81
|
+
assert_equal 'Bob', first_item[1][:input_value]
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#outcast_select' do
|
87
|
+
|
88
|
+
def formated_options? original, output
|
89
|
+
assert_equal [ {description: 'small', value: 's'}, {description: 'medium', value: 'm'}, {description: 'large', value: 'l'} ], output[:select_options]
|
90
|
+
refute original[:select_options].equal?(output[:select_options])
|
91
|
+
assert output[:select_options].all?{|o|!o[:selected]}
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'Leaves the options as they are when they are already formated' do
|
95
|
+
original = Outcasted.fields[:size]
|
96
|
+
output = Outcasted.new.outcast(:size, original, {input_name_prefix: 'data'})
|
97
|
+
formated_options?(original, output)
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'Formats the options when it is a 2 strings array' do
|
101
|
+
original = Outcasted.fields[:size].dup
|
102
|
+
original[:select_options] = [
|
103
|
+
[:small, :s],
|
104
|
+
[:medium, :m],
|
105
|
+
[:large, :l]
|
106
|
+
]
|
107
|
+
output = Outcasted.new.outcast(:size, original, {input_name_prefix: 'data'})
|
108
|
+
formated_options?(original, output)
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'Formats the options when they come from a proc' do
|
112
|
+
original = Outcasted.fields[:size].dup
|
113
|
+
original[:select_options] = proc{[
|
114
|
+
[:small, :s],
|
115
|
+
[:medium, :m],
|
116
|
+
[:large, :l]
|
117
|
+
]}
|
118
|
+
output = Outcasted.new.outcast(:size, original, {input_name_prefix: 'data'})
|
119
|
+
formated_options?(original, output)
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'Formats the options when they come from a symbol' do
|
123
|
+
original = Outcasted.fields[:size].dup
|
124
|
+
original[:select_options] = :get_size_options
|
125
|
+
output = Outcasted.new.outcast(:size, original, {input_name_prefix: 'data'})
|
126
|
+
formated_options?(original, output)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'Formats options when it comes from a simple string' do
|
130
|
+
original = Outcasted.fields[:size].dup
|
131
|
+
original[:select_options] = [:small,:medium,:large]
|
132
|
+
output = Outcasted.new.outcast(:size, original, {input_name_prefix: 'data'})
|
133
|
+
assert_equal [ {description: 'Small', value: 'small'}, {description: 'Medium', value: 'medium'}, {description: 'Large', value: 'large'} ], output[:select_options]
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'Selects the input value' do
|
137
|
+
original = Outcasted.fields[:size]
|
138
|
+
outcasted = Outcasted.new size: 'm'
|
139
|
+
output = outcasted.outcast(:size, original, {input_name_prefix: 'data'})
|
140
|
+
assert_equal 1, output[:select_options].select{|o|o[:selected]}.size
|
141
|
+
assert output[:select_options].find{|o|o[:value]=='m'}[:selected]
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'Adds [] at the end of input_name if multiple is true' do
|
145
|
+
original = Outcasted.fields[:tags]
|
146
|
+
output = Outcasted.new.outcast(:tags, original, {input_name_prefix: 'data'})
|
147
|
+
assert_equal 'data[tags][]', output[:input_name]
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'Selects multiple options when input_value is an array' do
|
151
|
+
original = Outcasted.fields[:tags]
|
152
|
+
outcasted = Outcasted.new tags: ['art','science']
|
153
|
+
output = outcasted.outcast(:tags, original, {input_name_prefix: 'data'})
|
154
|
+
assert output[:select_options].find{|o|o[:value]=='art'}[:selected]
|
155
|
+
assert output[:select_options].find{|o|o[:value]=='science'}[:selected]
|
156
|
+
refute output[:select_options].find{|o|o[:value]=='sport'}[:selected]
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'Orders input values at the begining when multiple options' do
|
160
|
+
original = Outcasted.fields[:related_properties]
|
161
|
+
|
162
|
+
# Normal
|
163
|
+
outcasted = Outcasted.new related_properties: ['prop3','prop1']
|
164
|
+
output = outcasted.outcast(:related_properties, original, {input_name_prefix: 'data'})
|
165
|
+
assert_equal 'prop3', output[:select_options][0][:value]
|
166
|
+
assert output[:select_options][0][:selected]
|
167
|
+
assert_equal 'prop1', output[:select_options][1][:value]
|
168
|
+
assert output[:select_options][1][:selected]
|
169
|
+
assert_equal 'prop2', output[:select_options][2][:value]
|
170
|
+
refute output[:select_options][2][:selected]
|
171
|
+
|
172
|
+
# When input_value is nil
|
173
|
+
outcasted = Outcasted.new
|
174
|
+
output = outcasted.outcast(:related_properties, original, {input_name_prefix: 'data'})
|
175
|
+
assert_equal 'prop1', output[:select_options][0][:value]
|
176
|
+
refute output[:select_options][0][:selected]
|
177
|
+
assert_equal 'prop2', output[:select_options][1][:value]
|
178
|
+
refute output[:select_options][1][:selected]
|
179
|
+
assert_equal 'prop3', output[:select_options][2][:value]
|
180
|
+
refute output[:select_options][2][:selected]
|
181
|
+
|
182
|
+
# When input_value has a non existing value
|
183
|
+
outcasted = Outcasted.new related_properties: ['stale','prop2']
|
184
|
+
output = outcasted.outcast(:related_properties, original, {input_name_prefix: 'data'})
|
185
|
+
assert_equal 'prop2', output[:select_options][0][:value]
|
186
|
+
assert output[:select_options][0][:selected]
|
187
|
+
assert_equal 'prop1', output[:select_options][1][:value]
|
188
|
+
refute output[:select_options][1][:selected]
|
189
|
+
assert_equal 'prop3', output[:select_options][2][:value]
|
190
|
+
refute output[:select_options][2][:selected]
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
|
195
|
+
describe '#outcast_attachment' do
|
196
|
+
|
197
|
+
it 'Sets url' do
|
198
|
+
original = Outcasted.fields[:pdf]
|
199
|
+
outcasted = Outcasted.new
|
200
|
+
output = outcasted.outcast(:pdf, original, {input_name_prefix: 'data'})
|
201
|
+
assert_nil output[:url]
|
202
|
+
|
203
|
+
outcasted.pdf = 'guidelines.pdf'
|
204
|
+
output = outcasted.outcast(:pdf, original, {input_name_prefix: 'data'})
|
205
|
+
assert_equal outcasted.attachment(:pdf).url, output[:url]
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
211
|
+
|
@@ -77,5 +77,47 @@ describe PopulateMe::Document, 'Schema' do
|
|
77
77
|
|
78
78
|
end
|
79
79
|
|
80
|
+
describe '::to_select_options' do
|
81
|
+
|
82
|
+
class Selectoptionable < PopulateMe::Document
|
83
|
+
field :name
|
84
|
+
field :slug
|
85
|
+
label :slug
|
86
|
+
end
|
87
|
+
|
88
|
+
before do
|
89
|
+
Selectoptionable.documents = []
|
90
|
+
Selectoptionable.new(id: '1', name: 'Joe', slug: 'joe').save
|
91
|
+
Selectoptionable.new(id: '2', name: 'William', slug: 'william').save
|
92
|
+
Selectoptionable.new(id: '3', name: 'Jack', slug: 'jack').save
|
93
|
+
Selectoptionable.new(id: '4', name: 'Averell', slug: 'averell').save
|
94
|
+
end
|
95
|
+
|
96
|
+
after do
|
97
|
+
Selectoptionable.documents = []
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'Formats all items for a select_options' do
|
101
|
+
output_proc = Selectoptionable.to_select_options
|
102
|
+
assert output_proc.is_a?(Proc)
|
103
|
+
output = output_proc.call
|
104
|
+
assert_equal 4, output.size
|
105
|
+
assert output.all?{|o| o.is_a?(Array) and o.size==2}
|
106
|
+
assert_equal '1', output.find{|o|o[0]=='joe'}[1]
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'Puts items in alphabetical order of their label' do
|
110
|
+
output= Selectoptionable.to_select_options.call
|
111
|
+
assert_equal ['averell', '4'], output[0]
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'Has an option for prepending empty choice' do
|
115
|
+
output= Selectoptionable.to_select_options(allow_empty: true).call
|
116
|
+
assert_equal ['?', ''], output[0]
|
117
|
+
assert_equal ['averell', '4'], output[1]
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
80
122
|
end
|
81
123
|
|
@@ -6,6 +6,8 @@ class Person < PopulateMe::Document
|
|
6
6
|
field :shared, type: :boolean
|
7
7
|
field :age, type: :integer
|
8
8
|
field :salary, type: :price
|
9
|
+
field :size, type: :select, select_option: ['S','M','L']
|
10
|
+
field :categories, type: :select, select_option: ['A','B','C'], multiple: true
|
9
11
|
field :dob, type: :date
|
10
12
|
field :when, type: :datetime
|
11
13
|
end
|
@@ -85,6 +87,14 @@ describe PopulateMe::Document, 'Typecasting' do
|
|
85
87
|
end
|
86
88
|
end
|
87
89
|
|
90
|
+
describe "Field has type :select" do
|
91
|
+
it "Removes 'nil' string if multiple/array" do
|
92
|
+
assert_equal 'M', subject.typecast(:size, 'M')
|
93
|
+
assert_equal ['A','B'], subject.typecast(:categories, ['A','B'])
|
94
|
+
assert_equal ['A','B'], subject.typecast(:categories, ['nil','A','B'])
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
88
98
|
describe "Field has type :date" do
|
89
99
|
it "Parses the date with Date.parse" do
|
90
100
|
assert_equal Date.parse('10/11/1979'), subject.typecast(:dob,'10/11/1979')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: populate-me
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mickael Riga
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-02-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: web-utils
|
@@ -195,8 +195,12 @@ files:
|
|
195
195
|
- example/config.ru
|
196
196
|
- lib/populate_me.rb
|
197
197
|
- lib/populate_me/admin.rb
|
198
|
+
- lib/populate_me/admin/__assets__/css/asmselect.css
|
199
|
+
- lib/populate_me/admin/__assets__/css/jquery-ui.min.css
|
198
200
|
- lib/populate_me/admin/__assets__/css/main.css
|
201
|
+
- lib/populate_me/admin/__assets__/js/asmselect.js
|
199
202
|
- lib/populate_me/admin/__assets__/js/columnav.js
|
203
|
+
- lib/populate_me/admin/__assets__/js/jquery-ui.min.js
|
200
204
|
- lib/populate_me/admin/__assets__/js/main.js
|
201
205
|
- lib/populate_me/admin/__assets__/js/mustache.js
|
202
206
|
- lib/populate_me/admin/__assets__/js/sortable.js
|
@@ -225,6 +229,7 @@ files:
|
|
225
229
|
- test/test_document.rb
|
226
230
|
- test/test_document_admin_adapter.rb
|
227
231
|
- test/test_document_callbacks.rb
|
232
|
+
- test/test_document_outcasting.rb
|
228
233
|
- test/test_document_persistence.rb
|
229
234
|
- test/test_document_schema.rb
|
230
235
|
- test/test_document_typecasting.rb
|
@@ -265,6 +270,7 @@ test_files:
|
|
265
270
|
- test/test_document.rb
|
266
271
|
- test/test_document_admin_adapter.rb
|
267
272
|
- test/test_document_callbacks.rb
|
273
|
+
- test/test_document_outcasting.rb
|
268
274
|
- test/test_document_persistence.rb
|
269
275
|
- test/test_document_schema.rb
|
270
276
|
- test/test_document_typecasting.rb
|