001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: https://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: https://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.ade.containerpage.client; 029 030import org.opencms.ade.containerpage.client.CmsContainerpageController.I_ReloadHandler; 031import org.opencms.ade.containerpage.client.ui.CmsContainerPageContainer; 032import org.opencms.ade.containerpage.client.ui.CmsContainerPageElementPanel; 033import org.opencms.ade.containerpage.client.ui.CmsOptionDialog; 034import org.opencms.ade.containerpage.client.ui.I_CmsDropContainer; 035import org.opencms.ade.containerpage.shared.CmsCntPageData; 036import org.opencms.ade.containerpage.shared.CmsDialogOptionsAndInfo; 037import org.opencms.ade.contenteditor.client.CmsContentEditor; 038import org.opencms.ade.contenteditor.client.CmsEditorContext; 039import org.opencms.ade.contenteditor.client.I_CmsEditorCloseHandler; 040import org.opencms.ade.contenteditor.shared.CmsContentDefinition; 041import org.opencms.ade.contenteditor.shared.CmsEditHandlerData; 042import org.opencms.ade.publish.shared.CmsPublishOptions; 043import org.opencms.gwt.client.CmsCoreProvider; 044import org.opencms.gwt.client.CmsEditableData; 045import org.opencms.gwt.client.I_CmsEditableData; 046import org.opencms.gwt.client.ui.contenteditor.CmsContentEditorDialog; 047import org.opencms.gwt.client.ui.contenteditor.CmsContentEditorDialog.DialogOptions; 048import org.opencms.gwt.client.ui.contenteditor.I_CmsContentEditorHandler; 049import org.opencms.gwt.client.util.CmsDebugLog; 050import org.opencms.gwt.client.util.CmsDomUtil; 051import org.opencms.gwt.client.util.I_CmsSimpleCallback; 052import org.opencms.gwt.shared.CmsGwtConstants; 053import org.opencms.util.CmsStringUtil; 054import org.opencms.util.CmsUUID; 055 056import java.util.ArrayList; 057import java.util.HashMap; 058import java.util.List; 059import java.util.Map; 060 061import com.google.gwt.dom.client.Element; 062import com.google.gwt.http.client.URL; 063import com.google.gwt.json.client.JSONBoolean; 064import com.google.gwt.json.client.JSONNumber; 065import com.google.gwt.json.client.JSONObject; 066import com.google.gwt.json.client.JSONString; 067import com.google.gwt.user.client.Command; 068import com.google.gwt.user.client.History; 069import com.google.gwt.user.client.Timer; 070import com.google.gwt.user.client.Window; 071 072import elemental2.dom.DomGlobal; 073import jsinterop.base.Js; 074 075/** 076 * The container-page editor implementation of the XML content editor handler.<p> 077 * 078 * @since 8.0.0 079 */ 080public class CmsContentEditorHandler implements I_CmsContentEditorHandler { 081 082 /** Content editor hash key whre a return to the opened editor is not possible. */ 083 private static final String EDITOR_FOR_NO_RETURN_HASH_KEY = "cE"; 084 085 /** Content editor hash key used for history management. */ 086 private static final String EDITOR_HASH_KEY = "cE:"; 087 088 /** Saved scroll position. */ 089 public static Integer scrollPosition; 090 091 /** The container-page handler. */ 092 CmsContainerpageHandler m_handler; 093 094 /** The content element to be replaced by the edited content. */ 095 CmsContainerPageElementPanel m_replaceElement; 096 097 /** The currently edited element's id. */ 098 private String m_currentElementId; 099 100 /** The depending element's id. */ 101 private String m_dependingElementId; 102 103 /** Flag indicating the content editor is currently opened. */ 104 private boolean m_editorOpened; 105 106 /** 107 * Constructor.<p> 108 * 109 * @param handler the container-page handler 110 */ 111 public CmsContentEditorHandler(CmsContainerpageHandler handler) { 112 113 m_handler = handler; 114 } 115 116 /** 117 * Closes the content editor.<p> 118 */ 119 public void closeContentEditor() { 120 121 CmsContentEditor.getInstance().closeEditor(); 122 m_editorOpened = false; 123 } 124 125 /** 126 * @see org.opencms.gwt.client.ui.contenteditor.I_CmsContentEditorHandler#onClose(java.lang.String, org.opencms.util.CmsUUID, boolean, boolean, boolean) 127 */ 128 public void onClose( 129 String sitePath, 130 CmsUUID structureId, 131 boolean isNew, 132 boolean hasChangedSettings, 133 boolean usedPublishDialog) { 134 135 if (m_currentElementId == null) { 136 m_currentElementId = structureId.toString(); 137 } 138 // we keep track of how many reloads are still ongoing - if all of them are done, we can send the edit events 139 final int[] reloadCounter = {0}; 140 141 I_ReloadHandler reloadHandler = new I_ReloadHandler() { 142 143 private List<Runnable> m_todo = new ArrayList<>(); 144 145 @Override 146 public void finish() { 147 148 if (usedPublishDialog) { 149 m_handler.m_controller.startPublishLockCheck(); 150 } 151 reloadCounter[0] -= 1; 152 if (reloadCounter[0] <= 0) { 153 m_todo.forEach(item -> item.run()); 154 } 155 if (scrollPosition != null) { 156 final int top = scrollPosition.intValue(); 157 scrollPosition = null; 158 Timer timer = new Timer() { 159 160 @Override 161 public void run() { 162 163 DomGlobal.document.documentElement.scrollTop = top; 164 } 165 166 }; 167 timer.schedule(1); 168 } 169 170 } 171 172 @Override 173 public void onReload(CmsContainerPageElementPanel oldElement, CmsContainerPageElementPanel newElement) { 174 175 m_todo.add(() -> { 176 m_handler.m_controller.sendElementEditedContent( 177 newElement, 178 Js.cast(oldElement.getElement()), 179 isNew); 180 181 }); 182 } 183 184 }; 185 186 if (m_replaceElement != null) { 187 if ((m_handler.m_controller.getData().getDetailId() != null) 188 && m_replaceElement.getId().startsWith(m_handler.m_controller.getData().getDetailId().toString())) { 189 Window.Location.assign( 190 CmsStringUtil.joinPaths( 191 CmsCoreProvider.get().getVfsPrefix(), 192 CmsContainerpageController.getCurrentUri(), 193 CmsContainerpageController.getServerId(m_currentElementId))); 194 } 195 reloadCounter[0] += 1; 196 m_handler.m_controller.replaceElement(m_replaceElement, m_currentElementId, reloadHandler); 197 m_replaceElement = null; 198 if (m_dependingElementId != null) { 199 reloadCounter[0] += 1; 200 m_handler.m_controller.reloadElements(new String[] {m_dependingElementId}, reloadHandler); 201 m_dependingElementId = null; 202 } 203 } else if (m_dependingElementId != null) { 204 reloadCounter[0] += 1; 205 m_handler.m_controller.reloadElements( 206 new String[] {m_currentElementId, m_dependingElementId}, 207 reloadHandler); 208 m_dependingElementId = null; 209 } else { 210 reloadCounter[0] += 1; 211 m_handler.m_controller.reloadElements(new String[] {m_currentElementId}, reloadHandler); 212 } 213 if (m_currentElementId != null) { 214 m_handler.addToRecent(m_currentElementId); 215 } 216 m_handler.enableToolbarButtons(); 217 m_handler.activateSelection(); 218 m_handler.m_controller.setContentEditing(false); 219 m_handler.m_controller.reInitInlineEditing(); 220 m_currentElementId = null; 221 if (hasChangedSettings) { 222 m_handler.m_controller.setPageChanged(new Runnable[] {}); 223 } 224 m_editorOpened = false; 225 } 226 227 /** 228 * Opens the XML content editor.<p> 229 * 230 * @param element the container element widget 231 * @param inline <code>true</code> to open the in-line editor for the given element if available 232 * @param wasNew <code>true</code> in case this is a newly created element not previously edited 233 */ 234 public void openDialog(final CmsContainerPageElementPanel element, final boolean inline, boolean wasNew) { 235 236 if (!inline && element.hasEditHandler()) { 237 m_handler.m_controller.getEditOptions( 238 element.getId(), 239 false, 240 new I_CmsSimpleCallback<CmsDialogOptionsAndInfo>() { 241 242 public void execute(CmsDialogOptionsAndInfo editOptions) { 243 244 final I_CmsSimpleCallback<CmsUUID> editCallBack = new I_CmsSimpleCallback<CmsUUID>() { 245 246 public void execute(CmsUUID arg) { 247 248 String contentId = element.getId(); 249 if (!element.getId().startsWith(arg.toString())) { 250 // the content structure ID has changed, the current element needs to be replaced after editing 251 m_replaceElement = element; 252 contentId = arg.toString(); 253 } 254 internalOpenDialog(element, contentId, inline, wasNew); 255 } 256 }; 257 if (editOptions == null) { 258 internalOpenDialog(element, element.getId(), inline, wasNew); 259 } else if (editOptions.getOptions().getOptions().size() == 1) { 260 m_handler.m_controller.prepareForEdit( 261 element.getId(), 262 editOptions.getOptions().getOptions().get(0).getValue(), 263 editCallBack); 264 } else { 265 CmsOptionDialog dialog = new CmsOptionDialog( 266 Messages.get().key(Messages.GUI_EDIT_HANDLER_SELECT_EDIT_OPTION_0), 267 editOptions.getOptions(), 268 editOptions.getInfo(), 269 new I_CmsSimpleCallback<String>() { 270 271 public void execute(String arg) { 272 273 m_handler.m_controller.prepareForEdit(element.getId(), arg, editCallBack); 274 } 275 }); 276 dialog.addDialogClose(new Command() { 277 278 public void execute() { 279 280 cancelEdit(); 281 } 282 }); 283 dialog.center(); 284 } 285 } 286 }); 287 } else { 288 internalOpenDialog(element, element.getId(), inline, wasNew); 289 } 290 } 291 292 /** 293 * Opens the XML content editor, checking for if an edit handler is configured first.<p> 294 * 295 * @param editableData the data of the element to edit 296 * @param isNew <code>true</code> if a new resource should be created 297 * @param dependingElementId the id of a depending element 298 * @param mode the element creation mode 299 * @param handlerDataForNew the edit handler data, if we are using an edit handler to create a new element; null otherwise 300 */ 301 public void openDialog( 302 final I_CmsEditableData editableData, 303 final boolean isNew, 304 final String dependingElementId, 305 final String mode, 306 final CmsEditHandlerData handlerDataForNew) { 307 308 if (!m_editorOpened) { 309 m_editorOpened = true; 310 m_handler.disableToolbarButtons(); 311 m_handler.deactivateCurrentButton(); 312 313 if (!isNew && (editableData.getStructureId() != null) && editableData.hasEditHandler()) { 314 final String elementId = CmsContentEditor.getClientIdForEditable(editableData); 315 m_handler.m_controller.getEditOptions( 316 elementId, 317 true, 318 new I_CmsSimpleCallback<CmsDialogOptionsAndInfo>() { 319 320 public void execute(CmsDialogOptionsAndInfo editOptions) { 321 322 final I_CmsSimpleCallback<CmsUUID> editCallBack = new I_CmsSimpleCallback<CmsUUID>() { 323 324 public void execute(CmsUUID arg) { 325 326 I_CmsEditableData data = editableData; 327 if (!data.getStructureId().equals(arg)) { 328 // the content structure ID has changed, change the editableData 329 data = new CmsEditableData(data); 330 ((CmsEditableData)data).setStructureId(arg); 331 } 332 internalOpenDialog(data, isNew, dependingElementId, mode, null); 333 } 334 }; 335 if (editOptions == null) { 336 internalOpenDialog(editableData, isNew, dependingElementId, mode, null); 337 } else if (editOptions.getOptions().getOptions().size() == 1) { 338 m_handler.m_controller.prepareForEdit( 339 elementId, 340 editOptions.getOptions().getOptions().get(0).getValue(), 341 editCallBack); 342 } else { 343 CmsOptionDialog dialog = new CmsOptionDialog( 344 Messages.get().key(Messages.GUI_EDIT_HANDLER_SELECT_EDIT_OPTION_0), 345 editOptions.getOptions(), 346 editOptions.getInfo(), 347 new I_CmsSimpleCallback<String>() { 348 349 public void execute(String arg) { 350 351 m_handler.m_controller.prepareForEdit(elementId, arg, editCallBack); 352 } 353 }); 354 dialog.addDialogClose(new Command() { 355 356 public void execute() { 357 358 cancelEdit(); 359 } 360 }); 361 dialog.center(); 362 } 363 } 364 }); 365 } else { 366 internalOpenDialog(editableData, isNew, dependingElementId, mode, handlerDataForNew); 367 } 368 369 } else { 370 CmsDebugLog.getInstance().printLine("Editor is already being opened."); 371 } 372 } 373 374 /** 375 * Opens the content editor according to the history hash.<p> 376 * 377 * @param historyHash the history hash 378 */ 379 public void openEditorForHistory(String historyHash) { 380 381 if (historyHash.startsWith(EDITOR_HASH_KEY)) { 382 if (!m_editorOpened) { 383 m_editorOpened = true; 384 CmsDebugLog.getInstance().printLine("EditorHandler - Opening editor from history"); 385 m_handler.m_controller.setContentEditing(true); 386 String id = historyHash.substring(EDITOR_HASH_KEY.length(), historyHash.indexOf(";")); 387 if (id.contains(",")) { 388 String[] ids = id.split(","); 389 m_currentElementId = URL.decodePathSegment(ids[0]); 390 m_dependingElementId = URL.decodePathSegment(ids[1]); 391 } else { 392 m_currentElementId = URL.decodePathSegment(id); 393 } 394 I_CmsEditorCloseHandler onClose = new I_CmsEditorCloseHandler() { 395 396 public void onClose(boolean hasChangedSettings, boolean usedPublishDialog) { 397 398 addClosedEditorHistoryItem(); 399 CmsContentEditorHandler.this.onClose( 400 null, 401 new CmsUUID(getCurrentElementId()), 402 false, 403 hasChangedSettings, 404 usedPublishDialog); 405 } 406 }; 407 String editorLocale = CmsCoreProvider.get().getLocale(); 408 409 CmsContentEditor.getInstance().openFormEditor( 410 getEditorContext(), 411 editorLocale, 412 m_currentElementId, 413 null, 414 null, 415 null, 416 null, 417 null, 418 m_handler.m_controller.getData().getMainLocale(), 419 null, 420 onClose); 421 } 422 } else { 423 closeContentEditor(); 424 } 425 } 426 427 /** 428 * Returns the currently edited element's id.<p> 429 * 430 * @return the currently edited element's id 431 */ 432 protected String getCurrentElementId() { 433 434 return m_currentElementId; 435 } 436 437 /** 438 * Adds a history item for the closed editor.<p> 439 */ 440 void addClosedEditorHistoryItem() { 441 442 History.newItem("", false); 443 } 444 445 /** 446 * Cancels opening the editor.<p> 447 */ 448 void cancelEdit() { 449 450 m_handler.enableToolbarButtons(); 451 m_handler.activateSelection(); 452 m_handler.m_controller.setContentEditing(false); 453 m_handler.m_controller.reInitInlineEditing(); 454 m_replaceElement = null; 455 m_dependingElementId = null; 456 m_currentElementId = null; 457 m_editorOpened = false; 458 } 459 460 /** 461 * Gets the editor context to use for the Acacia editor.<p> 462 * 463 * @return the editor context 464 */ 465 CmsEditorContext getEditorContext() { 466 467 CmsEditorContext result = new CmsEditorContext(); 468 result.getPublishParameters().put( 469 CmsPublishOptions.PARAM_CONTAINERPAGE, 470 "" + CmsCoreProvider.get().getStructureId()); 471 result.getPublishParameters().put( 472 CmsPublishOptions.PARAM_DETAIL, 473 "" + CmsContainerpageController.get().getData().getDetailId()); 474 result.getPublishParameters().put(CmsPublishOptions.PARAM_START_WITH_CURRENT_PAGE, ""); 475 elemental2.dom.HTMLMetaElement meta = Js.cast( 476 elemental2.dom.DomGlobal.document.querySelector( 477 "meta[name=" + CmsGwtConstants.META_EDITOR_STYLESHEET + "]")); 478 if (meta != null) { 479 result.setEditorStylesheet(meta.content); 480 } 481 return result; 482 } 483 484 /** 485 * Opens the edit dialog.<p> 486 * 487 * @param element the element to edit 488 * @param editContentId the edit content id 489 * @param inline <code>true</code> to edit the content inline 490 * @param wasNew <code>true</code> in case this is a newly created element not previously edited 491 */ 492 void internalOpenDialog( 493 final CmsContainerPageElementPanel element, 494 String editContentId, 495 final boolean inline, 496 boolean wasNew) { 497 498 if (!m_editorOpened) { 499 m_editorOpened = true; 500 m_handler.disableToolbarButtons(); 501 m_handler.deactivateCurrentButton(); 502 m_currentElementId = editContentId; 503 final String serverId = CmsContainerpageController.getServerId(m_currentElementId); 504 final Runnable classicEdit = new Runnable() { 505 506 public void run() { 507 508 CmsEditableData editableData = new CmsEditableData(); 509 editableData.setElementLanguage(CmsCoreProvider.get().getLocale()); 510 editableData.setStructureId(new CmsUUID(serverId)); 511 editableData.setSitePath(element.getSitePath()); 512 editableData.setMainLanguage(m_handler.m_controller.getData().getMainLocale()); 513 CmsContentEditorDialog.get().openEditDialog( 514 editableData, 515 false, 516 null, 517 new DialogOptions(), 518 CmsContentEditorHandler.this); 519 } 520 }; 521 522 if (m_handler.m_controller.getData().isUseClassicEditor() || element.isNewEditorDisabled()) { 523 classicEdit.run(); 524 } else { 525 String editorLocale = CmsCoreProvider.get().getLocale(); 526 final String mainLocale; 527 if (m_handler.m_controller.getData().getMainLocale() == null) { 528 Element htmlEl = CmsDomUtil.querySelector( 529 "[" + CmsGwtConstants.ATTR_DATA_ID + "*='" + serverId + "']", 530 element.getElement()); 531 if (htmlEl != null) { 532 String entityId = htmlEl.getAttribute(CmsGwtConstants.ATTR_DATA_ID); 533 mainLocale = CmsContentDefinition.getLocaleFromId(entityId); 534 } else { 535 mainLocale = null; 536 } 537 } else { 538 mainLocale = m_handler.m_controller.getData().getMainLocale(); 539 } 540 I_CmsEditorCloseHandler onClose = new I_CmsEditorCloseHandler() { 541 542 public void onClose(boolean hasChangedSettings, boolean usedPublishDialog) { 543 544 addClosedEditorHistoryItem(); 545 CmsContentEditorHandler.this.onClose( 546 element.getSitePath(), 547 new CmsUUID(serverId), 548 wasNew, 549 hasChangedSettings, 550 usedPublishDialog); 551 552 } 553 }; 554 if (inline && CmsContentEditor.hasEditable(element.getElement())) { 555 addEditingHistoryItem(true); 556 CmsEditorContext context = getEditorContext(); 557 context.setReusedElement(element.isReused()); 558 context.setHtmlContextInfo(getContextInfo(element)); 559 // remove expired style before initializing the editor 560 element.setReleasedAndNotExpired(true); 561 // in case of new elements, ignore load time 562 long loadTime = wasNew ? Long.MAX_VALUE : m_handler.m_controller.getLoadTime(); 563 CmsContentEditor.getInstance().openInlineEditor( 564 context, 565 new CmsUUID(serverId), 566 editorLocale, 567 element, 568 mainLocale, 569 loadTime, 570 onClose); 571 } else { 572 addEditingHistoryItem(false); 573 Map<String, String> settingPresets = new HashMap<String, String>(); 574 CmsEditorContext context = getEditorContext(); 575 context.setReusedElement(element.isReused()); 576 I_CmsDropContainer dropContainer = element.getParentTarget(); 577 if (dropContainer instanceof CmsContainerPageContainer) { 578 CmsContainerPageContainer container = (CmsContainerPageContainer)dropContainer; 579 settingPresets.putAll(container.getSettingPresets()); 580 } 581 context.setSettingPresets(settingPresets); 582 583 boolean allowSettings = m_handler.m_controller.getData().allowSettingsInEditor() 584 && !m_handler.m_controller.isEditingDisabled() 585 && !serverId.equals(String.valueOf(m_handler.m_controller.getData().getDetailId())); 586 I_CmsSimpleCallback<Boolean> openEditor = new I_CmsSimpleCallback<Boolean>() { 587 588 public void execute(Boolean lockedPage) { 589 590 CmsContentEditor.getInstance().openFormEditor( 591 context, 592 editorLocale, 593 serverId, 594 lockedPage.booleanValue() ? getCurrentElementId() : null, 595 null, 596 null, 597 null, 598 null, 599 mainLocale, 600 null, 601 onClose); 602 } 603 }; 604 if (allowSettings) { 605 if (m_handler.m_controller.getData().getDetailContainerPage() != null) { 606 CmsCoreProvider.get().lock( 607 m_handler.m_controller.getData().getDetailContainerPage(), 608 m_handler.m_controller.getLoadTime(), 609 openEditor); 610 } else { 611 CmsCoreProvider.get().lock( 612 CmsCoreProvider.get().getStructureId(), 613 m_handler.m_controller.getLoadTime(), 614 openEditor); 615 } 616 } else { 617 openEditor.execute(Boolean.FALSE); 618 } 619 620 } 621 } 622 } else { 623 CmsDebugLog.getInstance().printLine("Editor is already being opened."); 624 } 625 } 626 627 /** 628 * Opens the XML content editor internally.<p> 629 * 630 * @param editableData the data of the element to edit 631 * @param isNew <code>true</code> if a new resource should be created 632 * @param dependingElementId the id of a depending element 633 * @param mode the element creation mode 634 * @param editHandlerData the edit handler data, if we are using an edit handler to create a new element; null otherwise 635 */ 636 void internalOpenDialog( 637 final I_CmsEditableData editableData, 638 final boolean isNew, 639 String dependingElementId, 640 String mode, 641 CmsEditHandlerData editHandlerData) { 642 643 if ((editableData.getStructureId() != null) && !isNew) { 644 m_currentElementId = editableData.getStructureId().toString(); 645 } else { 646 m_currentElementId = null; 647 } 648 m_dependingElementId = dependingElementId; 649 if (m_handler.m_controller.getData().isUseClassicEditor()) { 650 CmsContentEditorDialog.get().openEditDialog(editableData, isNew, mode, new DialogOptions(), this); 651 } else { 652 String newLink = null; 653 if (isNew) { 654 newLink = editableData.getNewLink(); 655 // the new link is URL encoded twice, decode it 656 newLink = URL.decodeQueryString(newLink); 657 newLink = URL.decodeQueryString(newLink); 658 } 659 addEditingHistoryItem(isNew); 660 CmsContentEditor.getInstance().openFormEditor( 661 getEditorContext(), 662 CmsCoreProvider.get().getLocale(), 663 editableData.getStructureId().toString(), 664 null, 665 newLink, 666 null, 667 editableData.getPostCreateHandler(), 668 mode, 669 m_handler.m_controller.getData().getMainLocale(), 670 editHandlerData, 671 new I_CmsEditorCloseHandler() { 672 673 public void onClose(boolean hasChangedSettings, boolean usedPublishDialog) { 674 675 addClosedEditorHistoryItem(); 676 CmsContentEditorHandler.this.onClose( 677 editableData.getSitePath(), 678 editableData.getStructureId(), 679 isNew, 680 hasChangedSettings, 681 usedPublishDialog); 682 } 683 }); 684 } 685 686 } 687 688 /** 689 * Adds a history item for the opened editor.<p> 690 * Use the prohibitReturn flag to deny a return to the opened editor through the browser history. 691 * Use this feature for inline editing or when opening the editor for new resources.<p> 692 * 693 * @param prohibitReturn if <code>true</code> returning to the opened editor through the browser history is denied 694 */ 695 private void addEditingHistoryItem(boolean prohibitReturn) { 696 697 if (prohibitReturn) { 698 History.newItem(EDITOR_FOR_NO_RETURN_HASH_KEY, false); 699 } else { 700 History.newItem( 701 EDITOR_HASH_KEY 702 + CmsContainerpageController.getServerId(getCurrentElementId()) 703 + (m_dependingElementId != null ? "," + m_dependingElementId + ";" : ";"), 704 false); 705 } 706 } 707 708 /** 709 * Returns the HTML context info for the given element.<p> 710 * 711 * @param element the edited element 712 * 713 * @return the JSON string 714 */ 715 private String getContextInfo(CmsContainerPageElementPanel element) { 716 717 CmsContainerPageContainer container; 718 if (m_handler.m_controller.isGroupcontainerEditing()) { 719 container = (CmsContainerPageContainer)((CmsContainerPageElementPanel)element.getParentTarget()).getParentTarget(); 720 } else { 721 container = (CmsContainerPageContainer)element.getParentTarget(); 722 } 723 JSONObject result = new JSONObject(); 724 putString(result, CmsCntPageData.JSONKEY_ELEMENT_ID, element.getId()); 725 CmsUUID detailId = m_handler.m_controller.getData().getDetailId(); 726 if (detailId != null) { 727 putString(result, CmsCntPageData.JSONKEY_DETAIL_ELEMENT_ID, "" + detailId); 728 } 729 putString(result, CmsCntPageData.JSONKEY_NAME, "" + container.getContainerId()); 730 putString(result, CmsCntPageData.JSONKEY_TYPE, "" + container.getContainerType()); 731 result.put(CmsCntPageData.JSONKEY_WIDTH, new JSONNumber(container.getConfiguredWidth())); 732 result.put(CmsCntPageData.JSONKEY_DETAILVIEW, JSONBoolean.getInstance(container.isDetailView())); 733 result.put( 734 CmsCntPageData.JSONKEY_ISDETAILVIEWCONTAINER, 735 JSONBoolean.getInstance(container.isDetailViewContainer())); 736 result.put(CmsCntPageData.JSONKEY_DETAILONLY, JSONBoolean.getInstance(container.isDetailOnly())); 737 result.put(CmsCntPageData.JSONKEY_MAXELEMENTS, new JSONNumber(1)); 738 JSONObject presets = new JSONObject(); 739 Map<String, String> presetsMap = container.getSettingPresets(); 740 for (Map.Entry<String, String> entry : presetsMap.entrySet()) { 741 presets.put(entry.getKey(), new JSONString(entry.getValue())); 742 } 743 result.put(CmsCntPageData.JSONKEY_PRESETS, presets); 744 return result.toString(); 745 } 746 747 /** 748 * Adds a String value to the JSON object.<p> 749 * 750 * @param obj the object to manipulate 751 * @param key the key 752 * @param val the value 753 */ 754 private void putString(JSONObject obj, String key, String val) { 755 756 obj.put(key, new JSONString(val)); 757 } 758 759}