View Javadoc
1   /**
2    * This file Copyright (c) 2011-2018 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.ui.vaadin.gwt.client.editor.dom.processor;
35  
36  import info.magnolia.rendering.template.AreaDefinition;
37  import info.magnolia.ui.vaadin.gwt.client.editor.dom.MgnlArea;
38  import info.magnolia.ui.vaadin.gwt.client.editor.dom.MgnlElement;
39  import info.magnolia.ui.vaadin.gwt.client.editor.event.FrameNavigationEvent;
40  import info.magnolia.ui.vaadin.gwt.client.editor.model.Model;
41  
42  import com.google.gwt.dom.client.Element;
43  import com.google.web.bindery.event.shared.EventBus;
44  
45  /**
46   * Processor for {@link com.google.gwt.user.client.DOM} {@link Element}s. This is a crucial part of the page editor as it:
47   * <pre>
48   *  <ul>
49   *      <li>Creates a mapping between the {@link Element} of the DOM and {@link MgnlElement}. Used e.g. in {@link info.magnolia.ui.vaadin.gwt.client.editor.model.focus.FocusModel} to map elements to the right area or component.</li>
50   *      <li>Looks for certain markers in the attributes which will help inject the control bars at the right spot.</li>
51   *      <li>
52   *          Modifies links based on their function inside the page:
53   *          <ul>
54   *              <li>A link inside the navigation will be overwritten by an onclick method.</li>
55   *              <li>Normal links will simply be disabled.</li>
56   *          </ul>
57   *      </li>
58   *  </ul>
59   * </pre>
60   */
61  public class ElementProcessor {
62  
63      private static final String NAVIGATION_ROLE = "navigation";
64      private static final String ATTRIBUTE_ROLE = "role";
65      private final EventBus eventBus;
66      private final Model model;
67  
68      public ElementProcessor(EventBus eventBus, Model model) {
69  
70          this.eventBus = eventBus;
71          this.model = model;
72      }
73  
74      /**
75       * Processes the current {@link Element}.
76       *
77       * @param element the current node beeing processed
78       * @param mgnlElement the associated {@link info.magnolia.ui.vaadin.gwt.client.editor.dom.MgnlElement}
79       * @param preview
80       */
81      public void process(Element element, MgnlElement mgnlElement, boolean preview) {
82  
83          if (element.hasTagName("A")) {
84  
85              if (preview || isNavigation(element)) {
86                  registerOnclick(element);
87              } else {
88                  disableLink(element);
89                  removeHover(element);
90              }
91          }
92  
93          if (mgnlElement == null || mgnlElement.isPage()) {
94              return;
95          }
96  
97          model.addElement(mgnlElement, element);
98          if (mgnlElement instanceof MgnlArea) {
99              MgnlArea../../../../../../../../../info/magnolia/ui/vaadin/gwt/client/editor/dom/MgnlArea.html#MgnlArea">MgnlArea area = (MgnlArea) mgnlElement;
100 
101             if (element.hasAttribute(AreaDefinition.CMS_ADD)) {
102                 area.setComponentMarkerElement(element);
103                 return;
104             }
105         }
106         if (element.hasAttribute(AreaDefinition.CMS_EDIT)) {
107             mgnlElement.setEditElement(element);
108         }
109         else {
110             if (mgnlElement.getFirstElement() == null) {
111                 mgnlElement.setFirstElement(element);
112             }
113 
114             if (mgnlElement.getLastElement() == null || !mgnlElement.getLastElement().isOrHasChild(element)) {
115                 mgnlElement.setLastElement(element);
116             }
117         }
118 
119 
120     }
121 
122     /**
123      * Fires a {@link FrameNavigationEvent} to the eventBus.
124      *
125      * @see info.magnolia.ui.vaadin.gwt.client.connector.PageEditorConnector#init()
126      */
127     private void navigate(String path) {
128         eventBus.fireEvent(new FrameNavigationEvent(path));
129     }
130 
131     /**
132      * JSNI method which registers an onclick method which will call {@link #navigate(String)}.
133      * Extracts the href attribute from the {@link Element} and passes it as a parameter.
134      * By returning false the browser won't follow the link.
135      */
136     private native void registerOnclick(Element element) /*-{
137         var that = this;
138         var path = element.href;
139         var target = element.target;
140         if (target == '_blank') {
141             return true;
142         }
143         if (element.onclick == null) {
144             element.onclick = $entry(function () {
145                 that.@info.magnolia.ui.vaadin.gwt.client.editor.dom.processor.ElementProcessor::navigate(Ljava/lang/String;)(path);
146                 return false;
147             });
148         }
149     }-*/;
150 
151     private void removeHover(Element element) {
152         element.addClassName("disabled");
153     }
154 
155     private native static void disableLink(Element element) /*-{
156         if (element.onclick == null) {
157             element.onclick = function() {
158                 return false;
159             };
160         }
161     }-*/;
162 
163     /**
164      * Searches for an element with attribute {@link #ATTRIBUTE_ROLE} defined as {@link #NAVIGATION_ROLE} on the element itself and it's ancestors.
165      */
166     private boolean isNavigation(Element element) {
167         if (element == null) {
168             return false;
169         }
170         if (element.getAttribute(ATTRIBUTE_ROLE).equals(NAVIGATION_ROLE)) {
171             return true;
172         }
173         return isNavigation(element.getParentElement());
174     }
175 
176 }