001 package org.gwtbootstrap3.client.ui;
002
003 /*
004 * #%L
005 * GwtBootstrap3
006 * %%
007 * Copyright (C) 2013 GwtBootstrap3
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 * http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023 import org.gwtbootstrap3.client.ui.base.HasId;
024
025 import com.google.gwt.dom.client.Document;
026 import com.google.gwt.dom.client.Element;
027 import com.google.gwt.user.client.ui.UIObject;
028
029 /**
030 * A ScrollSpy handles scrolling events (typically on {@code <body>}) and
031 * updates "active" states of a {@link Nav} accordingly.
032 * <h3>Note</h3> The target element <strong>must</strong> be a parent element of a
033 * {@code <ul class="nav">} or {@link Nav}.
034 * <p/>
035 * Also the ScrollSpy must be initialized when the target element has been added
036 * to the DOM, for example in {@link com.google.gwt.user.client.ui.Widget#onAttach()}.
037 * <pre>{@code
038 * @Override
039 * protected void onAttach() {
040 * super.onAttach();
041 * ScrollSpy.scrollSpy(this);
042 * }}</pre>
043 * <p/>
044 * See Bootstrap's <a
045 * href="http://getbootstrap.com/javascript/#scrollspy">documentation</a>.
046 *
047 * @author Sven Jacobs
048 */
049 public class ScrollSpy {
050
051 private final Element spyOn;
052 private final String target;
053
054 /**
055 * Attaches ScrollSpy to document {@code <body>} and with the specified
056 * target CSS selector.
057 *
058 * @param selector CSS selector for target element
059 * @return ScrollSpy
060 */
061 public static ScrollSpy scrollSpy(final String selector) {
062 return new ScrollSpy((Element) Document.get().getBody().cast(), selector);
063 }
064
065 /**
066 * Attaches ScrollSpy to document {@code <body>} and with the specified
067 * target element that <strong>must</strong> have an ID.
068 *
069 * @param target Target element having an ID
070 * @return ScrollSpy
071 */
072 public static ScrollSpy scrollSpy(final HasId target) {
073 return new ScrollSpy((Element) Document.get().getBody().cast(), target);
074 }
075
076 /**
077 * Attaches ScrollSpy to specified object with specified target selector.
078 *
079 * @param spyOn Spy on this object
080 * @param selector CSS selector of target element
081 * @return ScrollSpy
082 */
083 public static ScrollSpy scrollSpy(final UIObject spyOn, final String selector) {
084 return new ScrollSpy(spyOn.getElement(), selector);
085 }
086
087 /**
088 * Attaches ScrollSpy to specified object with specified target element.
089 *
090 * @param spyOn Spy on this object
091 * @param target Target element having an ID
092 * @return ScrollSpy
093 */
094 public static ScrollSpy scrollSpy(final UIObject spyOn, final HasId target) {
095 return new ScrollSpy(spyOn.getElement(), target);
096 }
097
098 /**
099 * Attaches ScrollSpy to specified element with specified target selector.
100 *
101 * @param spyOn Spy on this element
102 * @param selector CSS selector of target element
103 * @return ScrollSpy
104 */
105 public static ScrollSpy scrollSpy(final Element spyOn, final String selector) {
106 return new ScrollSpy(spyOn, selector);
107 }
108
109 private ScrollSpy(final Element spyOn, final String selector) {
110
111 this.spyOn = spyOn;
112 this.target = selector;
113
114 init(this.spyOn, this.target);
115 }
116
117 private ScrollSpy(final Element spyOn, final HasId target) {
118
119 final String id = target.getId();
120
121 if (id == null || id.isEmpty()) {
122 throw new IllegalArgumentException("ScrollSpy target element must have id");
123 }
124
125 this.spyOn = spyOn;
126 this.target = "#" + id;
127
128 init(this.spyOn, this.target);
129 }
130
131 /**
132 * Refresh ScrollSpy after elements have been added to or removed from the
133 * DOM.
134 */
135 public void refresh() {
136 refresh(spyOn);
137 }
138
139 private native void init(final Element e, final String target) /*-{
140 var $e = $wnd.jQuery(e);
141
142 $e.scrollspy({
143 target: target
144 });
145 }-*/;
146
147 private native void refresh(final Element e) /*-{
148 $wnd.jQuery(e).scrollspy('refresh');
149 }-*/;
150 }