001package 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 023import org.gwtbootstrap3.client.ui.base.HasId; 024 025import com.google.gwt.dom.client.Document; 026import com.google.gwt.dom.client.Element; 027import 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 */ 049public 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}