summaryrefslogtreecommitdiff
path: root/public/javascripts/admin_interface.js
diff options
context:
space:
mode:
Diffstat (limited to 'public/javascripts/admin_interface.js')
-rw-r--r--public/javascripts/admin_interface.js340
1 files changed, 189 insertions, 151 deletions
diff --git a/public/javascripts/admin_interface.js b/public/javascripts/admin_interface.js
index 9da5d28..f6d915f 100644
--- a/public/javascripts/admin_interface.js
+++ b/public/javascripts/admin_interface.js
@@ -1,15 +1,3 @@
1function hide_all() {
2 $('#recent_changes_toggle').attr("class", "unselected");
3 $('#my_work_toggle').attr("class", "unselected");
4 $('#current_drafts_toggle').attr("class", "unselected");
5 $('#admin_sitemap_toggle').attr("class", "unselected");
6
7 $('#current_drafts_table').hide();
8 $('#my_work_table').hide();
9 $('#recent_changes_table').hide();
10 $('#admin_sitemap_table').hide();
11}
12
13$(document).ready(function () { 1$(document).ready(function () {
14 admin_search.initialize(); 2 admin_search.initialize();
15 3
@@ -19,15 +7,29 @@ $(document).ready(function () {
19 promotion: false, 7 promotion: false,
20 menubar: false, 8 menubar: false,
21 plugins: 'code link lists visualblocks', 9 plugins: 'code link lists visualblocks',
22 toolbar: 'bold italic underline | bullist numlist | link unlink | blocks | code', 10 toolbar: 'bold italic underline | bullist numlist | link unlink | insertpageimage | blocks | code',
23 extended_valid_elements: 'aggregate[children|tags|limit|order_by|order_direction|partial|conditions]', 11 extended_valid_elements: 'aggregate[children|tags|limit|order_by|order_direction|partial|conditions],a[href|target|rel|class|data-gallery],img[class|src|alt|title|width|height|style|border]',
24 relative_urls: false, 12 relative_urls: false,
25 entity_encoding: 'raw', 13 entity_encoding: 'raw',
26 valid_classes: { '*': '' }, 14 content_style: '.inline-image--full { width: 100%; margin: 1rem 0; } .inline-image--half { width: 48%; margin-bottom: 1rem; } .inline-image--left { float: left; margin-right: 1rem; } .inline-image--right { float: right; margin-left: 1rem; }',
15 valid_classes: {
16 '*': '',
17 'img': 'inline-image inline-image--full inline-image--half inline-image--left inline-image--right',
18 'a': 'glightbox'
19 },
27 setup: function(editor) { 20 setup: function(editor) {
28 editor.on('init', function() { 21 editor.on('init', function() {
29 cccms.setup_autosave(); 22 cccms.setup_autosave();
30 }); 23 });
24
25 editor.ui.registry.addButton('insertpageimage', {
26 icon: 'image',
27 text: 'Insert image',
28 tooltip: "Insert one of this page's attached images",
29 onAction: function() {
30 cccms.inline_images.open(editor);
31 }
32 });
31 } 33 }
32 }); 34 });
33 35
@@ -43,10 +45,6 @@ $(document).ready(function () {
43 menu_item_sorter.initialize(); 45 menu_item_sorter.initialize();
44 } 46 }
45 47
46 if ($("#metadata").length != 0) {
47 meta_data.initialize();
48 }
49
50 if ($("#parent_search_term").length != 0) { 48 if ($("#parent_search_term").length != 0) {
51 parent_search.initialize_search(); 49 parent_search.initialize_search();
52 } 50 }
@@ -55,6 +53,10 @@ $(document).ready(function () {
55 move_to_search.initialize_search(); 53 move_to_search.initialize_search();
56 } 54 }
57 55
56 if ($("#restore_search_term").length != 0) {
57 restore_search.initialize_search();
58 }
59
58 if ($("#event_node_search_term").length != 0) { 60 if ($("#event_node_search_term").length != 0) {
59 event_search.initialize_search(); 61 event_search.initialize_search();
60 } 62 }
@@ -71,75 +73,38 @@ $(document).ready(function () {
71 cccms.preview.initialize(); 73 cccms.preview.initialize();
72 } 74 }
73 75
74 if ($('#recent_changes_toggle').length != 0) {
75 hide_all();
76 $('#recent_changes_toggle').attr("class", "selected");
77 $('#recent_changes_table').show();
78
79 $('#recent_changes_toggle').bind("click", function(){
80 hide_all();
81 $('#recent_changes_toggle').attr("class", "selected");
82 $('#recent_changes_table').show();
83 return false;
84 });
85
86 $('#my_work_toggle').bind("click", function(){
87 hide_all();
88 $('#my_work_toggle').attr("class", "selected");
89 $('#my_work_table').show();
90 return false;
91 });
92
93 $('#admin_wizard_my_work').bind("click", function(){
94 hide_all();
95 $('#my_work_toggle').attr("class", "selected");
96 $('#my_work_table').show();
97 return false;
98 });
99
100 $('#current_drafts_toggle').bind("click", function(){
101 hide_all();
102 $('#current_drafts_toggle').attr("class", "selected");
103 $('#current_drafts_table').show();
104 return false;
105 });
106
107 $('#admin_sitemap_toggle').bind("click", function(){
108 hide_all();
109 $('#admin_sitemap_toggle').attr("class", "selected");
110 $('#admin_sitemap_table').show();
111 return false;
112 });
113
114 $('#admin_wizard_create_page').bind("click", function(){
115 hide_all();
116 $('#admin_sitemap_toggle').attr("class", "selected");
117 $('#admin_sitemap_table').show();
118 return false;
119 });
120 }
121
122 jQuery.ajaxSetup({ 76 jQuery.ajaxSetup({
123 'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript");} 77 'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript");}
124 }); 78 });
125 79
126 $(document).ajaxSend(function(event, request, settings) { 80 $(document).ajaxSend(function(event, request, settings) {
127 if (typeof(AUTH_TOKEN) == "undefined") return; 81 var meta = document.querySelector("meta[name='csrf-token']");
128 // settings.data is a serialized string like "foo=bar&baz=boink" (or null) 82 if (meta) request.setRequestHeader("X-CSRF-Token", meta.content);
129 settings.data = settings.data || "";
130 settings.data += (settings.data ? "&" : "") + "authenticity_token=" + encodeURIComponent(AUTH_TOKEN);
131 }); 83 });
132 84
133}); 85 document.addEventListener('click', function (event) {
86 var button = event.target.closest('.copy_button');
87 if (!button) return;
88
89 var text = button.dataset.copyUrl;
90 if (text === undefined && button.dataset.copyTarget) {
91 var target = document.querySelector(button.dataset.copyTarget);
92 text = target ? target.textContent : undefined;
93 }
134 94
95 if (!text || text === '—' || !navigator.clipboard) return;
135 96
136meta_data = { 97 navigator.clipboard.writeText(text).then(function () {
137 initialize : function() { 98 var label = button.querySelector('.copy_button_label');
138 document.getElementById("metadata_details").addEventListener("toggle", function() { 99 if (!label) return;
139 if (this.open) image_interface.initialize(); 100 var original = label.textContent;
101 label.textContent = 'Copied!';
102 setTimeout(function () { label.textContent = original; }, 1500);
140 }); 103 });
141 } 104 });
142}; 105
106});
107
143 108
144cccms = { 109cccms = {
145 setup_autosave : function() { 110 setup_autosave : function() {
@@ -172,6 +137,10 @@ cccms = {
172 options = options || {}; 137 options = options || {};
173 if (options.force || page.title_has_changed() || page.abstract_has_changed() || page.body_has_changed()) { 138 if (options.force || page.title_has_changed() || page.abstract_has_changed() || page.body_has_changed()) {
174 139
140 elements.body.find('a.glightbox').each(function() {
141 if ($(this).find('img').length === 0) { $(this).remove(); }
142 });
143
175 tinymce.triggerSave(); 144 tinymce.triggerSave();
176 page.cached_title = elements.title.val(); 145 page.cached_title = elements.title.val();
177 page.cached_abstract = elements.abstract.val(); 146 page.cached_abstract = elements.abstract.val();
@@ -252,6 +221,104 @@ cccms = {
252 refresh_if_open : function() { 221 refresh_if_open : function() {
253 if (cccms.preview.is_open) cccms.preview.refresh(); 222 if (cccms.preview.is_open) cccms.preview.refresh();
254 } 223 }
224 },
225
226 inline_images: {
227 ensure_overlay: function() {
228 if ($('#inline_image_picker').length) return;
229
230 var overlay = $(
231 '<div id="inline_image_picker" style="display:none">' +
232 '<div id="inline_image_picker_grid"></div>' +
233 '<div id="inline_image_picker_actions">' +
234 '<button type="button" data-placement="full">Insert full width</button>' +
235 '<button type="button" data-placement="left">Insert, align left</button>' +
236 '<button type="button" data-placement="right">Insert, align right</button>' +
237 '<button type="button" id="inline_image_picker_cancel">Cancel</button>' +
238 '</div>' +
239 '</div>'
240 );
241 $('body').append(overlay);
242
243 overlay.on('click', '#inline_image_picker_grid img', function() {
244 overlay.find('#inline_image_picker_grid img').removeClass('selected');
245 $(this).addClass('selected');
246 cccms.inline_images.selected_index = $(this).data('index');
247 });
248
249 overlay.on('click', '[data-placement]', function() {
250 cccms.inline_images.insert($(this).data('placement'));
251 });
252
253 overlay.on('click', '#inline_image_picker_cancel', function() {
254 overlay.hide();
255 });
256 },
257
258 open: function(editor) {
259 cccms.inline_images.ensure_overlay();
260 cccms.inline_images.editor = editor;
261
262 var showUrl = $("#page_editor > form").attr("data-show-url") || "";
263 var match = showUrl.match(/(\d+)$/);
264 cccms.inline_images.node_id = match ? match[1] : "";
265
266 var items = $('#related_asset_list li').map(function() {
267 return {
268 id: $(this).data('asset-id'),
269 thumb: $(this).find('img').attr('src'),
270 large: $(this).data('large-url'),
271 original: $(this).data('original-url'),
272 name: $(this).data('name'),
273 hasCredit: $(this).data('has-credit') === true,
274 headline: $(this).data('headline') === true
275 };
276 }).get();
277 cccms.inline_images.items = items;
278
279 var grid = $('#inline_image_picker_grid').empty();
280 if (items.length === 0) {
281 grid.append('<p>No images are attached to this page yet -- attach one from the Images section first.</p>');
282 cccms.inline_images.selected_index = null;
283 } else {
284 items.forEach(function(item, i) {
285 var wrapper = $('<div class="inline_image_picker_item"></div>');
286 wrapper.append($('<img>').attr('src', item.thumb).attr('data-index', i));
287 if (item.headline) {
288 wrapper.append($('<span>', { "class": "inline_image_picker_headline_badge" }).text("Headline"));
289 }
290 grid.append(wrapper);
291 });
292 cccms.inline_images.selected_index = 0;
293 grid.find('img').first().addClass('selected');
294 }
295
296 $('#inline_image_picker').show();
297 },
298
299 escape_attr: function(str) {
300 return String(str || '').replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
301 },
302
303 insert: function(placement) {
304 var item = cccms.inline_images.items[cccms.inline_images.selected_index];
305 if (!item) return;
306
307 var classes = placement === 'full'
308 ? 'inline-image inline-image--full'
309 : 'inline-image inline-image--half inline-image--' + placement;
310
311 var esc = cccms.inline_images.escape_attr;
312 var titleForGlightbox = (item.name || '').replace(/;/g, ',');
313 var glightboxOpts = 'title: ' + esc(titleForGlightbox) +
314 (item.hasCredit ? '; description: #credit_for_asset_' + esc(item.id) : '') + ';';
315 var html = '<a href="' + esc(item.original) + '" class="glightbox" data-gallery="page-' + esc(cccms.inline_images.node_id) + '"' +
316 ' data-glightbox="' + glightboxOpts + '">' +
317 '<img src="' + esc(item.large) + '" class="' + classes + '" alt="' + esc(item.name) + '"></a>';
318
319 cccms.inline_images.editor.insertContent(html);
320 $('#inline_image_picker').hide();
321 }
255 } 322 }
256} 323}
257 324
@@ -285,77 +352,6 @@ menu_item_sorter = {
285 } 352 }
286} 353}
287 354
288image_interface = {
289
290 initialize : function() {
291
292 $("#image_browser").hide();
293 image_interface.initialize_sortable_image_box();
294 image_interface.connect_browser_and_box();
295 image_interface.set_droppable_behavior();
296 image_interface.bind_image_browser_toggle();
297 },
298
299
300 set_droppable_behavior : function() {
301 $("ul#image_box").droppable({
302 out : function(event, ui) {
303 $(ui.draggable).fadeTo("fast", 0.4);
304
305 $(ui.draggable).bind("mouseup", function() {
306 $(this).remove();
307 });
308 },
309 over : function(event, ui) {
310 $(ui.draggable).fadeTo("fast", 1.0);
311 $(ui.draggable).unbind("mouseup");
312 }
313 });
314 },
315
316 connect_browser_and_box : function() {
317 $("#image_browser ul li").draggable({
318 connectToSortable : 'ul#image_box',
319 helper : 'clone',
320 revert : 'invalid'
321 });
322 },
323
324 initialize_sortable_image_box : function() {
325
326 $("ul#image_box").sortable({
327 revert : true,
328 update : function(event, ui) {
329 images = $("ul#image_box").sortable("serialize", {attribute : "rel"});
330
331 $.ajax({
332 type : "POST",
333 url : "/pages/" + $("ul#image_box").attr("rel") + "/sort_images",
334 dataType : "json",
335 data : images + "&_method=put",
336 success : function() {
337 }
338 });
339 }
340 });
341 },
342
343 bind_image_browser_toggle : function() {
344 $("#image_browser_toggle").bind("click", function(){
345 if ($("#image_browser_toggle").attr("class") == "unselected") {
346 $("#image_browser_toggle").attr("class", "selected");
347 $("#image_browser").show();
348 }
349 else {
350 $("#image_browser_toggle").attr("class", "unselected");
351 $("#image_browser").hide();
352 }
353
354 return false;
355 });
356 }
357}
358
359rrule_builder = { 355rrule_builder = {
360 initialize : function() { 356 initialize : function() {
361 rrule_builder.try_populate_from_rrule($("#event_rrule").val()); 357 rrule_builder.try_populate_from_rrule($("#event_rrule").val());
@@ -367,8 +363,10 @@ rrule_builder = {
367 }); 363 });
368 $("#rrule_monthly_ordinal").bind("change", function() { 364 $("#rrule_monthly_ordinal").bind("change", function() {
369 $("#rrule_ordinal_fields").toggle($(this).is(":checked")); 365 $("#rrule_ordinal_fields").toggle($(this).is(":checked"));
366 rrule_builder.toggle_custom_ordinal_fields();
370 rrule_builder.sync(); 367 rrule_builder.sync();
371 }); 368 });
369 $("#rrule_ordinal").bind("change", rrule_builder.toggle_custom_ordinal_fields);
372 $("#rrule_exclude_month").bind("change", function() { 370 $("#rrule_exclude_month").bind("change", function() {
373 $("#rrule_excluded_month").toggle($(this).is(":checked")); 371 $("#rrule_excluded_month").toggle($(this).is(":checked"));
374 rrule_builder.sync(); 372 rrule_builder.sync();
@@ -385,6 +383,12 @@ rrule_builder = {
385 $("#rrule_monthly_options").show(); 383 $("#rrule_monthly_options").show();
386 }, 384 },
387 385
386 toggle_custom_ordinal_fields : function() {
387 $("#rrule_custom_ordinal_fields").toggle(
388 $("#rrule_monthly_ordinal").is(":checked") && $("#rrule_ordinal").val() === "custom"
389 );
390 },
391
388 sync : function() { 392 sync : function() {
389 var freq = $("input[name='rrule_freq']:checked").val(); 393 var freq = $("input[name='rrule_freq']:checked").val();
390 var parts = []; 394 var parts = [];
@@ -400,7 +404,16 @@ rrule_builder = {
400 } else { 404 } else {
401 parts.push("FREQ=MONTHLY"); 405 parts.push("FREQ=MONTHLY");
402 if ($("#rrule_monthly_ordinal").is(":checked")) { 406 if ($("#rrule_monthly_ordinal").is(":checked")) {
403 parts.push("BYDAY=" + $("#rrule_ordinal").val() + $("#rrule_ordinal_day").val()); 407 var ordinal = $("#rrule_ordinal").val();
408 if (ordinal === "custom") {
409 var customDays = [];
410 $("input[id^='rrule_custom_ordinal_']:checked").each(function() {
411 customDays.push($(this).attr("id").replace("rrule_custom_ordinal_", "") + $("#rrule_ordinal_day").val());
412 });
413 if (customDays.length > 0) parts.push("BYDAY=" + customDays.join(","));
414 } else {
415 parts.push("BYDAY=" + ordinal + $("#rrule_ordinal_day").val());
416 }
404 } 417 }
405 } 418 }
406 419
@@ -435,8 +448,33 @@ rrule_builder = {
435 } else if (parts.FREQ === "MONTHLY") { 448 } else if (parts.FREQ === "MONTHLY") {
436 $("input[name='rrule_freq'][value='monthly']").prop("checked", true); 449 $("input[name='rrule_freq'][value='monthly']").prop("checked", true);
437 rrule_builder.show_monthly_options(); 450 rrule_builder.show_monthly_options();
451 var ordinalDays = parts.BYDAY && parts.BYDAY.split(",");
452 var customOrdinalDay = null;
453 var customOrdinals = [];
454 var customOrdinalsValid = ordinalDays && ordinalDays.length > 0;
455 if (customOrdinalsValid) {
456 ordinalDays.forEach(function(value) {
457 var customMatch = value.match(/^([1-5])([A-Z]{2})$/);
458 if (!customMatch || (customOrdinalDay && customOrdinalDay !== customMatch[2])) {
459 customOrdinalsValid = false;
460 return;
461 }
462 customOrdinalDay = customMatch[2];
463 customOrdinals.push(customMatch[1]);
464 });
465 }
466
438 var match = parts.BYDAY && parts.BYDAY.match(/^(-?\d+)([A-Z]{2})$/); 467 var match = parts.BYDAY && parts.BYDAY.match(/^(-?\d+)([A-Z]{2})$/);
439 if (match) { 468 if (customOrdinalsValid && (customOrdinals.length > 1 || customOrdinals[0] === "5")) {
469 $("#rrule_monthly_ordinal").prop("checked", true);
470 $("#rrule_ordinal_fields").show();
471 $("#rrule_ordinal").val("custom");
472 $("#rrule_ordinal_day").val(customOrdinalDay);
473 customOrdinals.forEach(function(ordinal) {
474 $("#rrule_custom_ordinal_" + ordinal).prop("checked", true);
475 });
476 rrule_builder.toggle_custom_ordinal_fields();
477 } else if (match) {
440 $("#rrule_monthly_ordinal").prop("checked", true); 478 $("#rrule_monthly_ordinal").prop("checked", true);
441 $("#rrule_ordinal_fields").show(); 479 $("#rrule_ordinal_fields").show();
442 $("#rrule_ordinal").val(match[1]); 480 $("#rrule_ordinal").val(match[1]);