@Override public void modifyBootstrapPage(BootstrapPageResponse response) { Element head = response.getDocument().getElementsByTag("head").get(0); String jqueryUrl = String.format("VAADIN/webjars/%s", webConfig.getWebJarJQueryPath()); includeScript(jqueryUrl, response, head); int customDeviceWidthForViewport = webConfig.getCustomDeviceWidthForViewport(); if (customDeviceWidthForViewport > 0) { includeMetaViewport("width=" + customDeviceWidthForViewport + ", initial-scale=" + webConfig.getPageInitialScale(), response, head); } else if (webConfig.getUseDeviceWidthForViewport()) { includeMetaViewport("width=device-width" + ", initial-scale=" + webConfig.getPageInitialScale(), response, head); } }
@Override public void modifyBootstrapPage(BootstrapPageResponse response) { Document document = response.getDocument(); Element head = document.getElementsByTag("head").get(0); for (ApplicationIcon icon : applicationIcon) { // <link rel="apple-touch-icon" sizes="114x114" // href="touch-icon-iphone4.png" /> Element iconEl = document.createElement("link"); iconEl.attr("rel", "apple-touch-icon"); String sizes = icon.getSizes(); if (sizes != null) { iconEl.attr("sizes", sizes); } iconEl.attr("href", icon.getHref()); head.appendChild(iconEl); } }
@Override public void modifyBootstrapPage(BootstrapPageResponse response) { super.modifyBootstrapPage(response); Element head = response.getDocument().getElementsByTag("head").get(0); includeMetaViewport("width=device-width, initial-scale=0.8", response, head); }
@Override public void modifyBootstrapPage(BootstrapPageResponse response) { Element head = response.getDocument().getElementsByTag("head") .get(0); Element link = response.getDocument().createElement("link"); link.attr("rel", "stylesheet"); link.attr("type", "text/css"); link.attr("href", "http://fonts.googleapis.com/css?family=Permanent+Marker"); head.appendChild(link); }
/** * Creates a new instance of TouchKitSettings and binds it to the given * {@link VaadinService}. * * @param vaadinService * the vaadin service to which the new instance should be bound. */ public TouchKitSettings(VaadinService vaadinService) { setViewPortSettings(new ViewPortSettings()); /* * WP8 needs device-width and maximum scale to work like ios (with * default settings). Without these custom values pixel size is huge in * landscape mode. With these values iphone5 goes to letter box when on * home screen. * * @viewport css rule will replace meta tags in the future and there is * a prefixed version in MobileIE10, but it is buggy (landscape mode * don't change "device-width"). */ final ViewPortSettings ieViewPortSettings = new ViewPortSettings(); ieViewPortSettings.setViewPortWidth("device-width"); ieViewPortSettings.setViewPortMaximumScale(1f); addViewPortSettings(new SettingSelector<ViewPortSettings>() { @Override public ViewPortSettings select(BootstrapPageResponse response) { String ua = response.getRequest().getHeader("User-Agent"); if (ua != null && ua.contains("IEMobile")) { return ieViewPortSettings; } return null; } }); setWebAppSettings(new WebAppSettings()); setApplicationIcons(new ApplicationIcons()); setApplicationCacheSettings(new ApplicationCacheSettings()); vaadinService.addSessionInitListener(this); vaadinService.setSystemMessagesProvider(this); }
/** * Selects viewport settings to be used for given bootstrap * request/response. * * @param response * @return The {@link ViewPortSettings} */ private ViewPortSettings selectViewPortSettings( BootstrapPageResponse response) { for (SettingSelector<ViewPortSettings> s : selectorBasedViewPortSettings) { ViewPortSettings selected = s.select(response); if (selected != null) { return selected; } } return defaultViewPortSettings; }
@Override public void modifyBootstrapPage(BootstrapPageResponse response) { ViewPortSettings viewPortSettings2 = selectViewPortSettings(response); if (viewPortSettings2 != null) { viewPortSettings2.modifyBootstrapPage(response); } if (getWebAppSettings() != null) { getWebAppSettings().modifyBootstrapPage(response); } if (getApplicationIcons() != null) { getApplicationIcons().modifyBootstrapPage(response); } if (getApplicationCacheSettings() != null) { OfflineModeEnabled offline = null; CacheManifestEnabled manifest = null; Class<?> clazz = response.getUiClass(); if (clazz != null) { offline = clazz.getAnnotation(OfflineModeEnabled.class); manifest = clazz.getAnnotation(CacheManifestEnabled.class); } if (response.getSession().getService() instanceof VaadinServletService) { clazz = ((VaadinServletService) response.getSession() .getService()).getServlet().getClass(); if (offline == null) { offline = clazz.getAnnotation(OfflineModeEnabled.class); } if (manifest == null) { manifest = clazz.getAnnotation(CacheManifestEnabled.class); } } getApplicationCacheSettings().setCacheManifestEnabled( manifest == null || manifest.value()); getApplicationCacheSettings().setOfflineModeEnabled( offline == null || offline.value()); getApplicationCacheSettings().modifyBootstrapPage(response); } }
/** * Generates the manifest file name for the given page response * * @param response * Page response where the manifest will be added. * @return The manifest file name, eg. "safari.manifest". */ protected String generateManifestFileName(BootstrapPageResponse response) { String userAgent = response.getRequest().getHeader("user-agent"); if (userAgent == null) { // Should not happen in "normal" cases but the header is optional return "safari.manifest"; } VBrowserDetails browser = new VBrowserDetails(userAgent); if (browser.isFirefox()) { return "gecko1_8.manifest"; } else if (browser.isChrome()) { return "safari.manifest"; } else if (browser.isIE()) { if (browser.getBrowserMajorVersion() > 10) { return "gecko1_8.manifest"; } else { return "ie10.manifest"; } } else if (browser.isAndroid()) { int major = browser.getOperatingSystemMajorVersion(); int minor = browser.getOperatingSystemMinorVersion(); if (major < 4 || (major == 4 && minor < 4)) { return "aosp.manifest"; } else { return "safari.manifest"; } } else { return "safari.manifest"; } }
@Override public void modifyBootstrapPage(BootstrapPageResponse response) { Document document = response.getDocument(); Element html = document.getElementsByTag("html").get(0); Element head = document.getElementsByTag("head").get(0); DocumentType doctype = (DocumentType) html.previousSibling(); DocumentType html5doc = new DocumentType("html", "", "", ""); doctype.replaceWith(html5doc); Element element = document.createElement("meta"); element.attr("name", "viewport"); StringBuilder content = new StringBuilder(); boolean open = false; open = addViewPortRule(content, open, "width", getViewPortWidth()); if (!isViewPortUserScalable()) { open = addViewPortRule(content, open, "user-scalable", "no"); } open = addViewPortRule(content, open, "initial-scale", getViewPortInitialScale()); open = addViewPortRule(content, open, "maximum-scale", getViewPortMaximumScale()); open = addViewPortRule(content, open, "minimum-scale", getViewPortMaximumScale()); element.attr("content", content.toString()); head.appendChild(element); // meta tag to disable gray tap highlights in WP8 (note, for some reason // these do not appear in W8, not even RT) // <meta name="msapplication-tap-highlight" content="no" /> element = document.createElement("meta"); element.attr("name", "msapplication-tap-highlight"); element.attr("content", "no"); head.appendChild(element); }
@Override public void serviceInit(ServiceInitEvent event) { ValoDependencyFilter dependencyFilter = new ValoDependencyFilter(); if (dependencyFilter.hasValoWebJar()) { event.addDependencyFilter(dependencyFilter); } VaadinServletService service = (VaadinServletService) event.getSource(); WebApplicationContext applicationContext = WebApplicationContextUtils .findWebApplicationContext( service.getServlet().getServletContext()); String apiKey = applicationContext.getEnvironment() .getProperty("map.apikey"); if (apiKey == null) { throw new RuntimeException( "Configure a map.apikey in your application.properties"); } event.addBootstrapListener(new BootstrapListener() { @Override public void modifyBootstrapPage(BootstrapPageResponse response) { Element head = response.getDocument().head(); head.appendElement("meta").attr("name", "viewport") .attr("content", "width=device-width, initial-scale=1"); // Flow sets element properties too late for google-map to get // the right API key. As a temporary workaround, we put our key // in the map's prototype instead. head.appendElement("script").html("window.mapApiKey = '" + apiKey + "';\n" + "customElements.whenDefined('google-map').then(function() {customElements.get('google-map').prototype.apiKey = window.mapApiKey})"); head.appendElement("link").attr("rel", "import").attr("href", response.getUriResolver().resolveVaadinUri( "frontend://bower_components/vaadin-valo-theme/typography.html")); head.appendElement("link").attr("rel", "import").attr("href", response.getUriResolver().resolveVaadinUri( "frontend://bower_components/vaadin-valo-theme/color.html")); head.appendElement("custom-style").appendElement("style") .attr("include", "valo-typography valo-colors"); } }); }
protected void includeScript(String src, BootstrapPageResponse response, Element head) { Element script = response.getDocument().createElement("script"); script.attr("src", src); head.appendChild(script); }
protected void includeMetaViewport(String content, BootstrapPageResponse response, Element head) { Element meta = response.getDocument().createElement("meta"); meta.attr("name", "viewport"); meta.attr("content", content); head.appendChild(meta); }
@Override public void modifyBootstrapPage(BootstrapPageResponse response) { Element head = response.getDocument().head(); // head = new Element(Tag.valueOf("div"), ""); // Favicons and links generated by // http://realfavicongenerator.net/ // addLink(head, "rel=shortcut icon", "href=/images/favicon.ico"); addLink(head, "rel=icon", "type=image/png", "href=/images/favicon-32x32.png", "sizes=32x32"); addLink(head, "rel=icon", "type=image/png", "href=/images/favicon-96x96.png", "sizes=96x96"); addLink(head, "rel=icon", "type=image/png", "href=/images/favicon-16x16.png", "sizes=16x16"); // Apple icons // addLink(head, "apple-touch-icon", "57x57", // "/images/apple-touch-icon-57x57.png"); // addLink(head, "apple-touch-icon", "60x60", // "/images/apple-touch-icon-60x60.png"); // addLink(head, "apple-touch-icon", "72x72", // "/images/apple-touch-icon-72x72.png"); // addLink(head, "apple-touch-icon", "76x76", // "/images/apple-touch-icon-76x76.png"); // addLink(head, "apple-touch-icon", "114x114", // "/images/apple-touch-icon-114x114.png"); // addLink(head, "apple-touch-icon", "120x120", // "/images/apple-touch-icon-120x120.png"); // addLink(head, "apple-touch-icon", "144x144", // "/images/apple-touch-icon-144x144.png"); // addLink(head, "apple-touch-icon", "152x152", // "/images/apple-touch-icon-152x152.png"); // addMeta(head, "name=theme-color", "content=#ffffff"); // Android // addLink(head, "rel=manifest", "href=/images/manifest.json"); // Safari // addLink(head, "rel=mask-icon", // "href=/images/safari-pinned-tab.svg", "color=#5bbad5"); // MS // addMeta(head, "name=msapplication-TileColor", "content=#da532c"); // addMeta(head, "name=msapplication-TileImage", // "content=/images/mstile-144x144.png"); // addMeta(head, "name=msapplication-config", // "content=/images/browserconfig.xml"); }
@Override public void modifyBootstrapPage(BootstrapPageResponse response) { Document document = response.getDocument(); Element head = document.getElementsByTag("head").get(0); Element element; if (isWebAppCapable()) { element = document.createElement("meta"); element.attr("name", "apple-mobile-web-app-capable"); element.attr("content", "yes"); head.appendChild(element); } if (getStatusBarStyle() != null) { element = document.createElement("meta"); element.attr("name", "apple-mobile-web-app-status-bar-style"); element.attr("content", getStatusBarStyle()); head.appendChild(element); } if (getStartupImage() != null) { element = document.createElement("link"); element.attr("rel", "apple-touch-startup-image"); element.attr("href", getStartupImage()); head.appendChild(element); } /* * Ensure window has "stable name", in case PreserveOnRefresh is used. * This is to fool vaadinBootstrap.js so that for example applications * used as ios "home screen webapps", can preserve their state among app * switches, like following links (with browser) and then returning back * to app. */ if (response.getUiClass().getAnnotation(PreserveOnRefresh.class) != null) { element = document.createElement("script"); element.attr("type", "text/javascript"); element.appendText("\nwindow.name = '" + response.getUiClass().hashCode() + "';\n"); head.appendChild(element); } }
@Override public void modifyBootstrapPage(BootstrapPageResponse response) { Document document = response.getDocument(); // Add the widgetsetUrl parameter to the bootstrap parameters. // This is overridden to avoid adding the naive random query // parameter (used by core to avoid caching of js file). final VaadinService service = response.getSession().getService(); final VaadinRequest request = response.getRequest(); final String staticFilePath = service .getStaticFileLocation(request); // VAADIN folder location final String vaadinDir = staticFilePath + "/VAADIN/"; // Figure out widgetset final UICreateEvent event = new UICreateEvent(request, response.getUiClass()); String widgetset = response.getUIProvider().getWidgetset(event); if (widgetset == null) { widgetset = request.getService() .getConfiguredWidgetset(request); } // Url for the widgetset final String widgetsetUrl = String.format( "%swidgetsets/%s/%s.nocache.js", vaadinDir, widgetset, widgetset); // Update the bootstrap page Element scriptTag = document.getElementsByTag("script").last(); String script = scriptTag.html(); scriptTag.html(""); script = script.replace("});", ",\"widgetsetUrl\":\"" + widgetsetUrl + "\",\"offlineEnabled\":" + isOfflineModeEnabled() + "});"); scriptTag.appendChild(new DataNode(script, scriptTag.baseUri())); if (isCacheManifestEnabled()) { // Add cache manifest attribute to html tag document.getElementsByTag("html").attr( "manifest", vaadinDir + "widgetsets/" + widgetset + "/" + generateManifestFileName(response)); } }
/** * @param response * @return used settings or null if settings shouldn't be used for this * request. */ T select(BootstrapPageResponse response);