source: main/trunk/greenstone3/web/interfaces/default/js/documentedit_scripts.js@ 33508

Last change on this file since 33508 was 33508, checked in by kjdon, 5 years ago

pass a param into readyPageForEditing - indicates whether to add the MapGPS edit buttons

File size: 17.5 KB
Line 
1/** Javascript file for editing a single document's content - metadata and text */
2/** uses other functions in documentedit_scripts_util.js */
3
4/* some vars for document editing */
5/* if true, will look through all the metadata for the document, and add each namespace into the list of metadata sets. If set to false, will only add in the ones defined in setStaticMetadataSets function (defined below) - override this function to make a custom list of sets */
6var dynamic_metadata_set_list = true;
7/* if false, will hide the metadata list selector. So the user will only get to see the default metadata set. */
8var display_metadata_set_selector = true;
9/* if true, will make the editing controls stay visible even on page scrolling */
10var keep_editing_controls_visible = true;
11/* Here you can choose which save buttons you like. Choose from 'save', 'rebuild', 'saveandrebuild' */
12var save_and_rebuild_buttons = ["saveandrebuild"];
13//var save_and_rebuild_buttons = ["save", "rebuild", "saveandrebuild"];
14
15/* What kind of metadata element selection do we provide?
16plain: just a text input box
17fixedlist: a drop down menu with a fixed list of options (provided by the availableMetadataElements list)
18autocomplete: a text input box with a list of suggestions to choose from (provided by the availableMetadataElements list). Allows additional input other than the fixed list
19 */
20var new_metadata_field_input_type = "plain";
21/* add all metadata button? only valid with fixedlist or autocomplete metadata element selection */
22var enable_add_all_metadata_button = true;
23
24/* Metadata elements to be used in the fixedlist/autocomplete options above */
25var availableMetadataElements = ["dc.Title", "dc.Subject"];
26/* metadata elements that have a list of values/suggestions */
27var autocompleteMetadata = new Array();
28/* for each metadata element specified here, one should provide an array of values. The name is the meta_name + "_values", but you must strip . and _ from the name.
29for example
30var autocompleteMetadata = ["dc.Subject"];
31var dcSubject_values = ["Kings", "Queens", "others"];
32 */
33
34/* The metadata specified in multiValuedMetadata array will be treated as a delimited list, using mvm_delimiter. On saving, the values will be separated and saved individually */
35
36var multiValuedMetadata = new Array(); // eg ["xx.Person", "xx.Location"];
37var mvm_delimiter = ";";
38
39/************************
40 * METADATA EDIT SCRIPTS *
41 ************************/
42
43function addEditMetadataLink(cell) {
44 cell = $(cell);
45 var id = cell.attr("id").substring(6);
46 var metaTable = gs.jqGet("meta" + id);
47 var row = cell.parent();
48 var newCell = $("<td>", {
49 "style": "font-size:0.7em; padding:0px 10px",
50 "class": "editMetadataButton"
51 });
52 var linkSpan = $("<span>", {
53 "class": "ui-state-default ui-corner-all",
54 "style": "padding: 2px; float:left;"
55 });
56
57 var linkLabel = $("<span>" + gs.text.de.edit_metadata + "</span>");
58 var linkIcon = $("<span>", {
59 "class": "ui-icon ui-icon-folder-collapsed"
60 });
61 newCell.linkIcon = linkIcon;
62 newCell.linkLabel = linkLabel;
63
64 var uList = $("<ul>", {
65 "style": "outline: 0 none; margin:0px; padding:0px;"
66 });
67 var labelItem = $("<li>", {
68 "style": "float:left; list-style:none outside none;"
69 });
70 var iconItem = $("<li>", {
71 "style": "float:left; list-style:none outside none;"
72 });
73
74 uList.append(iconItem);
75 uList.append(labelItem);
76 labelItem.append(linkLabel);
77 iconItem.append(linkIcon);
78
79 var newLink = $("<a>", {
80 "href": "javascript:;"
81 });
82 newLink.click(function () {
83 if (metaTable.css("display") == "none") {
84 linkLabel.html(gs.text.de.hide_metadata);
85 linkIcon.attr("class", "ui-icon ui-icon-folder-open");
86 metaTable.css("display", "block");
87 metaTable.metaNameField.css("display", "inline");
88 metaTable.addRowButton.css("display", "inline");
89 if (enable_add_all_metadata_button == true) {
90 metaTable.addAllButton.css("display", "inline");
91 }
92 } else {
93 linkLabel.html(gs.text.de.edit_metadata);
94 linkIcon.attr("class", "ui-icon ui-icon-folder-collapsed");
95 metaTable.css("display", "none");
96 metaTable.metaNameField.css("display", "none");
97 metaTable.addRowButton.css("display", "none");
98 if (enable_add_all_metadata_button == true) {
99 metaTable.addAllButton.css("display", "none");
100 }
101 }
102 });
103
104 newLink.append(uList);
105 linkSpan.append(newLink);
106 newCell.append(linkSpan);
107 row.append(newCell);
108
109 addFunctionalityToTable(metaTable);
110 metaTable.metaNameField.css("display", "none");
111 metaTable.addRowButton.css("display", "none");
112 if (enable_add_all_metadata_button == true) {
113 metaTable.addAllButton.css("display", "none");
114 }
115}
116
117var gsmap_store = {};
118var gps_metadata_name = "GPS.mapOverlay";
119
120// Called by documentedit_scripts_util.js when saving and rebuilding.
121// This function should return all the doc sections' map overlay data so that
122// setArchivesMetadata can be called for each and the entire collection rebuilt with the changes
123function getDocMapsEditDataForSaving(collName) {
124 var map_editors_array = Object.values(gsmap_store);
125 var modifiedMaps = []; // the array that is the return value: an array of only all the modified maps
126
127
128 for(var i = 0; i < map_editors_array.length; i++) {
129 var map_editor = map_editors_array[i];
130 var oldMapData = map_editor.savedOverlays; // stringified JSON shape
131 var newMapData = JSON.stringify(ShapesUtil.overlayToJSON(map_editor.overlays)); // stringified JSON shape too
132
133 // We only consider a map editor's map data to have been modified in the following cases:
134 // - if oldMapData is null, new mapData should not be empty array
135 // - OR oldMapData had some value and it's not the same as newMapData
136 if(!oldMapData && newMapData !== "[]" || oldMapData && oldMapData !== newMapData) {
137 var nodeID = map_editors_array[i].id;
138 //console.log("old vs new mapdata for nodeID " + nodeID);
139 //console.log("OLD: " + oldMapData);
140 //console.log("NEW: " + newMapData);
141
142 modifiedMaps.push({
143 collection: collName,
144 docID: nodeID,
145 name:gps_metadata_name,
146 metapos: 0,
147 value:newMapData
148 });
149
150 //map_editor.savedOverlays = newMapData;
151 // Saving the new overlay values as the old ones, for the state after saving and rebuilding is done,
152 // now happens after all setArchivesMeta)_ calls have succeeded,
153 // which is just at the start of sendBuildRequest() in documentedit_scripts_util.js::saveAndRebuild()
154 }
155
156 }
157
158 return modifiedMaps;
159}
160
161
162function addEditMapGPSLink(cell) {
163 cell = $(cell);
164 var id = cell.attr("id").substring(6);
165 //console.log(id);
166 var mapGPScontainer = gs.jqGet("map-and-controls-" + id);
167 var row = cell.parent();
168 var newCell = $("<td>", {
169 "style": "font-size:0.7em; padding:0px 10px",
170 "class": "editMapGPSButton"
171 });
172 var linkSpan = $("<span>", {
173 "class": "ui-state-default ui-corner-all",
174 "style": "padding: 2px; float:left;"
175 });
176
177 var linkLabel = $("<span>" + gs.text.de.edit_map_gps + "</span>");
178 var linkIcon = $("<span>", {
179 "class": "ui-icon ui-icon-folder-collapsed"
180 });
181 newCell.linkIcon = linkIcon;
182 newCell.linkLabel = linkLabel;
183
184 var uList = $("<ul>", {
185 "style": "outline: 0 none; margin:0px; padding:0px;"
186 });
187 var labelItem = $("<li>", {
188 "style": "float:left; list-style:none outside none;"
189 });
190 var iconItem = $("<li>", {
191 "style": "float:left; list-style:none outside none;"
192 });
193
194 uList.append(iconItem);
195 uList.append(labelItem);
196 labelItem.append(linkLabel);
197 iconItem.append(linkIcon);
198
199 var mapEditor = new MapEditor(id);
200 gsmap_store["map-" + id] = mapEditor;
201
202 var newLink = $("<a>", {
203 "href": "javascript:;"
204 });
205 newLink.click(function () {
206 //console.log(" Show/Hide Map Editor ");
207 var clicked_mapEditor = gsmap_store["map-" + id];
208
209 if (clicked_mapEditor.map == null) {
210 clicked_mapEditor.initMapEditorControls();
211 clicked_mapEditor.initMapEditor();
212 }
213 if (mapGPScontainer.css("display") == "none") {
214 linkLabel.html(gs.text.de.hide_map_gps);
215 linkIcon.attr("class", "ui-icon ui-icon-folder-open");
216 mapGPScontainer.css("display", "block");
217 } else {
218 linkLabel.html(gs.text.de.edit_map_gps);
219 linkIcon.attr("class", "ui-icon ui-icon-folder-collapsed");
220 mapGPScontainer.css("display", "none");
221
222 }
223 });
224
225 newLink.append(uList);
226 linkSpan.append(newLink);
227 newCell.append(linkSpan);
228 row.append(newCell);
229
230 mapGPScontainer.css("display", "none");
231
232}
233
234function setEditingFeaturesVisible(visible) {
235 if (visible) {
236 $("#editContentButton").html(gs.text.de.hide_editor);
237 $("#editContentButtonDiv").attr("class", "ui-state-default ui-corner-all");
238 } else {
239 $("#editContentButton").html(gs.text.de.edit_content);
240 $("#editContentButtonDiv").attr("class", "");
241 }
242
243 var visibility = (visible ? "" : "none");
244 if (display_metadata_set_selector == true) {
245 $("#metadataListLabel, #metadataSetList").css("display", visibility);
246 }
247
248 $(".editMetadataButton").each(function () {
249 $(this).css("display", visibility);
250 $(this.linkLabel).html(gs.text.de.edit_metadata);
251 $(this.linkIcon).attr("class", "ui-icon ui-icon-folder-collapsed");
252 });
253 /*
254 $(".editMapGPS").each(function(){
255 $(this).css("display", visibility);
256 $(this.linkLabel).html(gs.text.de.edit_map_gps);
257 $(this.linkIcon).attr("class", "ui-icon ui-icon-folder-collapsed");
258 });
259 */
260
261 $("table").each(function () {
262 if ($(this).attr("id") && $(this).attr("id").search(/^meta/) != -1) {
263 $(this).css("display", "none");
264 $(this.metaNameField).css("display", "none");
265 $(this.addRowButton).css("display", "none");
266 if (enable_add_all_metadata_button == true) {
267 $(this.addAllButton).css("display", "none");
268 }
269 }
270 });
271}
272
273/* override this function in other interface/site/collection if you want
274a different set of metadata sets
275Use in conjunction with the dynamic_metadata_set_list variable. */
276function setStaticMetadataSets(list) {
277 addOptionToList(list, "All", gs.text.de.all_metadata);
278}
279
280function readyPageForEditing(mapGPSEditingAllowed) {
281
282 if ($("#metadataSetList").length) {
283 var setList = $("#metadataSetList");
284 if (!setList.css("display") || setList.css("display") == "") {
285 setEditingFeaturesVisible(false);
286 } else {
287 setEditingFeaturesVisible(true);
288 }
289 return;
290 }
291
292 $("#editContentButton").html(gs.text.de.hide_editor);
293 //wait for 0.5 sec to let ckeditor up
294
295 // Initialising editableInitStates for CKEDITOR instances now happens in the CKEDITOR.on('instanceReady') handler, which is added upon docReady, see documentedit_scripts_util::$( document ).ready(...)
296 // Attempting CKEDITOR.on('instanceReady') at the start of this method or anywhere in this method didn't work because it was probably too late in page load phase to add the event handler then
297 // (the instanceReady() event would have been triggered before this method finally got called).
298
299 var editBar = $("#editBarLeft");
300
301 var visibleMetadataList = $("<select>", {
302 "id": "metadataSetList",
303 "class": "ui-state-default"
304 });
305 setStaticMetadataSets(visibleMetadataList);
306
307 if (display_metadata_set_selector == true) {
308 var metadataListLabel = $("<span>", {
309 "id": "metadataListLabel",
310 "style": "margin-left:20px;"
311 });
312 metadataListLabel.html(gs.text.de.visible_metadata);
313 editBar.append(metadataListLabel);
314 } else {
315 visibleMetadataList.css("display", "none");
316 }
317 editBar.append(visibleMetadataList);
318 visibleMetadataList.change(onVisibleMetadataSetChange);
319 editBar.append("<br>");
320
321 for (var i = 0; i < save_and_rebuild_buttons.length; i++) {
322 var button_type = save_and_rebuild_buttons[i];
323 if (button_type == "save") {
324 var saveButton = $("<button>", {
325 "id": "saveButton",
326 "class": "ui-state-default ui-corner-all"
327 });
328 saveButton.click(save);
329 saveButton.html(gs.text.de.save);
330 editBar.append(saveButton);
331 } else if (button_type == "rebuild") {
332 var rebuildButton = $("<button>", {
333 "id": "rebuildButton",
334 "class": "ui-state-default ui-corner-all"
335 });
336 rebuildButton.click(rebuildCurrentCollection);
337 rebuildButton.html(gs.text.de.rebuild);
338 editBar.append(rebuildButton);
339 } else if (button_type == "saveandrebuild") {
340 var saveAndRebuildButton = $("<button>", {
341 "id": "saveAndRebuildButton",
342 "class": "ui-state-default ui-corner-all"
343 });
344 saveAndRebuildButton.click(saveAndRebuild);
345 saveAndRebuildButton.html(gs.text.de.saverebuild);
346 editBar.append(saveAndRebuildButton);
347
348 }
349 }
350 var statusBarDiv = $("<div>");
351 editBar.append(statusBarDiv);
352 _statusBar = new StatusBar(statusBarDiv[0]);
353
354 var titleDivs = $(".sectionTitle");
355 for (var i = 0; i < titleDivs.length; i++) {
356 addEditMetadataLink(titleDivs[i]);
357 if (mapGPSEditingAllowed) {
358 addEditMapGPSLink(titleDivs[i]);
359 }
360 }
361
362 // We need to keep track of editableElementsInitialisationProgress: the number of editable elements that need to be initialised/need to finish initialising
363 // As CKEditors will be added, meaning more editable elements, must increment our counter editableElementsInitialisationProgress
364 //var $num_editable_textareas = $(".sectionText"); // consider searching for 'contenteditable="true"' as this is what CKEDITOR is looking for (we think!)
365 // I think for us it's always a <div> that has contenteditable="true", but to get all elements with attr contenteditable set to true,
366 // see https://stackoverflow.com/questions/4958081/find-all-elements-with-a-certain-attribute-value-in-jquery
367 // which has inefficient and slightly more efficient ways of doing that
368 var $num_editable_textareas = $('div[contenteditable="true"]');
369 editableElementsInitialisationProgress += $num_editable_textareas.length;
370
371 _baseURL = gs.xsltParams.library_name;
372 onVisibleMetadataSetChange(); // make sure that the selected item in the list is active
373
374 // If the user is attempting to leave the page, check if there are unsaved changes
375 // and if so, display an "Are you sure you want to leave" message.
376 // https://stackoverflow.com/questions/7080269/javascript-before-leaving-the-page
377 // Newer versions of Firefox/Chrome don't display custom message (security feature):
378 // https://stackoverflow.com/questions/22776544/why-is-jquery-onbeforeunload-not-working-in-chrome-and-firefox
379 // and http://jsfiddle.net/XZAWS/
380 // jquery bind() is deprecated: https://stackoverflow.com/questions/33654716/is-jquery-bind-deprecated
381
382 $(window).on("beforeunload", function(event) {
383
384 if(gs.cgiParams.docEdit == "1") { // like document.xsl, which checks the same var upon onload
385 // shouldn't check for whether changes are saved unless on Doc Editing page (DocEdit=1)
386 // else the following pop up always ends up appearing when attempting
387 // to leave a doc view page in Doc Editing Mode (when not yet actually Doc Editing)
388
389 // Because we've done extra work now in maintaining "editableElementsInitialisationProgress", which is
390 // the number of editable elements that still need to finish initialising, we can now be confident that
391 // the call to changesToUpdate() below won't return the wrong answers if a page with docEdit turned on
392 // is asked to unload (e.g. by pressing Reload) before the page has finished loading.
393 var changes = changesToUpdate();
394
395 //console.log("#### CHANGES before page reload: ", changes);
396
397 if(changes.length > 0) {
398 console.log("The collection hasn't yet been saved after editing. Are you sure you want to leave?");
399 return "The collection hasn't yet been saved after editing. Are you sure you want to leave?";
400 }
401 }
402 });
403
404
405}
406
407// override the one in documentmaker_scripts_util
408// currently not used if other one is present. need to get the js include order right
409function enableSaveButtons(enabled) {
410 if (enabled) {
411 $("#saveButton, #rebuildButton, #saveAndRebuildButton").removeAttr("disabled");
412 } else {
413 $("#saveButton, #rebuildButton, #saveAndRebuildButton").attr("disabled", "disabled");
414 }
415}
416
417/* this is a cut down version of save() from documentmaker_scripts_util.js
418going back to using save, will delete this once everything working*/
419function saveMetadataChangesOld() {
420
421 console.log("Saving metadata changes");
422
423 // get collection name
424 var collection = gs.cgiParams.c;
425
426 // get document id
427 var docID = gs.cgiParams.d;
428
429 var metadataChanges = new Array();
430 if (_deletedMetadata.length > 0) {
431
432 for (var i = 0; i < _deletedMetadata.length; i++) {
433
434 var currentRow = _deletedMetadata[i];
435
436 //Get metadata name
437 var cells = currentRow.getElementsByTagName("TD");
438 var nameCell = cells[0];
439 var name = nameCell.innerHTML;
440 var valueCell = cells[1];
441 var value = valueCell.innerHTML;
442 metadataChanges.push({
443 type: 'delete',
444 docID: docID,
445 name: name,
446 value: value
447 });
448 removeFromParent(currentRow);
449 }
450 }
451
452 if (metadataChanges.length == 0) {
453 console.log(gs.text.de.no_changes);
454 return;
455 }
456
457 var processChangesLoop = function (index) {
458 var change = metadataChanges[index];
459
460 var callbackFunction;
461 if (index + 1 == metadataChanges.length) {
462 callbackFunction = function () {
463 console.log("Completed saving metadata changes. You must rebuild the collection for the changes to take effect.");
464 };
465 } else {
466 callbackFunction = function () {
467 processChangesLoop(index + 1)
468 };
469 }
470 if (change.type == "delete") {
471 gs.functions.removeArchivesMetadata(collection, gs.xsltParams.site_name, change.docID, change.name, null, change.value, function () {
472 callbackFunction();
473 });
474 } else {
475 if (change.orig) {
476 gs.functions.setArchivesMetadata(collection, gs.xsltParams.site_name, docID, change.name, null, change.value, change.orig, "override", function () {
477 callbackFunction();
478 });
479 } else {
480 gs.functions.setArchivesMetadata(collection, gs.xsltParams.site_name, docID, change.name, null, change.value, null, "accumulate", function () {
481 callbackFunction();
482 });
483 }
484 }
485 }
486 processChangesLoop(0);
487 /* need to clear the changes from the page */
488 while (_deletedMetadata.length > 0) {
489 _deletedMetadata.pop();
490 }
491
492}
Note: See TracBrowser for help on using the repository browser.