populate-me 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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);