slices 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +3 -0
- data/README.md +51 -0
- data/Rakefile +9 -0
- data/app/assets/images/slices/ajax-loader.gif +0 -0
- data/app/assets/images/slices/asset-background.png +0 -0
- data/app/assets/images/slices/asset-spinner.gif +0 -0
- data/app/assets/images/slices/bg_header.gif +0 -0
- data/app/assets/images/slices/black-Linen.png +0 -0
- data/app/assets/images/slices/calendar.svg +68 -0
- data/app/assets/images/slices/chosen-sprite.png +0 -0
- data/app/assets/images/slices/drag-handle.svg +9 -0
- data/app/assets/images/slices/icon_admins.png +0 -0
- data/app/assets/images/slices/icon_app.png +0 -0
- data/app/assets/images/slices/icon_assets.png +0 -0
- data/app/assets/images/slices/icon_collapse.png +0 -0
- data/app/assets/images/slices/icon_drag.png +0 -0
- data/app/assets/images/slices/icon_files.png +0 -0
- data/app/assets/images/slices/icon_generic_file.png +0 -0
- data/app/assets/images/slices/icon_images.png +0 -0
- data/app/assets/images/slices/icon_padlock.png +0 -0
- data/app/assets/images/slices/icon_page.png +0 -0
- data/app/assets/images/slices/icon_search.png +0 -0
- data/app/assets/images/slices/icon_set-link.png +0 -0
- data/app/assets/images/slices/icon_set.png +0 -0
- data/app/assets/images/slices/icon_sitemap.png +0 -0
- data/app/assets/images/slices/icon_snippets.png +0 -0
- data/app/assets/images/slices/icon_template.jpg +0 -0
- data/app/assets/images/slices/icon_upload_happy.png +0 -0
- data/app/assets/images/slices/icon_upload_sad.png +0 -0
- data/app/assets/images/slices/icon_upload_thinking.png +0 -0
- data/app/assets/images/slices/noise.png +0 -0
- data/app/assets/images/slices/sitemap_icon_ghost.png +0 -0
- data/app/assets/images/slices/sitemap_icon_home.png +0 -0
- data/app/assets/images/slices/sitemap_icon_page.png +0 -0
- data/app/assets/images/slices/sitemap_icon_set_page.png +0 -0
- data/app/assets/images/slices/sitemap_icon_virtual_page.png +0 -0
- data/app/assets/images/slices/sitemap_overlay.png +0 -0
- data/app/assets/images/slices/spinner.gif +0 -0
- data/app/assets/images/slices/trash.png +0 -0
- data/app/assets/javascripts/admin.js.erb +18 -0
- data/app/assets/javascripts/slices/app/backbones/admins.js +114 -0
- data/app/assets/javascripts/slices/app/backbones/entries.js +172 -0
- data/app/assets/javascripts/slices/app/backbones/generic.js +101 -0
- data/app/assets/javascripts/slices/app/backbones/snippets.js +113 -0
- data/app/assets/javascripts/slices/app/helpers/assets.js +61 -0
- data/app/assets/javascripts/slices/app/helpers/breadcrumbs.js +30 -0
- data/app/assets/javascripts/slices/app/helpers/composer.js +26 -0
- data/app/assets/javascripts/slices/app/helpers/date_field.js +16 -0
- data/app/assets/javascripts/slices/app/helpers/get_value.js +31 -0
- data/app/assets/javascripts/slices/app/helpers/icon_upload_names.js.erb +5 -0
- data/app/assets/javascripts/slices/app/helpers/layout.js +20 -0
- data/app/assets/javascripts/slices/app/helpers/sitemap.js +150 -0
- data/app/assets/javascripts/slices/app/helpers/slice_preview.js +48 -0
- data/app/assets/javascripts/slices/app/helpers/tagging.js +73 -0
- data/app/assets/javascripts/slices/app/helpers/token_field.js +17 -0
- data/app/assets/javascripts/slices/app/helpers/upload_icons.js.erb +5 -0
- data/app/assets/javascripts/slices/app/helpers/uploader.js +127 -0
- data/app/assets/javascripts/slices/app/models/asset.js +29 -0
- data/app/assets/javascripts/slices/app/models/asset_collection.js +41 -0
- data/app/assets/javascripts/slices/app/models/attachment.js +29 -0
- data/app/assets/javascripts/slices/app/models/attachment_collection.js +7 -0
- data/app/assets/javascripts/slices/app/models/composer_item.js +1 -0
- data/app/assets/javascripts/slices/app/models/composer_item_collection.js +3 -0
- data/app/assets/javascripts/slices/app/models/file.js +103 -0
- data/app/assets/javascripts/slices/app/models/page.js +186 -0
- data/app/assets/javascripts/slices/app/models/s3_file.js +64 -0
- data/app/assets/javascripts/slices/app/slices.js +661 -0
- data/app/assets/javascripts/slices/app/views/asset_editor_view.js.erb +209 -0
- data/app/assets/javascripts/slices/app/views/asset_library_view.js +720 -0
- data/app/assets/javascripts/slices/app/views/asset_thumb_view.js.erb +191 -0
- data/app/assets/javascripts/slices/app/views/attachment_composer_view.js +350 -0
- data/app/assets/javascripts/slices/app/views/attachment_view.js +101 -0
- data/app/assets/javascripts/slices/app/views/calendar_view.js +198 -0
- data/app/assets/javascripts/slices/app/views/composer_item_view.js +54 -0
- data/app/assets/javascripts/slices/app/views/composer_view.js +130 -0
- data/app/assets/javascripts/slices/app/views/date_field_view.js +177 -0
- data/app/assets/javascripts/slices/app/views/file_view.js +142 -0
- data/app/assets/javascripts/slices/app/views/token_field_view.js +253 -0
- data/app/assets/javascripts/slices/lib/freeze.js +14 -0
- data/app/assets/javascripts/slices/lib/human_file_size.js +16 -0
- data/app/assets/javascripts/slices/lib/json_patch.js +9 -0
- data/app/assets/javascripts/slices/lib/moment.js +47 -0
- data/app/assets/javascripts/slices/lib/plugins.js +101 -0
- data/app/assets/javascripts/slices/lib/sortable.js +14 -0
- data/app/assets/javascripts/slices/slices.js +27 -0
- data/app/assets/javascripts/slices/vendor/autoscroll.js +188 -0
- data/app/assets/javascripts/slices/vendor/backbone.js +38 -0
- data/app/assets/javascripts/slices/vendor/handlebars.js +1920 -0
- data/app/assets/javascripts/slices/vendor/jqmodal.js +69 -0
- data/app/assets/javascripts/slices/vendor/jquery-ui.js +274 -0
- data/app/assets/javascripts/slices/vendor/jquery-ui_nested-sortable.js +357 -0
- data/app/assets/javascripts/slices/vendor/jquery.ajaxprogress.js +76 -0
- data/app/assets/javascripts/slices/vendor/jquery.js +2 -0
- data/app/assets/javascripts/slices/vendor/livefield.js +459 -0
- data/app/assets/javascripts/slices/vendor/moment.js +6 -0
- data/app/assets/javascripts/slices/vendor/rails.js +315 -0
- data/app/assets/javascripts/slices/vendor/underscore-string.js +1 -0
- data/app/assets/javascripts/slices/vendor/underscore.js +5 -0
- data/app/assets/stylesheets/admin.css +1 -0
- data/app/assets/stylesheets/slices/admin.css.erb +2237 -0
- data/app/assets/stylesheets/slices/reset_html5.css +106 -0
- data/app/assets/stylesheets/slices/slices.css +7 -0
- data/app/controllers/admin/admin_controller.rb +10 -0
- data/app/controllers/admin/admins_controller.rb +76 -0
- data/app/controllers/admin/assets_controller.rb +53 -0
- data/app/controllers/admin/auth/omniauth_callbacks_controller.rb +15 -0
- data/app/controllers/admin/auth/passwords_controller.rb +4 -0
- data/app/controllers/admin/auth/sessions_controller.rb +4 -0
- data/app/controllers/admin/entries_controller.rb +88 -0
- data/app/controllers/admin/page_search_controller.rb +12 -0
- data/app/controllers/admin/pages_controller.rb +103 -0
- data/app/controllers/admin/site_maps_controller.rb +15 -0
- data/app/controllers/admin/snippets_controller.rb +33 -0
- data/app/controllers/application_controller.rb +4 -0
- data/app/controllers/pages_controller.rb +45 -0
- data/app/controllers/slices_controller.rb +63 -0
- data/app/controllers/static_assets_controller.rb +52 -0
- data/app/helpers/admin/admin_helper.rb +63 -0
- data/app/helpers/admin/assets_helper.rb +36 -0
- data/app/helpers/admin/entries_helper.rb +13 -0
- data/app/helpers/admin/site_maps_helper.rb +104 -0
- data/app/helpers/assets_helper.rb +64 -0
- data/app/helpers/navigation_helper.rb +195 -0
- data/app/helpers/pages_helper.rb +119 -0
- data/app/models/admin.rb +34 -0
- data/app/models/asset.rb +211 -0
- data/app/models/attachment.rb +11 -0
- data/app/models/layout.rb +44 -0
- data/app/models/page.rb +214 -0
- data/app/models/placeholder_slice.rb +8 -0
- data/app/models/set_page.rb +12 -0
- data/app/models/set_slice.rb +57 -0
- data/app/models/site_map.rb +24 -0
- data/app/models/slice.rb +80 -0
- data/app/models/snippet.rb +21 -0
- data/app/observers/asset_observer.rb +6 -0
- data/app/observers/page_observer.rb +37 -0
- data/app/presenters/entry_presenter.rb +17 -0
- data/app/presenters/page_presenter.rb +67 -0
- data/app/presenters/presenter.rb +9 -0
- data/app/presenters/set_page_presenter.rb +2 -0
- data/app/views/admin/admins/index.html.erb +26 -0
- data/app/views/admin/admins/show.html.erb +27 -0
- data/app/views/admin/assets/index.html.erb +1 -0
- data/app/views/admin/auth/passwords/edit.html.erb +20 -0
- data/app/views/admin/auth/passwords/new.html.erb +14 -0
- data/app/views/admin/auth/sessions/_form.html.erb +35 -0
- data/app/views/admin/auth/sessions/new.html.erb +14 -0
- data/app/views/admin/entries/index.html.erb +32 -0
- data/app/views/admin/pages/_breadcrumbs.html.erb +32 -0
- data/app/views/admin/pages/_slices.html.erb +27 -0
- data/app/views/admin/pages/new.html.erb +14 -0
- data/app/views/admin/pages/show.html.erb +50 -0
- data/app/views/admin/shared/_asset_storage.html.erb +17 -0
- data/app/views/admin/shared/_custom_links.html.erb +1 -0
- data/app/views/admin/shared/_custom_navigation.html.erb +1 -0
- data/app/views/admin/shared/_navigation.html.erb +5 -0
- data/app/views/admin/site_maps/_page_li.html.erb +20 -0
- data/app/views/admin/site_maps/_set_page_li.html.erb +23 -0
- data/app/views/admin/site_maps/index.html.erb +29 -0
- data/app/views/admin/snippets/form.html.erb +12 -0
- data/app/views/admin/snippets/index.html.erb +20 -0
- data/app/views/admin/snippets/update.html.erb +0 -0
- data/app/views/layouts/admin.html.erb +72 -0
- data/lib/ext/file_store_cache.rb +18 -0
- data/lib/generators/humans/USAGE +8 -0
- data/lib/generators/humans/humans_generator.rb +10 -0
- data/lib/generators/humans/templates/humans.txt +6 -0
- data/lib/generators/slice/USAGE +28 -0
- data/lib/generators/slice/slice_generator.rb +123 -0
- data/lib/generators/slice/templates/main_fields.hbs +11 -0
- data/lib/generators/slice/templates/meta_fields.hbs +11 -0
- data/lib/generators/slice/templates/page.rb +19 -0
- data/lib/generators/slice/templates/presenter.rb +53 -0
- data/lib/generators/slice/templates/set.html.erb +8 -0
- data/lib/generators/slice/templates/set_slice.rb +14 -0
- data/lib/generators/slice/templates/set_slice_fields.hbs +5 -0
- data/lib/generators/slice/templates/show.html.erb +48 -0
- data/lib/generators/slice/templates/show_slice.rb +20 -0
- data/lib/generators/slice/templates/slice.rb +58 -0
- data/lib/generators/slice/templates/slice_fields.hbs +74 -0
- data/lib/generators/templates/slices.rb +211 -0
- data/lib/mongo_search.rb +84 -0
- data/lib/paperclip_validator.rb +5 -0
- data/lib/rack_utf8_fix.rb +10 -0
- data/lib/sRGB.icc +0 -0
- data/lib/set_link_renderer.rb +31 -0
- data/lib/slices.rb +68 -0
- data/lib/slices/asset/maker.rb +55 -0
- data/lib/slices/asset/rename.rb +67 -0
- data/lib/slices/available_slices.rb +43 -0
- data/lib/slices/cms_form_builder.rb +42 -0
- data/lib/slices/config.rb +93 -0
- data/lib/slices/container_parser.rb +70 -0
- data/lib/slices/generator_macros.rb +36 -0
- data/lib/slices/has_attachments.rb +111 -0
- data/lib/slices/has_slices.rb +88 -0
- data/lib/slices/i18n.rb +6 -0
- data/lib/slices/i18n/backend.rb +32 -0
- data/lib/slices/i18n_backend.rb +24 -0
- data/lib/slices/paperclip.rb +13 -0
- data/lib/slices/position_helper.rb +98 -0
- data/lib/slices/renderer.rb +52 -0
- data/lib/slices/slices_engine.rb +51 -0
- data/lib/slices/split_date_time_field.rb +14 -0
- data/lib/slices/tasks/assets.rake +35 -0
- data/lib/slices/tasks/db.rake +50 -0
- data/lib/slices/tasks/seeds.rake +93 -0
- data/lib/slices/tasks/validate.rake +62 -0
- data/lib/slices/tree.rb +306 -0
- data/lib/slices/version.rb +4 -0
- data/lib/slices/will_paginate.rb +12 -0
- data/lib/slices/will_paginate_mongoid.rb +45 -0
- data/lib/standard_tree.rb +193 -0
- metadata +483 -0
@@ -0,0 +1,186 @@
|
|
1
|
+
slices.model.Page = (
|
2
|
+
function () {
|
3
|
+
|
4
|
+
var settings,
|
5
|
+
pageId,
|
6
|
+
pageData,
|
7
|
+
newSliceIdCounter = 0,
|
8
|
+
NEW_SLICE_ID_NAME = '__new__',
|
9
|
+
slicesInContainers = {};
|
10
|
+
|
11
|
+
function load(callback) {
|
12
|
+
$.ajax({
|
13
|
+
url: settings.loadPagePath.split('{{id}}').join(pageId),
|
14
|
+
contentType: 'application/json',
|
15
|
+
dataType: 'json',
|
16
|
+
error: function (XMLHttpRequest, textStatus, errorThrown) {
|
17
|
+
// FIXME
|
18
|
+
throw new Error(errorThrown);
|
19
|
+
},
|
20
|
+
success: function (data, textStatus, XMLHttpRequest) {
|
21
|
+
parseLoadedData(data);
|
22
|
+
callback();
|
23
|
+
}
|
24
|
+
});
|
25
|
+
}
|
26
|
+
|
27
|
+
function save() {
|
28
|
+
var dfd = $.Deferred();
|
29
|
+
|
30
|
+
var params = $.extend({}, pageData);
|
31
|
+
|
32
|
+
_.each(params.slices, function (slice) {
|
33
|
+
// Don't pass back the temp ID assigned to new slices so that the backend knows to
|
34
|
+
// generate from scratch...
|
35
|
+
if (slice.id.indexOf(NEW_SLICE_ID_NAME) === 0) {
|
36
|
+
slice.client_id = slice.id;
|
37
|
+
slice._new = 1;
|
38
|
+
delete slice.id;
|
39
|
+
delete slice.template;
|
40
|
+
delete slice.name;
|
41
|
+
}
|
42
|
+
});
|
43
|
+
|
44
|
+
/* Strip these out of the returned JSON object, only values
|
45
|
+
* represented in the page form should be passed back HACKHACK */
|
46
|
+
var do_not_pass_back = [
|
47
|
+
'id',
|
48
|
+
'position',
|
49
|
+
'created_at',
|
50
|
+
'updated_at',
|
51
|
+
'has_content',
|
52
|
+
'path',
|
53
|
+
'page_id'];
|
54
|
+
|
55
|
+
_.each(do_not_pass_back, function(item) {
|
56
|
+
delete params[item]
|
57
|
+
});
|
58
|
+
|
59
|
+
$.ajax({
|
60
|
+
url: settings.savePagePath.split('{{id}}').join(pageId),
|
61
|
+
type: 'PUT',
|
62
|
+
data: JSON.stringify({ page: params }),
|
63
|
+
contentType: 'application/json',
|
64
|
+
dataType: 'json',
|
65
|
+
error: function (xhr, textStatus, errorThrown) {
|
66
|
+
if (xhr.status == 422) {
|
67
|
+
var errors = $.parseJSON(xhr.responseText);
|
68
|
+
|
69
|
+
// If the slice is new re-assign the ids we stripped off when saving
|
70
|
+
_.each(pageData.slices, function (slice) {
|
71
|
+
if (slice._new) slice.id = slice.client_id;
|
72
|
+
});
|
73
|
+
|
74
|
+
dfd.reject(errors);
|
75
|
+
} else {
|
76
|
+
throw new Error(errorThrown);
|
77
|
+
}
|
78
|
+
},
|
79
|
+
success: function (data, textStatus, XMLHttpRequest) {
|
80
|
+
parseLoadedData(data);
|
81
|
+
dfd.resolve();
|
82
|
+
}
|
83
|
+
});
|
84
|
+
|
85
|
+
return dfd.promise();
|
86
|
+
}
|
87
|
+
|
88
|
+
function parseLoadedData(data) {
|
89
|
+
pageData = data;
|
90
|
+
|
91
|
+
_.each(slices.availableContainers, function (container, machineName) {
|
92
|
+
slicesInContainers[machineName] = [];
|
93
|
+
});
|
94
|
+
|
95
|
+
pageData.slices = _.sortBy(pageData.slices, function (slice) {
|
96
|
+
return slice.position;
|
97
|
+
});
|
98
|
+
|
99
|
+
_.each(pageData.slices, function (slice) {
|
100
|
+
// Remove the client id which the backend returns even after a successfully created new slice
|
101
|
+
delete slice.client_id;
|
102
|
+
delete slice._new;
|
103
|
+
|
104
|
+
try {
|
105
|
+
slicesInContainers[slice.container].push(slice);
|
106
|
+
} catch(error) {
|
107
|
+
if (console != undefined) {
|
108
|
+
console.log("Error, missing container on slice?", error, slice);
|
109
|
+
}
|
110
|
+
}
|
111
|
+
});
|
112
|
+
}
|
113
|
+
|
114
|
+
function addSlice(slice) {
|
115
|
+
slice.id = NEW_SLICE_ID_NAME + newSliceIdCounter++;
|
116
|
+
pageData.slices.push(slice);
|
117
|
+
slicesInContainers[slice.container].push(slice);
|
118
|
+
}
|
119
|
+
|
120
|
+
function positionSlice(sliceId, pos) {
|
121
|
+
_.detect(pageData.slices, function (slice) {
|
122
|
+
return slice.id == sliceId;
|
123
|
+
}).position = pos;
|
124
|
+
}
|
125
|
+
|
126
|
+
return {
|
127
|
+
init: function (s) {
|
128
|
+
settings = s;
|
129
|
+
},
|
130
|
+
id: function (id) {
|
131
|
+
if (arguments.length === 0) {
|
132
|
+
return pageId;
|
133
|
+
}
|
134
|
+
pageId = id;
|
135
|
+
},
|
136
|
+
load: function (callback) {
|
137
|
+
load(callback);
|
138
|
+
},
|
139
|
+
save: function () {
|
140
|
+
return save();
|
141
|
+
},
|
142
|
+
field: function (varName) {
|
143
|
+
return pageData[varName];
|
144
|
+
},
|
145
|
+
getSlices: function (container) {
|
146
|
+
return slicesInContainers[container];
|
147
|
+
},
|
148
|
+
setSlices: function (container, slices) {
|
149
|
+
slicesInContainers[container] = [];
|
150
|
+
_.each(slices, function(slice) {
|
151
|
+
pageData.slices = _.reject(pageData.slices, function(pdslice) {
|
152
|
+
return pdslice.id === slice.id
|
153
|
+
});
|
154
|
+
pageData.slices.push(slice);
|
155
|
+
slicesInContainers[container].push(slice);
|
156
|
+
});
|
157
|
+
},
|
158
|
+
addSlice: function (slice) {
|
159
|
+
addSlice(slice);
|
160
|
+
},
|
161
|
+
positionSlice: function (sliceId, pos) {
|
162
|
+
positionSlice(sliceId, pos);
|
163
|
+
changed = true;
|
164
|
+
},
|
165
|
+
getMeta: function(key) {
|
166
|
+
return pageData[key];
|
167
|
+
},
|
168
|
+
setMeta: function(key, value) {
|
169
|
+
pageData[key] = value;
|
170
|
+
},
|
171
|
+
// This returns true if the page was created in the last minute.
|
172
|
+
seemsNew: function() {
|
173
|
+
var created = moment(this.field('created_at')),
|
174
|
+
recently = moment().subtract('minutes', 1);
|
175
|
+
|
176
|
+
return created >= recently && this.field('active') == false;
|
177
|
+
},
|
178
|
+
data: function() {
|
179
|
+
return pageData;
|
180
|
+
},
|
181
|
+
slices: function() {
|
182
|
+
return pageData.slices;
|
183
|
+
}
|
184
|
+
};
|
185
|
+
}
|
186
|
+
)();
|
@@ -0,0 +1,64 @@
|
|
1
|
+
slices.S3File = slices.File.extend({
|
2
|
+
|
3
|
+
setS3Key: function(name) {
|
4
|
+
this.set('key', slices.S3_TEMPFILE_KEY_PREFIX + '/' + Date.now() + '/' + name);
|
5
|
+
},
|
6
|
+
|
7
|
+
fileS3URL: function() {
|
8
|
+
return slices.S3_URL + this.get('key');
|
9
|
+
},
|
10
|
+
|
11
|
+
formDataToS3: function() {
|
12
|
+
var formData = this.formDataWithOptions(slices.S3_UPLOADER_DEFAULTS);
|
13
|
+
var browserFile = this.get('browserFile');
|
14
|
+
|
15
|
+
this.setS3Key(browserFile.name);
|
16
|
+
formData.append('key', this.get('key'));
|
17
|
+
formData.append('Content-Type', browserFile.type);
|
18
|
+
formData.append('file', browserFile);
|
19
|
+
return formData;
|
20
|
+
},
|
21
|
+
|
22
|
+
formDataFromS3: function() {
|
23
|
+
var formData = this.formDataWithOptions(this.params);
|
24
|
+
formData.append('file', this.fileS3URL());
|
25
|
+
return formData;
|
26
|
+
},
|
27
|
+
|
28
|
+
upload: function() {
|
29
|
+
var self = this,
|
30
|
+
url = slices.S3_URL,
|
31
|
+
data = this.formDataToS3();
|
32
|
+
|
33
|
+
this.uploadWithOptions(url, data, {
|
34
|
+
progress: function(xhr, progress) { self.onS3Progress(progress) },
|
35
|
+
success: function(response) { self.onS3Success(response) },
|
36
|
+
error: function(response) { self.onS3Error(response) }
|
37
|
+
});
|
38
|
+
},
|
39
|
+
|
40
|
+
onS3Progress: function(progress) {
|
41
|
+
this.onProgress(progress);
|
42
|
+
},
|
43
|
+
|
44
|
+
onS3Success: function(response) {
|
45
|
+
this.uploadToSlicesFromS3(response);
|
46
|
+
},
|
47
|
+
|
48
|
+
onS3Error: function(response) {
|
49
|
+
this.onError(response);
|
50
|
+
},
|
51
|
+
|
52
|
+
uploadToSlicesFromS3: function() {
|
53
|
+
var self = this,
|
54
|
+
url = this.url,
|
55
|
+
data = this.formDataFromS3();
|
56
|
+
|
57
|
+
this.uploadWithOptions(url, data, {
|
58
|
+
progress: function() {},
|
59
|
+
success: function(response) { self.onSuccess(response) },
|
60
|
+
error: function(error) { self.onError(error) }
|
61
|
+
});
|
62
|
+
},
|
63
|
+
|
64
|
+
});
|
@@ -0,0 +1,661 @@
|
|
1
|
+
// Slices.js
|
2
|
+
// (c) 2011 With Associates
|
3
|
+
// http://slices.withassociates.com/
|
4
|
+
|
5
|
+
var slices = {
|
6
|
+
|
7
|
+
defaultSettings: {
|
8
|
+
mainTemplate: '_page_main',
|
9
|
+
metaTemplate: '_page_meta',
|
10
|
+
templatesPath: '/slices/templates/',
|
11
|
+
loadPagePath: '/admin/pages/{{id}}.json',
|
12
|
+
savePagePath: '/admin/pages/{{id}}.json'
|
13
|
+
},
|
14
|
+
|
15
|
+
templates: {},
|
16
|
+
availableSlices: {},
|
17
|
+
availableContainers: {},
|
18
|
+
model: {},
|
19
|
+
|
20
|
+
fieldId: function(context, field) {
|
21
|
+
// If `this` is the current page, then we’ll use a `meta-{{field}}` ID.
|
22
|
+
if (context === slices.model.Page.data()) {
|
23
|
+
return ['meta', field].join('-');
|
24
|
+
|
25
|
+
// If this has an id, we’re dealing with a slice, so we’ll use a `slices-{{id}}-{{field}}` ID.
|
26
|
+
} else if (context.hasOwnProperty('id')) {
|
27
|
+
return ['slices', context.id, field].join('-');
|
28
|
+
|
29
|
+
// Otherwise, we just need a unique id.
|
30
|
+
} else {
|
31
|
+
slices.__uid__ = slices.__uid__ || 0;
|
32
|
+
return 'field-' + ++slices.__uid__;
|
33
|
+
}
|
34
|
+
},
|
35
|
+
|
36
|
+
controller: function SlicesController() {
|
37
|
+
|
38
|
+
// private vars
|
39
|
+
var settings,
|
40
|
+
busy = true;
|
41
|
+
|
42
|
+
// private methods
|
43
|
+
|
44
|
+
function init(pageId, passed_settings) {
|
45
|
+
settings = $.extend({}, slices.defaultSettings, passed_settings);
|
46
|
+
|
47
|
+
observeFormEvents();
|
48
|
+
|
49
|
+
slices.model.Page.init(settings);
|
50
|
+
slices.model.Page.id(pageId);
|
51
|
+
|
52
|
+
slices.availableContainers = settings.availableContainers;
|
53
|
+
slices.availableSlices = settings.availableSlices;
|
54
|
+
|
55
|
+
|
56
|
+
addSliceOptions(slices.availableSlices);
|
57
|
+
|
58
|
+
templates = [
|
59
|
+
'slice',
|
60
|
+
settings.mainTemplate,
|
61
|
+
settings.metaTemplate,
|
62
|
+
settings.mainExtraTemplate,
|
63
|
+
settings.metaExtraTemplate
|
64
|
+
];
|
65
|
+
|
66
|
+
loadSliceTemplates(pageId);
|
67
|
+
loadTemplates(templates, pageId, loadPageModel);
|
68
|
+
};
|
69
|
+
|
70
|
+
function addSliceOptions(slices) {
|
71
|
+
var select = $('#add-slice-fields select');
|
72
|
+
|
73
|
+
select.find('option:not(:disabled)').remove();
|
74
|
+
|
75
|
+
_.each(slices, function (slice, machineName) {
|
76
|
+
if (!restrictedAndNotSuper(slice)) {
|
77
|
+
select.append(
|
78
|
+
'<option value="' + machineName + '">' + slice.name + '</option>'
|
79
|
+
);
|
80
|
+
}
|
81
|
+
});
|
82
|
+
};
|
83
|
+
|
84
|
+
function templateUrl(name, pageId) {
|
85
|
+
name = name.split('{{id}}').join(pageId);
|
86
|
+
|
87
|
+
if (name.indexOf('/') === 0) {
|
88
|
+
return name + '.hbs';
|
89
|
+
} else {
|
90
|
+
return settings.templatesPath + name + '.hbs';
|
91
|
+
}
|
92
|
+
};
|
93
|
+
|
94
|
+
function loadSliceTemplates(pageId) {
|
95
|
+
_.each(slices.availableSlices, function(slice, name) {
|
96
|
+
$.ajax({
|
97
|
+
url: templateUrl(slice.template, pageId),
|
98
|
+
success: function(raw_template, textStatus, XMLHttpRequest) {
|
99
|
+
slices.templates[slice.template] = Handlebars.compile(raw_template);
|
100
|
+
}
|
101
|
+
});
|
102
|
+
})
|
103
|
+
};
|
104
|
+
|
105
|
+
function loadTemplates(templates, pageId, callback) {
|
106
|
+
templates = _.compact(templates);
|
107
|
+
var numTemplates = templates.length;
|
108
|
+
_.each(templates, function (templateName) {
|
109
|
+
$.ajax({
|
110
|
+
url: templateUrl(templateName, pageId),
|
111
|
+
success: function (raw_template, textStatus, XMLHttpRequest) {
|
112
|
+
slices.templates[templateName] = Handlebars.compile(raw_template);
|
113
|
+
if (--numTemplates == 0) callback();
|
114
|
+
}
|
115
|
+
});
|
116
|
+
});
|
117
|
+
};
|
118
|
+
|
119
|
+
function loadPageModel() {
|
120
|
+
slices.model.Page.load(onPageLoaded);
|
121
|
+
};
|
122
|
+
|
123
|
+
function addSliceTemplate(slice) {
|
124
|
+
var templateData = {},
|
125
|
+
sliceBlock,
|
126
|
+
sliceContent,
|
127
|
+
sliceContentTemplate = slices.availableSlices[slice.type].template,
|
128
|
+
isOpen = false;
|
129
|
+
|
130
|
+
var sliceBlock = $(
|
131
|
+
slices.templates['slice']({
|
132
|
+
id: slice.id,
|
133
|
+
name: slice.name,
|
134
|
+
css_class: slice.type + '-slice',
|
135
|
+
content: function () {
|
136
|
+
return slices.templates[sliceContentTemplate](slice)
|
137
|
+
}
|
138
|
+
})
|
139
|
+
);
|
140
|
+
|
141
|
+
var sliceContent = sliceBlock.find('.slice-content'),
|
142
|
+
controlBar = sliceBlock.find('.control-bar'),
|
143
|
+
preview = sliceBlock.find('.slice-preview');
|
144
|
+
|
145
|
+
if (_.isFunction(window.customSlicePreview)) {
|
146
|
+
var slicePreviewHelper = window.customSlicePreview;
|
147
|
+
delete window.customSlicePreview;
|
148
|
+
} else {
|
149
|
+
var slicePreviewHelper = slices.defaultSlicePreview;
|
150
|
+
}
|
151
|
+
|
152
|
+
var updateSlicePreview = function() {
|
153
|
+
preview.html(slicePreviewHelper.call(sliceContent));
|
154
|
+
}
|
155
|
+
|
156
|
+
updateSlicePreview();
|
157
|
+
|
158
|
+
controlBar.on('click', function () {
|
159
|
+
var closed = sliceBlock.is('.closed');
|
160
|
+
|
161
|
+
if (closed) {
|
162
|
+
sliceContent.slideDown('fast');
|
163
|
+
sliceBlock.removeClass('closed');
|
164
|
+
} else {
|
165
|
+
updateSlicePreview();
|
166
|
+
sliceContent.slideUp('fast');
|
167
|
+
sliceBlock.addClass('closed');
|
168
|
+
}
|
169
|
+
|
170
|
+
updateMinimiseAllSlices();
|
171
|
+
|
172
|
+
return false;
|
173
|
+
});
|
174
|
+
|
175
|
+
sliceBlock.find('a.sort').on('click', false);
|
176
|
+
|
177
|
+
if (restrictedAndNotSuper(slice)) {
|
178
|
+
sliceBlock.find('a.delete').remove();
|
179
|
+
} else {
|
180
|
+
sliceBlock.find('a.delete').on('click', function () {
|
181
|
+
slice._destroy = 1;
|
182
|
+
sliceBlock.slideUp('fast');
|
183
|
+
sliceBlock.trigger('change');
|
184
|
+
enableSaveButton();
|
185
|
+
return false;
|
186
|
+
});
|
187
|
+
}
|
188
|
+
|
189
|
+
$('#container-' + slice.container + '>ul').append(sliceBlock);
|
190
|
+
|
191
|
+
sliceContent.applyDataValues();
|
192
|
+
sliceContent.initDataPlugins();
|
193
|
+
|
194
|
+
enableContainerSelect(slice, sliceBlock);
|
195
|
+
|
196
|
+
}
|
197
|
+
|
198
|
+
function onPageLoaded() {
|
199
|
+
var tabControls = $('#container-tab-controls'),
|
200
|
+
containersHolder = $('#containers-holder').empty(),
|
201
|
+
addSliceFields = $('#add-slice-fields');
|
202
|
+
|
203
|
+
initMeta();
|
204
|
+
|
205
|
+
_.each(slices.availableContainers, function (container, machineName) {
|
206
|
+
// Create ourselves a tab button.
|
207
|
+
var tabButton = $(
|
208
|
+
'<a href="#container-' + machineName + '">' +
|
209
|
+
container.name +
|
210
|
+
'</a>'
|
211
|
+
);
|
212
|
+
|
213
|
+
if (container.primary) tabButton.addClass('primary');
|
214
|
+
|
215
|
+
container.availableSlices = _.clone(slices.availableSlices);
|
216
|
+
|
217
|
+
// Filter available slices to those specified in the layout
|
218
|
+
|
219
|
+
if (container.only) {
|
220
|
+
_.each(slices.availableSlices, function(slice, machineName) {
|
221
|
+
if (!_.contains(container.only, machineName)) {
|
222
|
+
delete container.availableSlices[machineName];
|
223
|
+
}
|
224
|
+
});
|
225
|
+
}
|
226
|
+
|
227
|
+
if (container.except) {
|
228
|
+
_.each(slices.availableSlices, function(slice, machineName) {
|
229
|
+
if (_.contains(container.except, machineName)) {
|
230
|
+
delete container.availableSlices[machineName];
|
231
|
+
}
|
232
|
+
});
|
233
|
+
}
|
234
|
+
|
235
|
+
tabButton.data('container', container);
|
236
|
+
|
237
|
+
// Bind the tab button click event.
|
238
|
+
tabButton.on('click', function() {
|
239
|
+
var tab = $(this);
|
240
|
+
var container = tab.data('container');
|
241
|
+
|
242
|
+
tabControls.find('a').removeClass('active');
|
243
|
+
containersHolder.find('>div').hide();
|
244
|
+
$('#container-' + machineName).show();
|
245
|
+
$(this).addClass('active');
|
246
|
+
|
247
|
+
updateMinimiseAllSlices();
|
248
|
+
addSliceOptions(container.availableSlices);
|
249
|
+
|
250
|
+
return false;
|
251
|
+
});
|
252
|
+
|
253
|
+
// Append our tab button (in an li) to the tab controls container.
|
254
|
+
tabControls.append($('<li />').append(tabButton));
|
255
|
+
|
256
|
+
// Create ourselves a container, holder and adder.
|
257
|
+
var container = $('<div id="container-' + machineName + '" class="container" />');
|
258
|
+
var holder = $('<ul class="slices-holder" />');
|
259
|
+
var adder = addSliceFields.clone();
|
260
|
+
|
261
|
+
// Remove redundant id attribute on our cloned adder.
|
262
|
+
// adder.attr({ id: '' });
|
263
|
+
|
264
|
+
// Bind the behaviour of our slice selector.
|
265
|
+
adder.find('select').bind('change', function() {
|
266
|
+
var sliceType = $(this).val();
|
267
|
+
|
268
|
+
if (sliceType === '') return false;
|
269
|
+
|
270
|
+
addNewSlice(
|
271
|
+
machineName,
|
272
|
+
$(this).val(),
|
273
|
+
$('#container-' + machineName + ' ul li').length
|
274
|
+
);
|
275
|
+
|
276
|
+
$('#container-' + machineName + ' ul').trigger('sortstop');
|
277
|
+
|
278
|
+
$(this).find('option:selected').removeAttr('selected');
|
279
|
+
$(this).find('option:disabled').attr('selected', 'selected');
|
280
|
+
|
281
|
+
return false;
|
282
|
+
});
|
283
|
+
|
284
|
+
// Glue everything together.
|
285
|
+
container.append(holder, adder);
|
286
|
+
containersHolder.append(container);
|
287
|
+
});
|
288
|
+
|
289
|
+
addSliceFields.remove();
|
290
|
+
tabControls.find('a:first, a.primary').trigger('click');
|
291
|
+
addSliceContainers();
|
292
|
+
addMinimiseAllSlices();
|
293
|
+
|
294
|
+
if ($('#page-meta').children().length > 0) {
|
295
|
+
$('<div id="show-meta"><a href="#">advanced options…</a></div>').
|
296
|
+
insertAfter('#page-meta').
|
297
|
+
toggle(function() {
|
298
|
+
$('#page-meta').slideDown('fast');
|
299
|
+
$(this).html('<a href="#">hide advanced options</a>');
|
300
|
+
$(this).addClass('open');
|
301
|
+
}, function() {
|
302
|
+
$('#page-meta').slideUp('fast');
|
303
|
+
$(this).html('<a href="#">advanced options…</a>');
|
304
|
+
$(this).removeClass('open');
|
305
|
+
});
|
306
|
+
|
307
|
+
if (slices.model.Page.seemsNew()) $('#show-meta').trigger('click');
|
308
|
+
}
|
309
|
+
|
310
|
+
busy = false;
|
311
|
+
}
|
312
|
+
|
313
|
+
function initMeta() {
|
314
|
+
$('#page-main').html(renderMetaFields(settings.mainTemplate));
|
315
|
+
|
316
|
+
$('#page-meta').html(renderMetaFields(settings.metaTemplate));
|
317
|
+
|
318
|
+
if (settings.metaExtraTemplate) {
|
319
|
+
$('#page-meta').append(renderMetaFields(settings.metaExtraTemplate));
|
320
|
+
}
|
321
|
+
|
322
|
+
if (settings.mainExtraTemplate) {
|
323
|
+
$('#page-extra-main').html(renderMetaFields(settings.mainExtraTemplate));
|
324
|
+
}
|
325
|
+
|
326
|
+
$('#page-meta-fields').applyDataValues().initDataPlugins();
|
327
|
+
|
328
|
+
Tagging.detect();
|
329
|
+
}
|
330
|
+
|
331
|
+
function renderMetaFields(name) {
|
332
|
+
var template = slices.templates[name],
|
333
|
+
page = slices.model.Page,
|
334
|
+
data = page.data();
|
335
|
+
|
336
|
+
return template(data);
|
337
|
+
}
|
338
|
+
|
339
|
+
function addNewSlice(container, type, pos) {
|
340
|
+
var slice = _.extend({}, slices.availableSlices[type], {
|
341
|
+
type: type,
|
342
|
+
container: container,
|
343
|
+
position: pos
|
344
|
+
});
|
345
|
+
slices.model.Page.addSlice(slice);
|
346
|
+
addSliceTemplate(slice);
|
347
|
+
}
|
348
|
+
|
349
|
+
function addSliceContainers() {
|
350
|
+
_.each(slices.availableContainers, function (container, machineName) {
|
351
|
+
$('#container-' + machineName + ' ul').empty();
|
352
|
+
});
|
353
|
+
|
354
|
+
_.each(slices.availableContainers, function (container, machineName) {
|
355
|
+
var container_slices = slices.model.Page.getSlices(machineName);
|
356
|
+
|
357
|
+
container_slices = _.map(container_slices, function(slice) {
|
358
|
+
return $.extend(true, {},
|
359
|
+
slices.availableSlices[slice.type],
|
360
|
+
slice
|
361
|
+
);
|
362
|
+
});
|
363
|
+
|
364
|
+
slices.model.Page.setSlices(machineName, container_slices);
|
365
|
+
|
366
|
+
_.each(container_slices, addSliceTemplate);
|
367
|
+
|
368
|
+
var ul = $('#container-' + machineName + '>ul');
|
369
|
+
|
370
|
+
ul.sortable({
|
371
|
+
handle: '.control-bar',
|
372
|
+
scroll: false,
|
373
|
+
beforeStart: function() {
|
374
|
+
ul.freezeHeight();
|
375
|
+
window.autoscroll.start();
|
376
|
+
},
|
377
|
+
stop: function() {
|
378
|
+
window.autoscroll.stop();
|
379
|
+
ul.thawHeight();
|
380
|
+
}
|
381
|
+
});
|
382
|
+
|
383
|
+
ul.on('sortstop', function (event, ui) {
|
384
|
+
ul.find('>li').each(function (i) {
|
385
|
+
slices.model.Page.positionSlice($(this).attr('rel'), i);
|
386
|
+
});
|
387
|
+
|
388
|
+
onReorder();
|
389
|
+
});
|
390
|
+
|
391
|
+
ul.trigger('sortstop');
|
392
|
+
});
|
393
|
+
}
|
394
|
+
|
395
|
+
function addMinimiseAllSlices(){
|
396
|
+
var minimise = $('#minimise');
|
397
|
+
minimise.text('Minimise all slices');
|
398
|
+
|
399
|
+
minimise.on('click', function () {
|
400
|
+
if (minimise.text().indexOf('Minimise') != -1){
|
401
|
+
$('.container:visible .slice:not(.closed) .control-bar').click();
|
402
|
+
} else {
|
403
|
+
$('.container:visible .slice.closed .control-bar').click();
|
404
|
+
}
|
405
|
+
return false;
|
406
|
+
})
|
407
|
+
}
|
408
|
+
|
409
|
+
function updateMinimiseAllSlices() {
|
410
|
+
var slices = $('.container:visible .slice');
|
411
|
+
|
412
|
+
if (slices.length === 0) return;
|
413
|
+
|
414
|
+
var closed = slices.filter('.closed'),
|
415
|
+
allClosed = closed.length === slices.length,
|
416
|
+
allOpen = closed.length === 0;
|
417
|
+
|
418
|
+
if (allClosed) {
|
419
|
+
$('#minimise').text('Expand all slices');
|
420
|
+
} else if (allOpen) {
|
421
|
+
$('#minimise').text('Minimise all slices');
|
422
|
+
}
|
423
|
+
}
|
424
|
+
|
425
|
+
function getArrayInputValuesFor(key) {
|
426
|
+
var result = [];
|
427
|
+
|
428
|
+
$('input[name="meta-' + key + '"]').each(function() {
|
429
|
+
var input = $(this);
|
430
|
+
|
431
|
+
switch (input.attr('type')) {
|
432
|
+
case 'checkbox':
|
433
|
+
if (input.is(':checked')) result.push(input.val());
|
434
|
+
break;
|
435
|
+
default:
|
436
|
+
result.push(input.val());
|
437
|
+
break;
|
438
|
+
}
|
439
|
+
});
|
440
|
+
|
441
|
+
return result;
|
442
|
+
}
|
443
|
+
|
444
|
+
function updateMeta() {
|
445
|
+
var model = slices.model.Page,
|
446
|
+
inputs = $('[id^="meta-"]');
|
447
|
+
|
448
|
+
inputs.each(function() {
|
449
|
+
var input = $(this),
|
450
|
+
id = input.attr('id'),
|
451
|
+
key = id.match(/meta-(.+)/)[1],
|
452
|
+
oldValue = model.getMeta(key),
|
453
|
+
newValue = slices.getValueForId(id);
|
454
|
+
|
455
|
+
if (newValue === undefined || newValue == oldValue) return;
|
456
|
+
|
457
|
+
model.setMeta(key, newValue);
|
458
|
+
model.changed = true;
|
459
|
+
});
|
460
|
+
}
|
461
|
+
|
462
|
+
function updateSlices() {
|
463
|
+
var model = slices.model.Page;
|
464
|
+
|
465
|
+
_.each(model.slices(), function(slice) {
|
466
|
+
var prefix = 'slices-' + slice.id + '-',
|
467
|
+
inputs = $('[id^="' + prefix + '"]');
|
468
|
+
|
469
|
+
inputs.each(function() {
|
470
|
+
var input = $(this),
|
471
|
+
id = input.attr('id'),
|
472
|
+
key = id.substr(prefix.length),
|
473
|
+
oldValue = slice[key],
|
474
|
+
newValue = slices.getValueForId(id);
|
475
|
+
|
476
|
+
if (newValue === undefined || newValue == oldValue) return;
|
477
|
+
|
478
|
+
slice[key] = newValue;
|
479
|
+
model.changed = true;
|
480
|
+
});
|
481
|
+
});
|
482
|
+
}
|
483
|
+
|
484
|
+
function updateModel() {
|
485
|
+
var model = slices.model.Page;
|
486
|
+
|
487
|
+
model.changed = false;
|
488
|
+
|
489
|
+
updateMeta()
|
490
|
+
updateSlices();
|
491
|
+
|
492
|
+
if (model.changed) enableSaveButton();
|
493
|
+
}
|
494
|
+
|
495
|
+
function observeFormEvents() {
|
496
|
+
$('#slices-form')
|
497
|
+
.on('submit', onFormSubmitted)
|
498
|
+
.on('change', onChange)
|
499
|
+
.on('keyup', 'input, textarea', _.debounce(function() {
|
500
|
+
$(this).trigger('change');
|
501
|
+
}, 100));
|
502
|
+
}
|
503
|
+
|
504
|
+
function onChange() {
|
505
|
+
if (!busy) updateModel();
|
506
|
+
}
|
507
|
+
|
508
|
+
function onReorder() {
|
509
|
+
if (!busy) enableSaveButton();
|
510
|
+
}
|
511
|
+
|
512
|
+
function onFormSubmitted(event) {
|
513
|
+
event.preventDefault();
|
514
|
+
|
515
|
+
busy = true;
|
516
|
+
|
517
|
+
$(document).trigger('slices:willSubmit');
|
518
|
+
|
519
|
+
updateModel();
|
520
|
+
|
521
|
+
disableSaveButton();
|
522
|
+
|
523
|
+
$('.error-message').remove();
|
524
|
+
$('.field-with-errors').removeClass('field-with-errors');
|
525
|
+
$('#container').freezeHeight();
|
526
|
+
|
527
|
+
// Save it...
|
528
|
+
slices.model.Page.save()
|
529
|
+
.done(function() {
|
530
|
+
initMeta();
|
531
|
+
addSliceContainers();
|
532
|
+
updateViewLink();
|
533
|
+
updateBreadcrumbs();
|
534
|
+
})
|
535
|
+
.fail(function(errors) {
|
536
|
+
_.each(errors, function(value, key) {
|
537
|
+
if (key == 'slices') {
|
538
|
+
value = _.flatten([value])[0];
|
539
|
+
_.each(value, function(fields, sliceId) {
|
540
|
+
_.each(fields, function(errorMsgs, fieldName) {
|
541
|
+
|
542
|
+
var inpId = ['slices', sliceId, fieldName].join('-'),
|
543
|
+
input = $('#' + inpId);
|
544
|
+
|
545
|
+
input.closest('li').addClass('field-with-errors');
|
546
|
+
|
547
|
+
var errorMsg = _.flatten([errorMsgs]).join(', ');
|
548
|
+
input.after(
|
549
|
+
$('<div class="error-message" />').text(
|
550
|
+
$('label[for=' + inpId + ']').text() + ' ' + errorMsg
|
551
|
+
)
|
552
|
+
);
|
553
|
+
|
554
|
+
var containerId = input.closest('.container').attr('id');
|
555
|
+
|
556
|
+
$('#container-tab-controls a[href=#' + containerId + ']')
|
557
|
+
.addClass('field-with-errors');
|
558
|
+
});
|
559
|
+
});
|
560
|
+
} else {
|
561
|
+
var li = $('#meta-' + key).closest('li');
|
562
|
+
|
563
|
+
li
|
564
|
+
.addClass('field-with-errors')
|
565
|
+
.append(
|
566
|
+
$('<div class="error-message" />').text(
|
567
|
+
li.find('.label').text() + ' ' + value
|
568
|
+
)
|
569
|
+
);
|
570
|
+
}
|
571
|
+
});
|
572
|
+
}).
|
573
|
+
always(function() {
|
574
|
+
disableSaveButton();
|
575
|
+
updateMinimiseAllSlices();
|
576
|
+
busy = false;
|
577
|
+
_.defer(function() { $('#container').thawHeight() });
|
578
|
+
});
|
579
|
+
}
|
580
|
+
|
581
|
+
function restrictedAndNotSuper(slice) {
|
582
|
+
return (slice.restricted && !settings.super_user);
|
583
|
+
}
|
584
|
+
|
585
|
+
// Rig-up the little container select widget in the control bar.
|
586
|
+
// This is not the prettiest, but you don't need me to tell you that,
|
587
|
+
// you can just look below.
|
588
|
+
function enableContainerSelect(slice, sliceBlock) {
|
589
|
+
|
590
|
+
var potentialContainers = {};
|
591
|
+
|
592
|
+
_.each(slices.availableContainers, function(container, machineName) {
|
593
|
+
if (container.availableSlices.hasOwnProperty(slice.type)) {
|
594
|
+
potentialContainers[machineName] = container;
|
595
|
+
}
|
596
|
+
});
|
597
|
+
|
598
|
+
if (Object.keys(potentialContainers).length <= 1) {
|
599
|
+
sliceBlock.find('.container-select').remove();
|
600
|
+
return;
|
601
|
+
}
|
602
|
+
|
603
|
+
sliceBlock.find('.container-select').each(function() {
|
604
|
+
var select = $(this);
|
605
|
+
|
606
|
+
// Add the options
|
607
|
+
select.append('<option value="default" selected disabled>Move to another container</option>');
|
608
|
+
|
609
|
+
_.each(potentialContainers, function(container, machineName) {
|
610
|
+
select.append('<option value="' + machineName + '">' + container.name + '</option>');
|
611
|
+
});
|
612
|
+
|
613
|
+
// On change, we'll move our slice to the selected container
|
614
|
+
// and notify all the appropriate objects that things have changed.
|
615
|
+
select.bind('change', function() {
|
616
|
+
// Attach to the new container, both in data and dom.
|
617
|
+
var newMachineName = select.val();
|
618
|
+
var newContainer = $('#container-' + newMachineName + ' > ul');
|
619
|
+
slice.container = newMachineName;
|
620
|
+
sliceBlock.detach().appendTo(newContainer);
|
621
|
+
|
622
|
+
// Reset the widget.
|
623
|
+
select.val('default');
|
624
|
+
|
625
|
+
// Make sure slice positions are accurate.
|
626
|
+
newContainer.find('> li').each(function(i) {
|
627
|
+
slices.model.Page.positionSlice($(this).attr('rel'), i);
|
628
|
+
});
|
629
|
+
|
630
|
+
// Fire re-order hooks.
|
631
|
+
onReorder();
|
632
|
+
});
|
633
|
+
});
|
634
|
+
}
|
635
|
+
|
636
|
+
// Enables/disables the 'Save changes' button.
|
637
|
+
function enableSaveButton() {
|
638
|
+
$('#save-changes').attr('disabled', false);
|
639
|
+
}
|
640
|
+
function disableSaveButton() {
|
641
|
+
$('#save-changes').attr('disabled', true);
|
642
|
+
}
|
643
|
+
|
644
|
+
function updateViewLink() {
|
645
|
+
$('#page-view-on-site').attr('href', slices.model.Page.data().path);
|
646
|
+
}
|
647
|
+
|
648
|
+
function updateBreadcrumbs() {
|
649
|
+
$('#breadcrumbs .current a').html(slices.model.Page.data().name);
|
650
|
+
}
|
651
|
+
|
652
|
+
// public API
|
653
|
+
return {
|
654
|
+
init: function (pageId, settings) {
|
655
|
+
return init(pageId, settings);
|
656
|
+
}
|
657
|
+
}
|
658
|
+
|
659
|
+
}()
|
660
|
+
};
|
661
|
+
|