populate-me 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/README.md +9 -0
  2. data/lib/populate_me/control/_public/css/main.css +180 -0
  3. data/lib/populate_me/control/_public/css/plugin.asmselect.css +63 -0
  4. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-bg_flat_30_cccccc_40x100.png +0 -0
  5. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-bg_flat_50_5c5c5c_40x100.png +0 -0
  6. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-bg_glass_20_555555_1x400.png +0 -0
  7. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-bg_glass_40_0078a3_1x400.png +0 -0
  8. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-bg_glass_40_ffc73d_1x400.png +0 -0
  9. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-bg_gloss-wave_25_333333_500x100.png +0 -0
  10. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-bg_highlight-soft_80_eeeeee_1x100.png +0 -0
  11. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-bg_inset-soft_25_000000_1x100.png +0 -0
  12. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-bg_inset-soft_30_f58400_1x100.png +0 -0
  13. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-icons_222222_256x240.png +0 -0
  14. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-icons_4b8e0b_256x240.png +0 -0
  15. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-icons_a83300_256x240.png +0 -0
  16. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-icons_cccccc_256x240.png +0 -0
  17. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-icons_ffffff_256x240.png +0 -0
  18. data/lib/populate_me/control/_public/css/ui-darkness/jquery-ui-1.8.17.custom.css +430 -0
  19. data/lib/populate_me/control/_public/img/handle-pattern.png +0 -0
  20. data/lib/populate_me/control/_public/img/icons-cms.png +0 -0
  21. data/lib/populate_me/control/_public/img/placeholder.png +0 -0
  22. data/lib/populate_me/control/_public/img/placeholder.stash_thumb.gif +0 -0
  23. data/lib/populate_me/control/_public/img/placeholder.stash_thumb.png +0 -0
  24. data/lib/populate_me/control/_public/img/small-loader.gif +0 -0
  25. data/lib/populate_me/control/_public/js/addon.timepicker.js +20 -0
  26. data/lib/populate_me/control/_public/js/jquery-ui.js +114 -0
  27. data/lib/populate_me/control/_public/js/jquery.js +167 -0
  28. data/lib/populate_me/control/_public/js/jquery.mustache.js +559 -0
  29. data/lib/populate_me/control/_public/js/main.js +144 -0
  30. data/lib/populate_me/control/_public/js/plugin.asmselect.js +407 -0
  31. data/lib/populate_me/control/_public/js/plugin.form.js +11 -0
  32. data/lib/populate_me/control/_public/js/plugin.quicksearch.js +1 -0
  33. data/lib/populate_me/control/_public/js/plugin.underwood.js +4 -0
  34. data/lib/populate_me/control/views/layout.erb +77 -0
  35. data/lib/populate_me/control.rb +193 -0
  36. data/lib/populate_me/mongo/backend_api_plug.rb +77 -0
  37. data/lib/populate_me/mongo/crushyform.rb +225 -0
  38. data/lib/populate_me/mongo/mutation.rb +266 -0
  39. data/lib/populate_me/mongo/plug.rb +132 -0
  40. data/lib/populate_me/mongo/stash.rb +119 -0
  41. data/lib/populate_me/mongo.rb +1 -0
  42. data/populate-me.gemspec +14 -0
  43. metadata +120 -0
@@ -0,0 +1,144 @@
1
+ // Array last()
2
+ Array.prototype.last = function() {
3
+ return this[this.length-1];
4
+ };
5
+
6
+ $(function() {
7
+ // Templates
8
+ var template_menu = $('#template-menu').html();
9
+ var template_nutshell = $('#template-nutshell').html();
10
+ var template_nut_tree = $('#template-nut-tree').html();
11
+
12
+ // Stack
13
+ // For each step, the stack record an object with the new URL and other values like scroll
14
+ var stack = [];
15
+ var pushstack = function(url,parent_name) {
16
+ if(stack.length!=0) { // record state
17
+ stack.last().scroll = $(window).scrollTop();
18
+ stack.last().search = $search.val();
19
+ $search.val('');
20
+ }
21
+ stack.push({url: url, parent_name: parent_name});
22
+ load_content();
23
+ };
24
+ var popstack = function() {
25
+ if(stack.length>1) {
26
+ stack.pop();
27
+ load_content(true);
28
+ }
29
+ };
30
+
31
+ // Quicksearch
32
+ var $search = $('#search');
33
+ var search_opts = {
34
+ onAfter: function() {
35
+ if ($search.val()=='' && stack.length!=0 && stack.last().sortable) {
36
+ $('.nutshell-bar').addClass('sortable-handle');
37
+ } else {
38
+ $('.nutshell-bar').removeClass('sortable-handle');
39
+ }
40
+ }
41
+ }
42
+ var qs;
43
+
44
+ // Content div
45
+ var $content = $('#content');
46
+ var $page_title = $('#page-title');
47
+ var content_callback = function() {
48
+ // Cancel form
49
+ $(':submit[value=SAVE]').after(" or <a href='javascript:;' class='popstack cancel'>CANCEL</a>");
50
+ // reset previous state
51
+ $search.val(stack.last().search);
52
+ $('#search').keyup();
53
+ $(window).scrollTop(stack.last().scroll);
54
+ // Sortable
55
+ $('.sortable').sortable({
56
+ stop: function() { $.ajax({
57
+ url: admin_path+'/'+stack.last().class_name,
58
+ data: $(this).sortable('serialize'),
59
+ type: 'PUT'
60
+ });
61
+ },
62
+ items: '.nutshell',
63
+ handle:'.sortable-handle'
64
+ });
65
+ // Date/Time pickers
66
+ $('.datepicker').datepicker({dateFormat: 'yy-mm-dd'});
67
+ $('.timepicker').timepicker({showSecond: true,timeFormat: 'hh:mm:ss'});
68
+ $('.datetimepicker').datetimepicker({showSecond: true,dateFormat: 'yy-mm-dd',timeFormat: 'hh:mm:ss'});
69
+ // Multiple select with asmSelect
70
+ $(".asm-select").asmSelect({ sortable: true });
71
+ };
72
+ var load_content = function(poping) {
73
+ var url = stack.last().url;
74
+ var parent_name = stack.last().parent_name;
75
+ $.get(url, function(data) {
76
+ var query_string = url.match(/\?.*$/);
77
+ data.query_string = query_string ? query_string[0].replace(/filter\[/g,'model[') : '';
78
+ var direction = poping ? '200px' : '-200px';
79
+ $content.animate({left: direction, opacity: 0}, function() {
80
+ $content.css({left: '0px'});
81
+ if (data.action=='form') $content.html(data.form);
82
+ if (data.action=='menu') $content.html($.mustache(template_menu, data));
83
+ if (data.action=='list') {
84
+ $content.html($.mustache(template_nut_tree, data, {nutshell: template_nutshell}));
85
+ stack.last().class_name = data.class_name
86
+ stack.last().sortable = data.sortable
87
+ qs = $search.quicksearch($(".nutshell"), search_opts);
88
+ }
89
+ content_callback();
90
+ var new_title = data.page_title;
91
+ if (parent_name) new_title = new_title+"<br><small>for "+parent_name+"</small>";
92
+ //var new_title = parent_name ? data.page_title+' for '+parent_name : data.page_title;
93
+ $page_title.html(new_title);
94
+ $content.animate({opacity: 1});
95
+ });
96
+ });
97
+ };
98
+
99
+ // Stack links
100
+ $(".pushstack").live('click', function() {
101
+ var $this = $(this);
102
+ if ($(this).hasClass('further-btn')) var parent_name = $this.parents('.nutshell').find('.nutshell-title').text();
103
+ pushstack(this.href, parent_name);
104
+ return false;
105
+ });
106
+ $(".popstack").live('click', function() {
107
+ popstack();
108
+ return false;
109
+ });
110
+
111
+ // Ajax form
112
+ $('.backend-form').live('submit', function() {
113
+ var $form = $(this);
114
+ $form.find(':submit').after("<img src='"+admin_path+"/_public/img/small-loader.gif' />").remove();
115
+ $form.ajaxSubmit({
116
+ success: function(data) {
117
+ if (data.action=='save' || data.match(/ok/i)) { // Success
118
+ popstack();
119
+ } else {
120
+ $content.html(data.form);
121
+ content_callback();
122
+ }
123
+ }
124
+ });
125
+ return false;
126
+ });
127
+
128
+ // Ajax delete
129
+ $('.nutshell-delete').live('click', function() {
130
+ var $this = $(this);
131
+ if (confirm('Are you sure you want to delete this ?')) {
132
+ $.ajax({
133
+ url: this.href,
134
+ type: 'DELETE',
135
+ success: function() { $this.parents('.nutshell').fadeOut(function() { $(this).remove(); }); }
136
+ });
137
+ }
138
+ return false;
139
+ });
140
+
141
+ // Init
142
+ pushstack(admin_path+'/menu');
143
+ });
144
+
@@ -0,0 +1,407 @@
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
+ (function($) {
13
+
14
+ $.fn.asmSelect = function(customOptions) {
15
+
16
+ var options = {
17
+
18
+ listType: 'ol', // Ordered list 'ol', or unordered list 'ul'
19
+ sortable: false, // Should the list be sortable?
20
+ highlight: false, // Use the highlight feature?
21
+ animate: false, // Animate the the adding/removing of items in the list?
22
+ addItemTarget: 'bottom', // Where to place new selected items in list: top or bottom
23
+ hideWhenAdded: false, // Hide the option when added to the list? works only in FF
24
+ debugMode: false, // Debug mode keeps original select visible
25
+
26
+ removeLabel: 'remove', // Text used in the "remove" link
27
+ highlightAddedLabel: 'Added: ', // Text that precedes highlight of added item
28
+ highlightRemovedLabel: 'Removed: ', // Text that precedes highlight of removed item
29
+
30
+ containerClass: 'asmContainer', // Class for container that wraps this widget
31
+ selectClass: 'asmSelect', // Class for the newly created <select>
32
+ optionDisabledClass: 'asmOptionDisabled', // Class for items that are already selected / disabled
33
+ listClass: 'asmList', // Class for the list ($ol)
34
+ listSortableClass: 'asmListSortable', // Another class given to the list when it is sortable
35
+ listItemClass: 'asmListItem', // Class for the <li> list items
36
+ listItemLabelClass: 'asmListItemLabel', // Class for the label text that appears in list items
37
+ removeClass: 'asmListItemRemove', // Class given to the "remove" link
38
+ highlightClass: 'asmHighlight' // Class given to the highlight <span>
39
+
40
+ };
41
+
42
+ $.extend(options, customOptions);
43
+
44
+ return this.each(function(index) {
45
+
46
+ var $original = $(this); // the original select multiple
47
+ var $container; // a container that is wrapped around our widget
48
+ var $select; // the new select we have created
49
+ var $ol; // the list that we are manipulating
50
+ var buildingSelect = false; // is the new select being constructed right now?
51
+ var ieClick = false; // in IE, has a click event occurred? ignore if not
52
+ var ignoreOriginalChangeEvent = false; // originalChangeEvent bypassed when this is true
53
+
54
+ function init() {
55
+
56
+ // initialize the alternate select multiple
57
+
58
+ // this loop ensures uniqueness, in case of existing asmSelects placed by ajax (1.0.3)
59
+ while($("#" + options.containerClass + index).size() > 0) index++;
60
+
61
+ $select = $("<select></select>")
62
+ .addClass(options.selectClass)
63
+ .attr('name', options.selectClass + index)
64
+ .attr('id', options.selectClass + index);
65
+
66
+ $selectRemoved = $("<select></select>");
67
+
68
+ $ol = $("<" + options.listType + "></" + options.listType + ">")
69
+ .addClass(options.listClass)
70
+ .attr('id', options.listClass + index);
71
+
72
+ $container = $("<div></div>")
73
+ .addClass(options.containerClass)
74
+ .attr('id', options.containerClass + index);
75
+
76
+ buildSelect();
77
+
78
+ $select.change(selectChangeEvent)
79
+ .click(selectClickEvent);
80
+
81
+ $original.change(originalChangeEvent)
82
+ .wrap($container).before($select).before($ol);
83
+
84
+ if(options.sortable) makeSortable();
85
+
86
+ if($.browser.msie && $.browser.version < 8) $ol.css('display', 'inline-block'); // Thanks Matthew Hutton
87
+ }
88
+
89
+ function makeSortable() {
90
+
91
+ // make any items in the selected list sortable
92
+ // requires jQuery UI sortables, draggables, droppables
93
+
94
+ $ol.sortable({
95
+ items: 'li.' + options.listItemClass,
96
+ handle: '.' + options.listItemLabelClass,
97
+ axis: 'y',
98
+ update: function(e, data) {
99
+
100
+ var updatedOptionId;
101
+
102
+ $(this).children("li").each(function(n) {
103
+
104
+ $option = $('#' + $(this).attr('rel'));
105
+
106
+ if($(this).is(".ui-sortable-helper")) {
107
+ updatedOptionId = $option.attr('id');
108
+ return;
109
+ }
110
+
111
+ $original.append($option);
112
+ });
113
+
114
+ if(updatedOptionId) triggerOriginalChange(updatedOptionId, 'sort');
115
+ }
116
+
117
+ }).addClass(options.listSortableClass);
118
+ }
119
+
120
+ function selectChangeEvent(e) {
121
+
122
+ // an item has been selected on the regular select we created
123
+ // check to make sure it's not an IE screwup, and add it to the list
124
+
125
+ if($.browser.msie && $.browser.version < 7 && !ieClick) return;
126
+ var id = $(this).children("option:selected").slice(0,1).attr('rel');
127
+ addListItem(id);
128
+ ieClick = false;
129
+ triggerOriginalChange(id, 'add'); // for use by user-defined callbacks
130
+ }
131
+
132
+ function selectClickEvent() {
133
+
134
+ // IE6 lets you scroll around in a select without it being pulled down
135
+ // making sure a click preceded the change() event reduces the chance
136
+ // if unintended items being added. there may be a better solution?
137
+
138
+ ieClick = true;
139
+ }
140
+
141
+ function originalChangeEvent(e) {
142
+
143
+ // select or option change event manually triggered
144
+ // on the original <select multiple>, so rebuild ours
145
+
146
+ if(ignoreOriginalChangeEvent) {
147
+ ignoreOriginalChangeEvent = false;
148
+ return;
149
+ }
150
+
151
+ $select.empty();
152
+ $ol.empty();
153
+ buildSelect();
154
+
155
+ // opera has an issue where it needs a force redraw, otherwise
156
+ // the items won't appear until something else forces a redraw
157
+ if($.browser.opera) $ol.hide().fadeIn("fast");
158
+ }
159
+
160
+ function buildSelect() {
161
+
162
+ // build or rebuild the new select that the user
163
+ // will select items from
164
+
165
+ buildingSelect = true;
166
+
167
+ // add a first option to be the home option / default selectLabel
168
+ $select.prepend("<option>" + $original.attr('title') + "</option>");
169
+
170
+ $original.children("option").each(function(n) {
171
+
172
+ var $t = $(this);
173
+ var id;
174
+
175
+ if(!$t.attr('id')) $t.attr('id', 'asm' + index + 'option' + n);
176
+ id = $t.attr('id');
177
+
178
+ if($t.is(":selected")) {
179
+ addListItem(id);
180
+ addSelectOption(id, true);
181
+ } else {
182
+ addSelectOption(id);
183
+ }
184
+ });
185
+
186
+ if(!options.debugMode) $original.hide(); // IE6 requires this on every buildSelect()
187
+ selectFirstItem();
188
+ buildingSelect = false;
189
+ }
190
+
191
+ function addSelectOption(optionId, disabled) {
192
+
193
+ // add an <option> to the <select>
194
+ // used only by buildSelect()
195
+
196
+ if(disabled == undefined) var disabled = false;
197
+
198
+ var $O = $('#' + optionId);
199
+ var $option = $("<option>" + $O.text() + "</option>")
200
+ .val($O.val())
201
+ .attr('rel', optionId);
202
+
203
+ if(disabled) disableSelectOption($option);
204
+
205
+ $select.append($option);
206
+ }
207
+
208
+ function selectFirstItem() {
209
+
210
+ // select the firm item from the regular select that we created
211
+
212
+ $select.children(":eq(0)").attr("selected", true);
213
+ }
214
+
215
+ function disableSelectOption($option) {
216
+
217
+ // make an option disabled, indicating that it's already been selected
218
+ // because safari is the only browser that makes disabled items look 'disabled'
219
+ // we apply a class that reproduces the disabled look in other browsers
220
+
221
+ $option.addClass(options.optionDisabledClass)
222
+ .attr("selected", false)
223
+ .attr("disabled", true);
224
+
225
+ if(options.hideWhenAdded) $option.hide();
226
+ if($.browser.msie) $select.hide().show(); // this forces IE to update display
227
+ }
228
+
229
+ function enableSelectOption($option) {
230
+
231
+ // given an already disabled select option, enable it
232
+
233
+ $option.removeClass(options.optionDisabledClass)
234
+ .attr("disabled", false);
235
+
236
+ if(options.hideWhenAdded) $option.show();
237
+ if($.browser.msie) $select.hide().show(); // this forces IE to update display
238
+ }
239
+
240
+ function addListItem(optionId) {
241
+
242
+ // add a new item to the html list
243
+
244
+ var $O = $('#' + optionId);
245
+
246
+ if(!$O) return; // this is the first item, selectLabel
247
+
248
+ var $removeLink = $("<a></a>")
249
+ .attr("href", "#")
250
+ .addClass(options.removeClass)
251
+ .prepend(options.removeLabel)
252
+ .click(function() {
253
+ dropListItem($(this).parent('li').attr('rel'));
254
+ return false;
255
+ });
256
+
257
+ var $itemLabel = $("<span></span>")
258
+ .addClass(options.listItemLabelClass)
259
+ .html($O.html());
260
+
261
+ var $item = $("<li></li>")
262
+ .attr('rel', optionId)
263
+ .addClass(options.listItemClass)
264
+ .append($itemLabel)
265
+ .append($removeLink)
266
+ .hide();
267
+
268
+ if(!buildingSelect) {
269
+ if($O.is(":selected")) return; // already have it
270
+ $O.attr('selected', true);
271
+ }
272
+
273
+ if(options.addItemTarget == 'top' && !buildingSelect) {
274
+ $ol.prepend($item);
275
+ if(options.sortable) $original.prepend($O);
276
+ } else {
277
+ $ol.append($item);
278
+ if(options.sortable) $original.append($O);
279
+ }
280
+
281
+ addListItemShow($item);
282
+
283
+ disableSelectOption($("[rel=" + optionId + "]", $select));
284
+
285
+ if(!buildingSelect) {
286
+ setHighlight($item, options.highlightAddedLabel);
287
+ selectFirstItem();
288
+ if(options.sortable) $ol.sortable("refresh");
289
+ }
290
+
291
+ }
292
+
293
+ function addListItemShow($item) {
294
+
295
+ // reveal the currently hidden item with optional animation
296
+ // used only by addListItem()
297
+
298
+ if(options.animate && !buildingSelect) {
299
+ $item.animate({
300
+ opacity: "show",
301
+ height: "show"
302
+ }, 100, "swing", function() {
303
+ $item.animate({
304
+ height: "+=2px"
305
+ }, 50, "swing", function() {
306
+ $item.animate({
307
+ height: "-=2px"
308
+ }, 25, "swing");
309
+ });
310
+ });
311
+ } else {
312
+ $item.show();
313
+ }
314
+ }
315
+
316
+ function dropListItem(optionId, highlightItem) {
317
+
318
+ // remove an item from the html list
319
+
320
+ if(highlightItem == undefined) var highlightItem = true;
321
+ var $O = $('#' + optionId);
322
+
323
+ $O.attr('selected', false);
324
+ $item = $ol.children("li[rel=" + optionId + "]");
325
+
326
+ dropListItemHide($item);
327
+ enableSelectOption($("[rel=" + optionId + "]", options.removeWhenAdded ? $selectRemoved : $select));
328
+
329
+ if(highlightItem) setHighlight($item, options.highlightRemovedLabel);
330
+
331
+ triggerOriginalChange(optionId, 'drop');
332
+
333
+ }
334
+
335
+ function dropListItemHide($item) {
336
+
337
+ // remove the currently visible item with optional animation
338
+ // used only by dropListItem()
339
+
340
+ if(options.animate && !buildingSelect) {
341
+
342
+ $prevItem = $item.prev("li");
343
+
344
+ $item.animate({
345
+ opacity: "hide",
346
+ height: "hide"
347
+ }, 100, "linear", function() {
348
+ $prevItem.animate({
349
+ height: "-=2px"
350
+ }, 50, "swing", function() {
351
+ $prevItem.animate({
352
+ height: "+=2px"
353
+ }, 100, "swing");
354
+ });
355
+ $item.remove();
356
+ });
357
+
358
+ } else {
359
+ $item.remove();
360
+ }
361
+ }
362
+
363
+ function setHighlight($item, label) {
364
+
365
+ // set the contents of the highlight area that appears
366
+ // directly after the <select> single
367
+ // fade it in quickly, then fade it out
368
+
369
+ if(!options.highlight) return;
370
+
371
+ $select.next("#" + options.highlightClass + index).remove();
372
+
373
+ var $highlight = $("<span></span>")
374
+ .hide()
375
+ .addClass(options.highlightClass)
376
+ .attr('id', options.highlightClass + index)
377
+ .html(label + $item.children("." + options.listItemLabelClass).slice(0,1).text());
378
+
379
+ $select.after($highlight);
380
+
381
+ $highlight.fadeIn("fast", function() {
382
+ setTimeout(function() { $highlight.fadeOut("slow"); }, 50);
383
+ });
384
+ }
385
+
386
+ function triggerOriginalChange(optionId, type) {
387
+
388
+ // trigger a change event on the original select multiple
389
+ // so that other scripts can pick them up
390
+
391
+ ignoreOriginalChangeEvent = true;
392
+ $option = $("#" + optionId);
393
+
394
+ $original.trigger('change', [{
395
+ 'option': $option,
396
+ 'value': $option.val(),
397
+ 'id': optionId,
398
+ 'item': $ol.children("[rel=" + optionId + "]"),
399
+ 'type': type
400
+ }]);
401
+ }
402
+
403
+ init();
404
+ });
405
+ };
406
+
407
+ })(jQuery);