Index: ../../git/magnolia_main/magnolia-templating-editor/src/main/java/info/magnolia/templating/editor/client/dom/processor/ElementProcessor.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP <+>/**\n * This file Copyright (c) 2011 Magnolia International\n * Ltd. (http://www.magnolia-cms.com). All rights reserved.\n *\n *\n * This file is dual-licensed under both the Magnolia\n * Network Agreement and the GNU General Public License.\n * You may elect to use one or the other of these licenses.\n *\n * This file is distributed in the hope that it will be\n * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the\n * implied warranty of MERCHANTABILITY or FITNESS FOR A\n * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.\n * Redistribution, except as permitted by whichever of the GPL\n * or MNA you select, is prohibited.\n *\n * 1. For the GPL license (GPL), you can redistribute and/or\n * modify this file under the terms of the GNU General\n * Public License, Version 3, as published by the Free Software\n * Foundation. You should have received a copy of the GNU\n * General Public License, Version 3 along with this program;\n * if not, write to the Free Software Foundation, Inc., 51\n * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n *\n * 2. For the Magnolia Network Agreement (MNA), this file\n * and the accompanying materials are made available under the\n * terms of the MNA which accompanies this distribution, and\n * is available at http://www.magnolia-cms.com/mna.html\n *\n * Any modifications to this file must keep this entire header\n * intact.\n *\n */\npackage info.magnolia.templating.editor.client.dom.processor;\n\nimport com.google.gwt.dom.client.Element;\nimport com.google.gwt.dom.client.Node;\n\nimport info.magnolia.rendering.template.AreaDefinition;\nimport info.magnolia.templating.editor.client.PageEditor;\nimport info.magnolia.templating.editor.client.dom.MgnlElement;\n\n/**\n * Processor for DOM elements.\n */\npublic class ElementProcessor {\n\n public static void process(Node node, MgnlElement mgnlElement) {\n\n Element element = node.cast();\n if (element.hasTagName(\"A\")) {\n disableLink(element);\n removeHover(element);\n }\n PageEditor.model.addElement(mgnlElement, element);\n\n if (element.hasAttribute(AreaDefinition.CMS_ADD)) {\n mgnlElement.setComponentElement(element);\n }\n\n else if (element.hasAttribute(AreaDefinition.CMS_PLACEHOLDER)) {\n mgnlElement.setAreaElement(element);\n }\n\n else if (element.hasAttribute(AreaDefinition.CMS_EDIT)) {\n mgnlElement.setEditElement(element);\n }\n\n else {\n if (mgnlElement.getFirstElement() == null) {\n mgnlElement.setFirstElement(element);\n }\n\n if (mgnlElement.getLastElement() == null || !mgnlElement.getLastElement().isOrHasChild(element)) {\n mgnlElement.setLastElement(element);\n }\n }\n\n }\n\n public static void removeHover (Element element) {\n element.addClassName(\"disabled\");\n }\n\n public native static void disableLink(Element element) /*-{\n if (element.onclick == null) {\n element.onclick = function() {\n return false;\n };\n }\n }-*/;\n}\n =================================================================== --- ../../git/magnolia_main/magnolia-templating-editor/src/main/java/info/magnolia/templating/editor/client/dom/processor/ElementProcessor.java (revision 026ad62bb10416ca8a59c36db5db8d8376d8c563) +++ ../../git/magnolia_main/magnolia-templating-editor/src/main/java/info/magnolia/templating/editor/client/dom/processor/ElementProcessor.java (revision ) @@ -45,9 +45,17 @@ */ public class ElementProcessor { - public static void process(Node node, MgnlElement mgnlElement) { + private static String NAVIGATION_ROLE ="navigation"; + public static boolean process(Node node, MgnlElement mgnlElement) { + Element element = node.cast(); + + // If element has role navigation skip node and children. + if (element.getAttribute("role").equals(NAVIGATION_ROLE)) { + return false; + } + if (element.hasTagName("A")) { disableLink(element); removeHover(element); @@ -75,6 +83,7 @@ mgnlElement.setLastElement(element); } } + return true; } Index: ../../git/magnolia_main/magnolia-templating-editor/src/main/java/info/magnolia/templating/editor/client/PageEditor.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP <+>/**\n * This file Copyright (c) 2011-2012 Magnolia International\n * Ltd. (http://www.magnolia-cms.com). All rights reserved.\n *\n *\n * This file is dual-licensed under both the Magnolia\n * Network Agreement and the GNU General Public License.\n * You may elect to use one or the other of these licenses.\n *\n * This file is distributed in the hope that it will be\n * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the\n * implied warranty of MERCHANTABILITY or FITNESS FOR A\n * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.\n * Redistribution, except as permitted by whichever of the GPL\n * or MNA you select, is prohibited.\n *\n * 1. For the GPL license (GPL), you can redistribute and/or\n * modify this file under the terms of the GNU General\n * Public License, Version 3, as published by the Free Software\n * Foundation. You should have received a copy of the GNU\n * General Public License, Version 3 along with this program;\n * if not, write to the Free Software Foundation, Inc., 51\n * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n *\n * 2. For the Magnolia Network Agreement (MNA), this file\n * and the accompanying materials are made available under the\n * terms of the MNA which accompanies this distribution, and\n * is available at http://www.magnolia-cms.com/mna.html\n *\n * Any modifications to this file must keep this entire header\n * intact.\n *\n */\npackage info.magnolia.templating.editor.client;\n\n\nimport info.magnolia.templating.editor.client.dom.Comment;\nimport info.magnolia.templating.editor.client.dom.MgnlElement;\nimport info.magnolia.templating.editor.client.dom.processor.CommentProcessor;\nimport info.magnolia.templating.editor.client.dom.processor.ElementProcessor;\nimport info.magnolia.templating.editor.client.dom.processor.MgnlElementProcessor;\nimport info.magnolia.templating.editor.client.dom.processor.MgnlElementProcessorFactory;\nimport info.magnolia.templating.editor.client.jsni.JavascriptUtils;\nimport info.magnolia.templating.editor.client.model.ModelStorage;\nimport info.magnolia.templating.editor.client.widget.PreviewChannel;\nimport info.magnolia.templating.editor.client.widget.PreviewChannel.Orientation;\nimport info.magnolia.templating.editor.client.widget.dnd.LegacyDragAndDrop;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\nimport com.google.gwt.core.client.EntryPoint;\nimport com.google.gwt.core.client.GWT;\nimport com.google.gwt.dom.client.AnchorElement;\nimport com.google.gwt.dom.client.Document;\nimport com.google.gwt.dom.client.Element;\nimport com.google.gwt.dom.client.FormElement;\nimport com.google.gwt.dom.client.Node;\nimport com.google.gwt.dom.client.NodeList;\nimport com.google.gwt.dom.client.Style.Unit;\nimport com.google.gwt.event.dom.client.KeyCodes;\nimport com.google.gwt.event.dom.client.KeyDownEvent;\nimport com.google.gwt.event.dom.client.KeyDownHandler;\nimport com.google.gwt.event.dom.client.MouseMoveEvent;\nimport com.google.gwt.event.dom.client.MouseMoveHandler;\nimport com.google.gwt.event.dom.client.MouseUpEvent;\nimport com.google.gwt.event.dom.client.MouseUpHandler;\nimport com.google.gwt.http.client.Request;\nimport com.google.gwt.http.client.RequestBuilder;\nimport com.google.gwt.http.client.RequestCallback;\nimport com.google.gwt.http.client.RequestException;\nimport com.google.gwt.http.client.Response;\nimport com.google.gwt.http.client.URL;\nimport com.google.gwt.http.client.UrlBuilder;\nimport com.google.gwt.user.client.Window;\nimport com.google.gwt.user.client.Window.ScrollEvent;\nimport com.google.gwt.user.client.Window.ScrollHandler;\nimport com.google.gwt.user.client.ui.HTML;\nimport com.google.gwt.user.client.ui.RootPanel;\n\n/**\n * Client side implementation of the page editor. Outputs ui widgets inside document element (typically the {@code } element).\n * Since the DOM manipulations performed by the PageEditor (i.e. dynamic creation of edit bars) happen when all other javascripts have already been loaded\n * (see GWT bootstrap FAQ),\n * if you have some custom javascript which needs to operate on elements added by the PageEditor, you will have to use the utility javascript method mgnl.PageEditor.onReady(callback).\n * This will ensure that your handler functions are executed when the PageEditor is actually done.\n *

For example:\n *

\n * mgnl.PageEditor.onReady( function() {\n *    alert('hello, page editor is ready.')\n * });\n * 
\n * Modules can register multiple callbacks this way. The order in which callbacks are fired is the same in which they were registered.\n *

\n * @version $Id$\n *\n * TODO clean up/refactoring.\n */\npublic class PageEditor extends HTML implements EntryPoint {\n\n private static final String MGNL_CHANNEL_PARAMETER = \"mgnlChannel\";\n private static final String MGNL_PREVIEW_PARAMETER = \"mgnlPreview\";\n private static final String MGNL_INTERCEPT_PARAMETER = \"mgnlIntercept\";\n private static final String MGNL_VERSION_PARAMETER = \"mgnlVersion\";\n\n private static String locale;\n public final static ModelStorage model = ModelStorage.getInstance();\n private LinkedList mgnlElements = new LinkedList();\n\n // In case we're in preview mode, we will stop processing the document, after the pagebar has been injected.\n public static boolean process = true;\n private static boolean isPreview = false;\n\n\n @Override\n public void onModuleLoad() {\n\n String mgnlVersion = Window.Location.getParameter(MGNL_VERSION_PARAMETER);\n if(mgnlVersion != null) {\n return;\n }\n\n String mgnlChannel = Window.Location.getParameter(MGNL_CHANNEL_PARAMETER);\n boolean isMobile = \"smartphone\".equals(mgnlChannel) || \"tablet\".equals(mgnlChannel);\n\n if(isMobile) {\n GWT.log(\"Found \" + mgnlChannel + \" in request, post processing links...\");\n postProcessLinksOnMobilePreview(Document.get().getDocumentElement(), mgnlChannel);\n return;\n }\n\n JavascriptUtils.setWindowLocation(Window.Location.getPath());\n // save x/y positon\n Window.addWindowScrollHandler(new ScrollHandler() {\n\n @Override\n public void onWindowScroll(ScrollEvent event) {\n String value = event.getScrollLeft() + \":\" + event.getScrollTop();\n JavascriptUtils.setEditorPositionCookie(value);\n }\n });\n\n JavascriptUtils.getCookiePosition();\n\n locale = JavascriptUtils.detectCurrentLocale();\n\n long startTime = System.currentTimeMillis();\n processDocument(Document.get().getDocumentElement(), null);\n processMgnlElements();\n\n GWT.log(\"Time spent to process cms comments: \" + (System.currentTimeMillis() - startTime) + \"ms\");\n\n JavascriptUtils.getCookieContentId();\n\n RootPanel.get().addDomHandler(new MouseUpHandler() {\n @Override\n public void onMouseUp(MouseUpEvent event) {\n\n model.getFocusModel().onMouseUp((Element)event.getNativeEvent().getEventTarget().cast());\n event.stopPropagation();\n }\n }, MouseUpEvent.getType());\n\n RootPanel.get().addDomHandler(new KeyDownHandler() {\n @Override\n public void onKeyDown(KeyDownEvent event) {\n if (event.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) {\n //if we're moving an element abort move\n if(LegacyDragAndDrop.isMoving()) {\n LegacyDragAndDrop.moveComponentReset();\n } else {\n PageEditor.enablePreview(!isPreview);\n }\n event.preventDefault();\n }\n }\n }, KeyDownEvent.getType());\n\n\n\n RootPanel.get().addDomHandler(new MouseMoveHandler() {\n\n @Override\n public void onMouseMove(MouseMoveEvent event) {\n\n Element moveElement = Document.get().getElementById(\"mgnlEditorMoveDiv\");\n\n if (moveElement != null) {\n int x = event.getClientX() + Window.getScrollLeft();\n int y = event.getClientY() + 15 + Window.getScrollTop();\n moveElement.getStyle().setTop(y, Unit.PX);\n moveElement.getStyle().setLeft(x, Unit.PX);\n }\n }\n }, MouseMoveEvent.getType());\n\n JavascriptUtils.resetEditorCookies();\n\n GWT.log(\"Running onPageEditorReady callbacks...\");\n onPageEditorReady();\n }\n\n public static void openDialog(String dialog, String workspace, String path) {\n JavascriptUtils.mgnlOpenDialog(path, \"\", \"\", dialog, workspace, \"\", \"\", \"\", locale);\n }\n\n public static void deleteComponent(String path) {\n JavascriptUtils.mgnlDeleteNode(path);\n }\n\n public static void addComponent(String workspace, String path, String nodeName, String availableComponents) {\n // Not used anymore. The node is passed together with the path\n String collectionName = null;\n\n if (nodeName == null) {\n nodeName = \"mgnlNew\";\n }\n if (availableComponents == null) {\n availableComponents = \"\";\n }\n if (availableComponents.contains(\",\")) {\n JavascriptUtils.mgnlOpenDialog(path, collectionName, nodeName, availableComponents, workspace, \".magnolia/dialogs/selectParagraph.html\", \"\", \"\", locale);\n } else if (!availableComponents.isEmpty()) {\n JavascriptUtils.mgnlOpenDialog(path, collectionName, nodeName, availableComponents, workspace, \".magnolia/dialogs/editParagraph.html\", \"\", \"\", locale);\n }\n }\n\n public static void showTree(String workspace, String path) {\n JavascriptUtils.showTree(workspace, path);\n\n }\n\n public static void createComponent(String workspace, String path, String itemType) {\n GWT.log(\"Creating [\" + itemType + \"] in workspace [\" + workspace + \"] at path [\" + path + \"]\");\n\n final StringBuilder url = new StringBuilder();\n url.append(JavascriptUtils.getContextPath() + \".magnolia/pageeditor/PageEditorServlet\");\n url.append(\"?action=create\");\n url.append(\"&workspace=\" + workspace);\n url.append(\"&path=\" + path);\n url.append(\"&itemType=\" + itemType);\n\n RequestBuilder req = new RequestBuilder(RequestBuilder.GET, URL.encode(url.toString()));\n req.setCallback(new RequestCallback() {\n\n @Override\n public void onResponseReceived(Request request, Response response) {\n int status = response.getStatusCode();\n String responseText = \"\";\n boolean reload = false;\n\n switch (status) {\n case Response.SC_OK:\n reload = true;\n break;\n case Response.SC_UNAUTHORIZED:\n responseText = \"Is your session expired? Please, try to login again.\";\n break;\n default:\n responseText = \"See logs for more details.\";\n }\n\n if (reload) {\n UrlBuilder urlBuilder = Window.Location.createUrlBuilder();\n\n urlBuilder.removeParameter(\"mgnlIntercept\");\n urlBuilder.removeParameter(\"mgnlPath\");\n\n Window.Location.replace(urlBuilder.buildString());\n } else {\n Window.alert(\"An error occurred on the server: response status code is \" + status + \"\\n\" + responseText);\n }\n }\n\n @Override\n public void onError(Request request, Throwable exception) {\n Window.alert(exception.getMessage());\n }\n });\n try {\n req.send();\n } catch (RequestException e) {\n Window.alert(\"An error occurred while trying to send a request to the server: \" + e.getMessage());\n }\n\n }\n\n public static void createChannelPreview(final String channelName, final Orientation orientation) {\n setPreview(true);\n GWT.log(\"Creating preview for channel type [\" + channelName + \"] \");\n\n final UrlBuilder urlBuilder = Window.Location.createUrlBuilder();\n\n //always cleanup the url from preview params\n urlBuilder.removeParameter(MGNL_PREVIEW_PARAMETER);\n urlBuilder.removeParameter(MGNL_INTERCEPT_PARAMETER);\n urlBuilder.removeParameter(MGNL_CHANNEL_PARAMETER);\n\n urlBuilder.setParameter(MGNL_PREVIEW_PARAMETER, String.valueOf(isPreview()));\n urlBuilder.setParameter(MGNL_CHANNEL_PARAMETER, channelName);\n final PreviewChannel previewChannelWidget = new PreviewChannel(urlBuilder.buildString(), orientation, channelName);\n //this causes the pop up to show\n previewChannelWidget.center();\n }\n\n private void processDocument(Node node, MgnlElement mgnlElement) {\n if(process) {\n for (int i = 0; i < node.getChildCount(); i++) {\n Node childNode = node.getChild(i);\n if (childNode.getNodeType() == Comment.COMMENT_NODE) {\n\n try {\n mgnlElement = CommentProcessor.process(childNode, mgnlElement);\n }\n catch (IllegalArgumentException e) {\n GWT.log(\"Not CMSComment element, skipping: \" + e.toString());\n\n }\n catch (Exception e) {\n GWT.log(\"Caught undefined exception: \" + e.toString());\n }\n }\n else if (childNode.getNodeType() == Node.ELEMENT_NODE && mgnlElement != null) {\n ElementProcessor.process(childNode, mgnlElement);\n }\n\n processDocument(childNode, mgnlElement);\n }\n }\n }\n\n private void processMgnlElements() {\n List rootElements = new LinkedList(model.getRootElements());\n for (MgnlElement root : rootElements) {\n LinkedList elements = new LinkedList();\n elements.add(root);\n elements.addAll(root.getDescendants());\n\n for (MgnlElement mgnlElement : elements) {\n try {\n MgnlElementProcessor processor = MgnlElementProcessorFactory.getProcessor(mgnlElement);\n processor.process();\n }\n catch (IllegalArgumentException e) {\n GWT.log(\"MgnlFactory could not instantiate class. The element is neither an area nor component.\");\n }\n }\n }\n\n }\n\n //FIXME submitting forms still renders website channel and edit bars\n private void postProcessLinksOnMobilePreview(Element root, String channel) {\n NodeList anchors = root.getElementsByTagName(\"a\");\n\n final String mobilePreviewParams = MGNL_CHANNEL_PARAMETER+\"=\"+channel+\"&\"+ MGNL_PREVIEW_PARAMETER+\"=true\";\n\n for (int i = 0; i < anchors.getLength(); i++) {\n AnchorElement anchor = AnchorElement.as(anchors.getItem(i));\n\n GWT.log(\"Starting to process link \" + anchor.getHref());\n\n if(JavascriptUtils.isEmpty(anchor.getHref())) {\n continue;\n }\n String manipulatedHref = anchor.getHref().replaceFirst(Window.Location.getProtocol() + \"//\" + Window.Location.getHost(), \"\");\n String queryString = Window.Location.getQueryString() != null ? Window.Location.getQueryString() : \"\";\n\n GWT.log(\"query string is \" + queryString);\n\n String queryStringRegex = queryString.replaceFirst(\"\\\\?\", \"\\\\\\\\?\");\n manipulatedHref = manipulatedHref.replaceFirst(queryStringRegex, \"\");\n int indexOfHash = manipulatedHref.indexOf(\"#\");\n\n if(indexOfHash != -1) {\n manipulatedHref = manipulatedHref.substring(indexOfHash);\n } else {\n if(!queryString.contains(mobilePreviewParams)) {\n if(queryString.startsWith(\"?\")) {\n queryString += \"&\" + mobilePreviewParams;\n } else {\n queryString = \"?\" + mobilePreviewParams;\n }\n }\n manipulatedHref += queryString;\n }\n GWT.log(\"Resulting link is \" + manipulatedHref);\n anchor.setHref(manipulatedHref);\n }\n NodeList forms = root.getElementsByTagName(\"form\");\n\n for (int i = 0; i < forms.getLength(); i++) {\n FormElement form = FormElement.as(forms.getItem(i));\n form.setAction(form.getAction().concat(\"?\"+ mobilePreviewParams));\n }\n }\n\n\n private native void onPageEditorReady() /*-{\n var callbacks = $wnd.mgnl.PageEditor.onPageEditorReadyCallbacks\n if(typeof callbacks != 'undefined') {\n for(var i=0; i < callbacks.length; i++) {\n callbacks[i].apply()\n }\n }\n }-*/;\n\n /**\n * Enables/disables default (desktop) preview.\n */\n public static void enablePreview(boolean preview) {\n setPreview(preview);\n final UrlBuilder urlBuilder = Window.Location.createUrlBuilder();\n GWT.log(\"Current url is [\" + urlBuilder.buildString() + \"], setting preview to \" + isPreview());\n\n //always cleanup the url\n urlBuilder.removeParameter(MGNL_PREVIEW_PARAMETER);\n urlBuilder.removeParameter(MGNL_INTERCEPT_PARAMETER);\n urlBuilder.removeParameter(MGNL_CHANNEL_PARAMETER);\n\n urlBuilder.setParameter(MGNL_INTERCEPT_PARAMETER, \"PREVIEW\");\n urlBuilder.setParameter(MGNL_PREVIEW_PARAMETER, String.valueOf(isPreview()));\n\n if(isPreview()) {\n urlBuilder.setParameter(MGNL_CHANNEL_PARAMETER, \"desktop\");\n } else {\n urlBuilder.setParameter(MGNL_CHANNEL_PARAMETER, \"all\");\n }\n\n final String newUrl = urlBuilder.buildString();\n GWT.log(\"New url is [\" + newUrl + \"]\");\n\n Window.Location.replace(newUrl);\n }\n\n /**\n * @return true if the current page is in the default (desktop) preview mode, false otherwise.\n */\n public static boolean isPreview() {\n return isPreview;\n }\n\n public static void setPreview(boolean preview) {\n isPreview = preview;\n }\n\n}\n =================================================================== --- ../../git/magnolia_main/magnolia-templating-editor/src/main/java/info/magnolia/templating/editor/client/PageEditor.java (revision 026ad62bb10416ca8a59c36db5db8d8376d8c563) +++ ../../git/magnolia_main/magnolia-templating-editor/src/main/java/info/magnolia/templating/editor/client/PageEditor.java (revision ) @@ -304,6 +304,8 @@ } private void processDocument(Node node, MgnlElement mgnlElement) { + boolean proceed = true; + if(process) { for (int i = 0; i < node.getChildCount(); i++) { Node childNode = node.getChild(i); @@ -321,10 +323,11 @@ } } else if (childNode.getNodeType() == Node.ELEMENT_NODE && mgnlElement != null) { - ElementProcessor.process(childNode, mgnlElement); + proceed = ElementProcessor.process(childNode, mgnlElement); } - + if (proceed) { - processDocument(childNode, mgnlElement); + processDocument(childNode, mgnlElement); + } } } }