@@ -0,0 +1,45 @@ | |||
/* | |||
* Copyright 2000-2016 Vaadin Ltd. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | |||
* use this file except in compliance with the License. You may obtain a copy of | |||
* the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |||
* License for the specific language governing permissions and limitations under | |||
* the License. | |||
*/ | |||
package com.vaadin.annotations; | |||
import java.lang.annotation.Documented; | |||
import java.lang.annotation.ElementType; | |||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.RetentionPolicy; | |||
import java.lang.annotation.Target; | |||
/** | |||
* Annotation enabling using multiple {@link JavaScript @JavaScript} | |||
* annotations. | |||
* <p> | |||
* <b>NOT meant to be used</b>, for multiple JavaScript dependencies, | |||
* {@link JavaScript @JavaScript} should be used instead. | |||
* | |||
* @author Vaadin Ltd | |||
*/ | |||
@Retention(RetentionPolicy.RUNTIME) | |||
@Target(ElementType.TYPE) | |||
@Documented | |||
public @interface InternalContainerAnnotationForJS { | |||
/** | |||
* Not to be used, instead multiple {@link JavaScript @JavaScript} | |||
* annotations should be used. | |||
* | |||
* @return an array of the JavaScript annotations | |||
*/ | |||
JavaScript[] value(); | |||
} |
@@ -0,0 +1,45 @@ | |||
/* | |||
* Copyright 2000-2016 Vaadin Ltd. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | |||
* use this file except in compliance with the License. You may obtain a copy of | |||
* the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |||
* License for the specific language governing permissions and limitations under | |||
* the License. | |||
*/ | |||
package com.vaadin.annotations; | |||
import java.lang.annotation.Documented; | |||
import java.lang.annotation.ElementType; | |||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.RetentionPolicy; | |||
import java.lang.annotation.Target; | |||
/** | |||
* Annotation enabling using multiple {@link StyleSheet @StyleSheet} | |||
* annotations. | |||
* <p> | |||
* <b>NOT meant to be used</b>, for multiple style sheet dependencies, | |||
* {@link StyleSheet @StyleSheet} should be used instead. | |||
* | |||
* @author Vaadin Ltd | |||
*/ | |||
@Retention(RetentionPolicy.RUNTIME) | |||
@Target(ElementType.TYPE) | |||
@Documented | |||
public @interface InternalContainerAnnotationForSS { | |||
/** | |||
* Not to be used, instead multiple {@link StyleSheet @StyleSheet} | |||
* annotations should be used. | |||
* | |||
* @return an array of the style sheet annotations | |||
*/ | |||
StyleSheet[] value(); | |||
} |
@@ -16,7 +16,9 @@ | |||
package com.vaadin.annotations; | |||
import java.lang.annotation.Documented; | |||
import java.lang.annotation.ElementType; | |||
import java.lang.annotation.Repeatable; | |||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.RetentionPolicy; | |||
import java.lang.annotation.Target; | |||
@@ -49,17 +51,22 @@ import com.vaadin.server.ClientConnector; | |||
* http://host.com/file1.js as is and file2.js from /com/example/file2.js on the | |||
* server's classpath using the ClassLoader that was used to load | |||
* com.example.MyConnector. | |||
* <p> | |||
* For adding multiple JavaScript files for a single component, you can use this | |||
* annotation multiple times. | |||
* | |||
* @author Vaadin Ltd | |||
* @since 7.0.0 | |||
*/ | |||
@Retention(RetentionPolicy.RUNTIME) | |||
@Target(ElementType.TYPE) | |||
@Documented | |||
@Repeatable(InternalContainerAnnotationForJS.class) | |||
public @interface JavaScript { | |||
/** | |||
* JavaScript files to load before initializing the client-side connector. | |||
* | |||
* @return an array of JavaScript file urls | |||
* @return an array of JavaScript file URLs | |||
*/ | |||
public String[] value(); | |||
} |
@@ -16,7 +16,9 @@ | |||
package com.vaadin.annotations; | |||
import java.lang.annotation.Documented; | |||
import java.lang.annotation.ElementType; | |||
import java.lang.annotation.Repeatable; | |||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.RetentionPolicy; | |||
import java.lang.annotation.Target; | |||
@@ -54,12 +56,17 @@ import com.vaadin.server.ClientConnector; | |||
* http://host.com/file1.css as is and file2.css from /com/example/file2.css on | |||
* the server's classpath using the ClassLoader that was used to load | |||
* com.example.MyConnector. | |||
* <p> | |||
* For adding multiple style sheets for a single component, you can use this | |||
* annotation multiple times. | |||
* | |||
* @author Vaadin Ltd | |||
* @since 7.0.0 | |||
*/ | |||
@Retention(RetentionPolicy.RUNTIME) | |||
@Target(ElementType.TYPE) | |||
@Documented | |||
@Repeatable(InternalContainerAnnotationForSS.class) | |||
public @interface StyleSheet { | |||
/** | |||
* Style sheets to load before initializing the client-side connector. |
@@ -437,23 +437,29 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler { | |||
.attr("href", themeUri + "/favicon.ico"); | |||
} | |||
JavaScript javaScript = uiClass.getAnnotation(JavaScript.class); | |||
if (javaScript != null) { | |||
String[] resources = javaScript.value(); | |||
for (String resource : resources) { | |||
String url = registerDependency(context, uiClass, resource); | |||
head.appendElement("script").attr("type", "text/javascript") | |||
.attr("src", url); | |||
JavaScript[] javaScripts = uiClass | |||
.getAnnotationsByType(JavaScript.class); | |||
if (javaScripts != null) { | |||
for (JavaScript javaScript : javaScripts) { | |||
String[] resources = javaScript.value(); | |||
for (String resource : resources) { | |||
String url = registerDependency(context, uiClass, resource); | |||
head.appendElement("script").attr("type", "text/javascript") | |||
.attr("src", url); | |||
} | |||
} | |||
} | |||
StyleSheet styleSheet = uiClass.getAnnotation(StyleSheet.class); | |||
if (styleSheet != null) { | |||
String[] resources = styleSheet.value(); | |||
for (String resource : resources) { | |||
String url = registerDependency(context, uiClass, resource); | |||
head.appendElement("link").attr("rel", "stylesheet") | |||
.attr("type", "text/css").attr("href", url); | |||
StyleSheet[] styleSheets = uiClass | |||
.getAnnotationsByType(StyleSheet.class); | |||
if (styleSheets != null) { | |||
for (StyleSheet styleSheet : styleSheets) { | |||
String[] resources = styleSheet.value(); | |||
for (String resource : resources) { | |||
String url = registerDependency(context, uiClass, resource); | |||
head.appendElement("link").attr("rel", "stylesheet") | |||
.attr("type", "text/css").attr("href", url); | |||
} | |||
} | |||
} | |||
@@ -288,21 +288,25 @@ public class UidlWriter implements Serializable { | |||
List<String> styleDependencies = new ArrayList<>(); | |||
for (Class<? extends ClientConnector> class1 : newConnectorTypes) { | |||
JavaScript jsAnnotation = class1 | |||
.getAnnotation(JavaScript.class); | |||
if (jsAnnotation != null) { | |||
for (String uri : jsAnnotation.value()) { | |||
scriptDependencies | |||
.add(manager.registerDependency(uri, class1)); | |||
JavaScript[] jsAnnotations = class1 | |||
.getAnnotationsByType(JavaScript.class); | |||
if (jsAnnotations != null) { | |||
for (JavaScript jsAnnotation : jsAnnotations) { | |||
for (String uri : jsAnnotation.value()) { | |||
scriptDependencies.add( | |||
manager.registerDependency(uri, class1)); | |||
} | |||
} | |||
} | |||
StyleSheet styleAnnotation = class1 | |||
.getAnnotation(StyleSheet.class); | |||
if (styleAnnotation != null) { | |||
for (String uri : styleAnnotation.value()) { | |||
styleDependencies | |||
.add(manager.registerDependency(uri, class1)); | |||
StyleSheet[] styleAnnotations = class1 | |||
.getAnnotationsByType(StyleSheet.class); | |||
if (styleAnnotations != null) { | |||
for (StyleSheet styleAnnotation : styleAnnotations) { | |||
for (String uri : styleAnnotation.value()) { | |||
styleDependencies.add( | |||
manager.registerDependency(uri, class1)); | |||
} | |||
} | |||
} | |||
} |
@@ -28,7 +28,8 @@ public class JavaScriptPreloading extends AbstractReindeerTestUI { | |||
public String xhtml; | |||
} | |||
@JavaScript({ "js_label.js", "wholly_different.js" }) | |||
@JavaScript("js_label.js") | |||
@JavaScript("wholly_different.js") | |||
public class JsLabel extends AbstractJavaScriptComponent { | |||
public JsLabel(final String xhtml) { |
@@ -23,7 +23,8 @@ import com.vaadin.tests.components.AbstractReindeerTestUI; | |||
import com.vaadin.ui.Label; | |||
@JavaScript("uiDependency.js") | |||
@StyleSheet("theme://uiDependency.css") | |||
@StyleSheet({ "theme://uiDependency1.css", "theme://uiDependency2.css" }) | |||
@StyleSheet("theme://uiDependency3.css") | |||
@Theme("tests-valo") | |||
public class UiDependenciesInHtml extends AbstractReindeerTestUI { | |||
@@ -1,24 +1,34 @@ | |||
(function() { | |||
var loadedBeforeVaadin = (window.vaadin === undefined); | |||
window.reportUiDependencyStatus = function() { | |||
var styleIndex = 1000; | |||
var style1Index = 1000; | |||
var style2Index = 1000; | |||
var style3Index = 1000; | |||
var themeIndex = -1; | |||
var stylesheets = document.querySelectorAll("link[rel=stylesheet]"); | |||
for(var i = 0; i < stylesheets.length; i++) { | |||
for (var i = 0; i < stylesheets.length; i++) { | |||
var stylesheet = stylesheets[i]; | |||
var href = stylesheet.getAttribute("href"); | |||
if (href.indexOf("uiDependency.css") > -1) { | |||
styleIndex = i; | |||
var href = stylesheet.getAttribute("href"); | |||
if (href.indexOf("uiDependency1.css") > -1) { | |||
style1Index = i; | |||
} else if (href.indexOf("uiDependency2.css") > -1) { | |||
style2Index = i; | |||
} else if (href.indexOf("uiDependency3.css") > -1) { | |||
style3Index = i; | |||
} else if (href.indexOf("styles.css" > -1)) { | |||
themeIndex = i; | |||
} | |||
} | |||
var status = "Script loaded before vaadinBootstrap.js: " + loadedBeforeVaadin; | |||
status += "<br />Style tag before vaadin theme: " + (styleIndex < themeIndex); | |||
var status = "Script loaded before vaadinBootstrap.js: " | |||
+ loadedBeforeVaadin; | |||
status += "<br />Style tag before vaadin theme: " | |||
+ (style1Index < themeIndex); | |||
status += "<br />Style tags in correct order: " | |||
+ (style1Index < style2Index && style2Index < style3Index); | |||
document.getElementById("statusBox").innerHTML = status; | |||
} | |||
})(); |
@@ -30,7 +30,7 @@ public class UiDependenciesInHtmlTest extends SingleBrowserTest { | |||
String statusText = findElement(By.id("statusBox")).getText(); | |||
Assert.assertEquals( | |||
"Script loaded before vaadinBootstrap.js: true\nStyle tag before vaadin theme: true", | |||
"Script loaded before vaadinBootstrap.js: true\nStyle tag before vaadin theme: true\nStyle tags in correct order: true", | |||
statusText); | |||
} | |||