org.opencms.ade.containerpage.client.CmsContainerpageUtil Maven / Gradle / Ivy
Show all versions of opencms-gwt Show documentation
/*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (c) Alkacon Software GmbH (http://www.alkacon.com)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* For further information about Alkacon Software, please see the
* company website: http://www.alkacon.com
*
* For further information about OpenCms, please see the
* project website: http://www.opencms.org
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.opencms.ade.containerpage.client;
import org.opencms.ade.containerpage.client.ui.A_CmsToolbarOptionButton;
import org.opencms.ade.containerpage.client.ui.CmsContainerPageContainer;
import org.opencms.ade.containerpage.client.ui.CmsContainerPageElementPanel;
import org.opencms.ade.containerpage.client.ui.CmsElementOptionBar;
import org.opencms.ade.containerpage.client.ui.CmsGroupContainerElementPanel;
import org.opencms.ade.containerpage.client.ui.CmsMenuListItem;
import org.opencms.ade.containerpage.client.ui.I_CmsDropContainer;
import org.opencms.ade.containerpage.client.ui.css.I_CmsLayoutBundle;
import org.opencms.ade.containerpage.shared.CmsContainerElement;
import org.opencms.ade.containerpage.shared.CmsContainerElementData;
import org.opencms.gwt.client.CmsCoreProvider;
import org.opencms.gwt.client.CmsEditableData;
import org.opencms.gwt.client.ui.CmsErrorDialog;
import org.opencms.gwt.client.ui.CmsPushButton;
import org.opencms.gwt.client.ui.contextmenu.CmsContextMenuButton;
import org.opencms.gwt.client.ui.contextmenu.CmsContextMenuHandler;
import org.opencms.gwt.client.util.CmsDebugLog;
import org.opencms.gwt.client.util.CmsDomUtil;
import org.opencms.gwt.shared.CmsTemplateContextInfo;
import org.opencms.util.CmsStringUtil;
import org.opencms.util.CmsUUID;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.Style;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window;
/**
* Utility class for the container-page editor.
*
* @since 8.0.0
*/
public class CmsContainerpageUtil {
/** The container page controller. */
private CmsContainerpageController m_controller;
/** List of buttons of the tool-bar. */
private A_CmsToolbarOptionButton[] m_optionButtons;
/**
* Constructor.
*
* @param controller the container page controller
* @param optionButtons the tool-bar option buttons
*/
public CmsContainerpageUtil(CmsContainerpageController controller, A_CmsToolbarOptionButton... optionButtons) {
m_controller = controller;
m_optionButtons = optionButtons;
}
/**
* Adds an option bar to the given drag element.
*
* @param element the element
*/
public void addOptionBar(CmsContainerPageElementPanel element) {
// the view permission is required for any actions regarding this element
if (element.hasViewPermission()) {
CmsElementOptionBar optionBar = CmsElementOptionBar.createOptionBarForElement(
element,
m_controller.getDndHandler(),
m_optionButtons);
element.setElementOptionBar(optionBar);
}
}
/**
* Transforms all contained elements into {@link CmsContainerPageElementPanel}.
*
* @param container the container
*/
public void consumeContainerElements(I_CmsDropContainer container) {
// the drag element widgets are created from the existing DOM elements,
Element child = container.getElement().getFirstChildElement();
while (child != null) {
boolean isContainerElement = CmsDomUtil.hasClass(
CmsContainerElement.CLASS_CONTAINER_ELEMENT_START_MARKER,
child);
boolean isGroupcontainerElement = CmsDomUtil.hasClass(
CmsContainerElement.CLASS_GROUP_CONTAINER_ELEMENT_MARKER,
child);
if (isContainerElement || isGroupcontainerElement) {
String serializedData = child.getAttribute("rel");
CmsContainerElement elementData = null;
try {
elementData = m_controller.getSerializedElement(serializedData);
} catch (Exception e) {
CmsErrorDialog.handleException(new Exception(
"Deserialization of element data failed. This may be caused by expired java-script resources, please clear your browser cache and try again.",
e));
}
if (isContainerElement) {
// searching for content element root
Element elementRoot = (Element)child.getNextSibling();
while ((elementRoot != null) && (elementRoot.getNodeType() != Node.ELEMENT_NODE)) {
Element temp = elementRoot;
elementRoot = (Element)elementRoot.getNextSibling();
temp.removeFromParent();
}
if (elementRoot == null) {
child.removeFromParent();
child = null;
continue;
}
if (CmsDomUtil.hasClass(CmsContainerElement.CLASS_CONTAINER_ELEMENT_START_MARKER, elementRoot)) {
// broken element, already at next start marker
if (elementData != null) {
alertParsingError(elementData.getSitePath());
}
child.removeFromParent();
child = elementRoot;
continue;
}
if (CmsDomUtil.hasClass(CmsContainerElement.CLASS_CONTAINER_ELEMENT_END_MARKER, elementRoot)) {
// broken element, no content element root
if (elementData != null) {
alertParsingError(elementData.getSitePath());
}
child.removeFromParent();
child = elementRoot.getNextSiblingElement();
elementRoot.removeFromParent();
continue;
} else {
// looking for the next marker that wraps the current element
Element endMarker = (Element)elementRoot.getNextSibling();
// only if the end marker node is not null and has neither the end-marker class or start-marker class
// remove the current node and check the next sibling
while (!((endMarker == null) || ((endMarker.getNodeType() == Node.ELEMENT_NODE) && (CmsDomUtil.hasClass(
CmsContainerElement.CLASS_CONTAINER_ELEMENT_END_MARKER,
endMarker) || CmsDomUtil.hasClass(
CmsContainerElement.CLASS_CONTAINER_ELEMENT_START_MARKER,
endMarker))))) {
Element temp = endMarker;
endMarker = (Element)endMarker.getNextSibling();
temp.removeFromParent();
}
if (endMarker == null) {
if (elementData != null) {
alertParsingError(elementData.getSitePath());
}
// broken element, end marker missing
elementRoot.removeFromParent();
child.removeFromParent();
child = null;
continue;
}
if (CmsDomUtil.hasClass(CmsContainerElement.CLASS_CONTAINER_ELEMENT_START_MARKER, endMarker)) {
if (elementData != null) {
alertParsingError(elementData.getSitePath());
}
// broken element, end marker missing
elementRoot.removeFromParent();
child.removeFromParent();
child = endMarker;
}
if (elementData == null) {
// deserialization failed, remove whole element
child.removeFromParent();
elementRoot.removeFromParent();
child = endMarker.getNextSiblingElement();
endMarker.removeFromParent();
continue;
}
CmsDomUtil.removeScriptTags(elementRoot);
CmsContainerPageElementPanel containerElement = createElement(
elementRoot,
container,
elementData);
if (elementData.isNew()) {
containerElement.setNewType(elementData.getResourceType());
}
container.adoptElement(containerElement);
child.removeFromParent();
child = endMarker.getNextSiblingElement();
endMarker.removeFromParent();
}
} else if (isGroupcontainerElement && (container instanceof CmsContainerPageContainer)) {
if (elementData == null) {
// deserialization failed, remove whole group container
Element sibling = child.getNextSiblingElement();
container.getElement().removeChild(child);
child = sibling;
continue;
}
CmsDomUtil.removeScriptTags(child);
CmsGroupContainerElementPanel groupContainer = createGroupcontainer(child, container, elementData);
groupContainer.setContainerId(container.getContainerId());
container.adoptElement(groupContainer);
consumeContainerElements(groupContainer);
if (groupContainer.getWidgetCount() == 0) {
groupContainer.addStyleName(I_CmsLayoutBundle.INSTANCE.containerpageCss().emptyGroupContainer());
}
// important: adding the option-bar only after the group-containers have been consumed
if (!m_controller.isDetailPage() || container.isDetailView() || container.isDetailOnly()) {
//only allow editing if either element of detail only container or not in detail view
addOptionBar(groupContainer);
}
child = child.getNextSiblingElement();
}
} else {
Element sibling = child.getNextSiblingElement();
container.getElement().removeChild(child);
child = sibling;
continue;
}
}
}
/**
* The method will create {@link CmsContainerPageContainer} object for all given containers
* by converting the associated DOM elements. The contained elements will be transformed into {@link CmsContainerPageElementPanel}.
*
* @param containers the container data
*
* @return the drag target containers
*/
public Map consumeContainers(Map containers) {
Map result = new HashMap();
Iterator it = containers.values().iterator();
while (it.hasNext()) {
CmsContainerJso container = it.next();
try {
CmsContainerPageContainer dragContainer = new CmsContainerPageContainer(container);
consumeContainerElements(dragContainer);
result.put(container.getName(), dragContainer);
} catch (Exception e) {
CmsErrorDialog.handleException(new Exception("Error parsing container "
+ container.getName()
+ ". Please check if your HTML is well formed.", e));
}
}
return result;
}
/**
* Creates an drag container element.
*
* @param containerElement the container element data
* @param container the container parent
*
* @return the draggable element
*
* @throws Exception if something goes wrong
*/
public CmsContainerPageElementPanel createElement(
CmsContainerElementData containerElement,
I_CmsDropContainer container) throws Exception {
if (containerElement.isGroupContainer() || containerElement.isInheritContainer()) {
List subElements = new ArrayList();
for (String subId : containerElement.getSubItems()) {
CmsContainerElementData element = m_controller.getCachedElement(subId);
if (element != null) {
subElements.add(element);
} else {
CmsDebugLog.getInstance().printLine("Cached element not found");
}
}
return createGroupcontainerElement(containerElement, subElements, container);
}
Element element = CmsDomUtil.createElement(containerElement.getContents().get(container.getContainerId()));
// ensure any embedded flash players are set opaque so UI elements may be placed above them
CmsDomUtil.fixFlashZindex(element);
CmsContainerPageElementPanel result = createElement(element, container, containerElement);
if (!CmsContainerpageController.get().shouldShowInContext(containerElement)) {
result.getElement().getStyle().setDisplay(Style.Display.NONE);
result.addStyleName(CmsTemplateContextInfo.DUMMY_ELEMENT_MARKER);
}
return result;
}
/**
* Creates a drag container element for group-container elements.
*
* @param containerElement the container element data
* @param subElements the sub-elements
* @param container the drag parent
*
* @return the draggable element
*
* @throws Exception if something goes wrong
*/
public CmsContainerPageElementPanel createGroupcontainerElement(
CmsContainerElementData containerElement,
List subElements,
I_CmsDropContainer container) throws Exception {
Element element = DOM.createDiv();
element.addClassName(CmsContainerElement.CLASS_GROUP_CONTAINER_ELEMENT_MARKER);
CmsGroupContainerElementPanel groupContainer = createGroupcontainer(element, container, containerElement);
groupContainer.setContainerId(container.getContainerId());
//adding sub-elements
Iterator it = subElements.iterator();
while (it.hasNext()) {
CmsContainerElementData subElement = it.next();
if (subElement.getContents().containsKey(container.getContainerId())) {
CmsContainerPageElementPanel subDragElement = createElement(subElement, groupContainer);
groupContainer.add(subDragElement);
}
}
if (subElements.size() == 0) {
groupContainer.addStyleName(I_CmsLayoutBundle.INSTANCE.containerpageCss().emptyGroupContainer());
}
addOptionBar(groupContainer);
return groupContainer;
}
/**
* Creates a list item.
*
* @param containerElement the element data
*
* @return the list item widget
*/
public CmsMenuListItem createListItem(final CmsContainerElementData containerElement) {
CmsMenuListItem listItem = new CmsMenuListItem(containerElement);
if (!containerElement.isGroupContainer()
&& !containerElement.isInheritContainer()
&& CmsStringUtil.isEmptyOrWhitespaceOnly(containerElement.getNoEditReason())) {
listItem.enableEdit(new ClickHandler() {
public void onClick(ClickEvent event) {
CmsEditableData editableData = new CmsEditableData();
editableData.setElementLanguage(CmsCoreProvider.get().getLocale());
editableData.setStructureId(new CmsUUID(
CmsContainerpageController.getServerId(containerElement.getClientId())));
editableData.setSitePath(containerElement.getSitePath());
getController().getContentEditorHandler().openDialog(editableData, false, null);
((CmsPushButton)event.getSource()).clearHoverState();
}
});
} else {
if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(containerElement.getNoEditReason())) {
listItem.disableEdit(containerElement.getNoEditReason(), true);
} else {
listItem.disableEdit(Messages.get().key(Messages.GUI_CLIPBOARD_ITEM_CAN_NOT_BE_EDITED_0), false);
}
}
listItem.initMoveHandle(m_controller.getDndHandler(), true);
String clientId = containerElement.getClientId();
String serverId = CmsContainerpageController.getServerId(clientId);
if (CmsUUID.isValidUUID(serverId)) {
CmsContextMenuButton button = new CmsContextMenuButton(new CmsUUID(serverId), new CmsContextMenuHandler() {
@Override
public void refreshResource(CmsUUID structureId) {
Window.Location.reload();
}
});
listItem.getListItemWidget().addButton(button);
}
return listItem;
}
/**
* Returns the container page controller.
*
* @return the container page controller
*/
protected CmsContainerpageController getController() {
return m_controller;
}
/**
* Displays the element parsing error dialog.
*
* @param sitePath the element site path
*/
private void alertParsingError(String sitePath) {
new CmsErrorDialog("Error parsing element "
+ sitePath
+ ". Please check if the HTML generated by the element formatter is well formed.", null).center();
}
/**
* Creates an drag container element.
*
* @param element the DOM element
* @param dragParent the drag parent
* @param elementData the element data
*
* @return the draggable element
*/
private CmsContainerPageElementPanel createElement(
Element element,
I_CmsDropContainer dragParent,
CmsContainerElement elementData) {
CmsContainerPageElementPanel dragElement = new CmsContainerPageElementPanel(
element,
dragParent,
elementData.getClientId(),
elementData.getSitePath(),
elementData.getNoEditReason(),
elementData.hasSettings(dragParent.getContainerId()),
elementData.hasViewPermission(),
elementData.hasWritePermission(),
elementData.isReleasedAndNotExpired(),
elementData.isNewEditorDisabled());
boolean isSubElement = dragParent instanceof CmsGroupContainerElementPanel;
boolean isContainerEditable = isSubElement
|| !m_controller.isDetailPage()
|| dragParent.isDetailView()
|| dragParent.isDetailOnly();
if (isContainerEditable) {
addOptionBar(dragElement);
}
// only enable inline editing for the new content editor
// also ignore group container sub-elements unless group editing
if (!m_controller.getData().isUseClassicEditor()
&& m_controller.hasActiveSelection()
&& isContainerEditable
&& (!isSubElement || m_controller.isGroupcontainerEditing())) {
dragElement.initInlineEditor(m_controller);
}
return dragElement;
}
/**
* Creates a drag container element. This will not add an option-bar!
*
* @param element the DOM element
* @param dragParent the drag parent
* @param elementData the element data
*
* @return the draggable element
*/
private CmsGroupContainerElementPanel createGroupcontainer(
Element element,
I_CmsDropContainer dragParent,
CmsContainerElement elementData) {
CmsGroupContainerElementPanel groupContainer = new CmsGroupContainerElementPanel(
element,
dragParent,
elementData.getClientId(),
elementData.getSitePath(),
elementData.getResourceType(),
elementData.getNoEditReason(),
elementData.hasSettings(dragParent.getContainerId()),
elementData.hasViewPermission(),
elementData.hasWritePermission(),
elementData.isReleasedAndNotExpired());
return groupContainer;
}
}