/*
* 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.CmsContainerElementData;
import org.opencms.gwt.client.util.CmsDomUtil;
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.Node;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
/**
* Utility class for the container-page editor.<p>
*
* @since 8.0.0
*/
public class CmsContainerpageUtil {
/** HTML class used to identify container elements. Has to be identical with {@link org.opencms.jsp.CmsJspTagContainer#CLASS_CONTAINER_ELEMENT_END_MARKER}. */
public static final String CLASS_CONTAINER_ELEMENT_END_MARKER = "cms_ade_element_end";
/** HTML class used to identify container elements. Has to be identical with {@link org.opencms.jsp.CmsJspTagContainer#CLASS_CONTAINER_ELEMENT_START_MARKER}. */
public static final String CLASS_CONTAINER_ELEMENT_START_MARKER = "cms_ade_element_start";
/** HTML class used to identify group container elements. Has to be identical with {@link org.opencms.jsp.CmsJspTagContainer#CLASS_GROUP_CONTAINER_ELEMENT_MARKER}. */
public static final String CLASS_GROUP_CONTAINER_ELEMENT_MARKER = "cms_ade_groupcontainer";
/** The container page controller. */
private CmsContainerpageController m_controller;
/** List of buttons of the tool-bar. */
private A_CmsToolbarOptionButton[] m_optionButtons;
/**
* Constructor.<p>
*
* @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.<p>
*
* @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}.<p>
*
* @param container the container
*/
public void consumeContainerElements(I_CmsDropContainer container) {
// the drag element widgets are created from the existing DOM elements,
Element child = (Element)container.getElement().getFirstChildElement();
while (child != null) {
boolean isContainerElement = CmsDomUtil.hasClass(CLASS_CONTAINER_ELEMENT_START_MARKER, child);
boolean isGroupcontainerElement = CmsDomUtil.hasClass(CLASS_GROUP_CONTAINER_ELEMENT_MARKER, child);
if (isContainerElement || isGroupcontainerElement) {
String clientId = child.getAttribute("clientId");
String sitePath = child.getAttribute("alt");
String noEditReason = child.getAttribute("rel");
String newType = child.getAttribute("newType");
boolean hasProps = Boolean.parseBoolean(child.getAttribute("hasprops"));
boolean hasViewPermission = Boolean.parseBoolean(child.getAttribute("hasviewpermission"));
boolean releasedAndNotExpired = Boolean.parseBoolean(child.getAttribute("releasedandnotexpired"));
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(CLASS_CONTAINER_ELEMENT_START_MARKER, elementRoot)) {
// broken element, already at next start marker
child.removeFromParent();
child = elementRoot;
continue;
}
if (CmsDomUtil.hasClass(CLASS_CONTAINER_ELEMENT_END_MARKER, elementRoot)) {
// broken element, no content element root
child.removeFromParent();
child = (Element)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(
CLASS_CONTAINER_ELEMENT_END_MARKER,
endMarker) || CmsDomUtil.hasClass(CLASS_CONTAINER_ELEMENT_START_MARKER, endMarker))))) {
Element temp = endMarker;
endMarker = (Element)endMarker.getNextSibling();
temp.removeFromParent();
}
if (endMarker == null) {
// broken element, end marker missing
elementRoot.removeFromParent();
child.removeFromParent();
child = null;
continue;
}
if (CmsDomUtil.hasClass(CLASS_CONTAINER_ELEMENT_START_MARKER, endMarker)) {
// broken element, end marker missing
elementRoot.removeFromParent();
child.removeFromParent();
child = endMarker;
}
CmsDomUtil.removeScriptTags(elementRoot);
CmsContainerPageElementPanel containerElement = createElement(
elementRoot,
container,
clientId,
sitePath,
noEditReason,
hasProps,
hasViewPermission,
releasedAndNotExpired);
if ((newType != null) && (newType.length() > 0)) {
containerElement.setNewType(newType);
}
container.adoptElement(containerElement);
child.removeFromParent();
child = (Element)endMarker.getNextSiblingElement(); // (Element)container.getElement().getFirstChildElement();
endMarker.removeFromParent();
}
} else if (isGroupcontainerElement && (container instanceof CmsContainerPageContainer)) {
CmsDomUtil.removeScriptTags(child);
CmsGroupContainerElementPanel groupContainer = createGroupcontainer(
child,
container,
clientId,
sitePath,
noEditReason,
hasProps,
hasViewPermission,
releasedAndNotExpired);
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
addOptionBar(groupContainer);
child = (Element)child.getNextSiblingElement();
}
} else {
Element sibling = (Element)child.getNextSiblingElement();
DOM.removeChild((Element)container.getElement(), 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}.<p>
*
* @param containers the container data
*
* @return the drag target containers
*/
public Map<String, CmsContainerPageContainer> consumeContainers(Map<String, CmsContainerJso> containers) {
Map<String, CmsContainerPageContainer> result = new HashMap<String, CmsContainerPageContainer>();
Iterator<CmsContainerJso> it = containers.values().iterator();
while (it.hasNext()) {
CmsContainerJso container = it.next();
CmsContainerPageContainer dragContainer = new CmsContainerPageContainer(container);
consumeContainerElements(dragContainer);
result.put(container.getName(), dragContainer);
}
return result;
}
/**
* Creates an drag container element.<p>
*
* @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()) {
List<CmsContainerElementData> subElements = new ArrayList<CmsContainerElementData>();
for (String subId : containerElement.getSubItems()) {
CmsContainerElementData element = m_controller.getCachedElement(subId);
if (element != null) {
subElements.add(element);
}
}
return createGroupcontainerElement(containerElement, subElements, container);
}
boolean hasProps = !containerElement.getSettingConfig().isEmpty();
com.google.gwt.user.client.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);
return createElement(
element,
container,
containerElement.getClientId(),
containerElement.getSitePath(),
containerElement.getNoEditReason(),
hasProps,
containerElement.hasViewPermission(),
containerElement.isReleasedAndNotExpired());
}
/**
* Creates a drag container element for group-container elements.<p>
*
* @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<CmsContainerElementData> subElements,
I_CmsDropContainer container) throws Exception {
com.google.gwt.user.client.Element element = DOM.createDiv();
element.addClassName(CmsContainerpageUtil.CLASS_GROUP_CONTAINER_ELEMENT_MARKER);
boolean hasProps = !containerElement.getSettingConfig().isEmpty();
CmsGroupContainerElementPanel groupContainer = createGroupcontainer(
element,
container,
containerElement.getClientId(),
containerElement.getSitePath(),
containerElement.getNoEditReason(),
hasProps,
containerElement.hasViewPermission(),
containerElement.isReleasedAndNotExpired());
groupContainer.setContainerId(container.getContainerId());
//adding sub-elements
Iterator<CmsContainerElementData> 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.<p>
*
* @param containerElement the element data
*
* @return the list item widget
*/
public CmsMenuListItem createListItem(CmsContainerElementData containerElement) {
CmsMenuListItem listItem = new CmsMenuListItem(containerElement);
listItem.initMoveHandle(m_controller.getDndHandler());
return listItem;
}
/**
* Creates an drag container element.<p>
*
* @param element the DOM element
* @param dragParent the drag parent
* @param clientId the client id
* @param sitePath the element site-path
* @param noEditReason the no edit reason
* @param hasProps if true, the container element has properties which can be edited
* @param hasViewPermission indicates if the current user has view permissions on the element resource
*
* @return the draggable element
*/
private CmsContainerPageElementPanel createElement(
com.google.gwt.user.client.Element element,
I_CmsDropContainer dragParent,
String clientId,
String sitePath,
String noEditReason,
boolean hasProps,
boolean hasViewPermission,
boolean releasedAndNotExpired) {
CmsContainerPageElementPanel dragElement = new CmsContainerPageElementPanel(
element,
dragParent,
clientId,
sitePath,
noEditReason,
hasProps,
hasViewPermission,
releasedAndNotExpired);
// enableDragHandler(dragElement);
addOptionBar(dragElement);
return dragElement;
}
/**
* Creates an drag container element. This will not add an option-bar!<p>
*
* @param element the DOM element
* @param dragParent the drag parent
* @param clientId the client id
* @param sitePath the element site-path
* @param noEditReason the no edit reason
* @param hasProps true if the group-container has properties to edit
* @param hasViewPermission indicates if the current user has view permissions on the element resource
*
* @return the draggable element
*/
private CmsGroupContainerElementPanel createGroupcontainer(
com.google.gwt.user.client.Element element,
I_CmsDropContainer dragParent,
String clientId,
String sitePath,
String noEditReason,
boolean hasProps,
boolean hasViewPermission,
boolean releasedAndNotExpired) {
CmsGroupContainerElementPanel groupContainer = new CmsGroupContainerElementPanel(
element,
dragParent,
clientId,
sitePath,
noEditReason,
hasProps,
hasViewPermission,
releasedAndNotExpired);
return groupContainer;
}
}