001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.gwt.client.util; 029 030import java.util.List; 031 032import com.google.gwt.core.client.JavaScriptObject; 033import com.google.gwt.user.client.Timer; 034 035/** 036 * Helper class to append a stylesheet link to the head of the current page and run a callback when everything has been loaded. 037 */ 038public class CmsStylesheetLoader { 039 040 /** The callback that should be called when everything has been loaded. */ 041 private Runnable m_allLoadedCallback; 042 043 /** Indicates whether the all-loaded callback has already been called. */ 044 private boolean m_callbackCalled; 045 046 /** The callback for the onload handlers of the stylesheets. */ 047 private JavaScriptObject m_jsCallback; 048 049 /** The number of stylesheets that have been already loaded. */ 050 private int m_loadCounter; 051 052 /** The list of stylesheets to load. */ 053 private List<String> m_stylesheets; 054 055 /** 056 * Creates a new instance.<p> 057 * 058 * @param stylesheets the list of stylesheets to load 059 * @param allLoadedCallback the callback to call when everything has been loaded 060 */ 061 public CmsStylesheetLoader(List<String> stylesheets, Runnable allLoadedCallback) { 062 063 m_stylesheets = stylesheets; 064 m_loadCounter = 0; 065 m_allLoadedCallback = allLoadedCallback; 066 067 m_jsCallback = createJsCallback(); 068 } 069 070 /** 071 * Checks the window.document for given style-sheet.<p> 072 * 073 * @param styleSheetLink the style-sheet link 074 * @return true if the stylesheet is already present 075 */ 076 private static native boolean checkStylesheet(String styleSheetLink)/*-{ 077 var styles = $wnd.document.styleSheets; 078 for (var i = 0; i < styles.length; i++) { 079 if (styles[i].href != null 080 && styles[i].href.indexOf(styleSheetLink) >= 0) { 081 // style-sheet is present 082 return true; 083 } 084 } 085 return false; 086 }-*/; 087 088 /** 089 * Starts the loading process and creates a timer that sets of the callback after a given tiime if it hasn't already been triggered. 090 * 091 * @param timeout number of milliseconds after which the callback should be called if it hasn't already been 092 */ 093 public void loadWithTimeout(int timeout) { 094 095 for (String stylesheet : m_stylesheets) { 096 boolean alreadyLoaded = checkStylesheet(stylesheet); 097 if (alreadyLoaded) { 098 m_loadCounter += 1; 099 } else { 100 appendStylesheet(stylesheet, m_jsCallback); 101 } 102 } 103 checkAllLoaded(); 104 if (timeout > 0) { 105 Timer timer = new Timer() { 106 107 @SuppressWarnings("synthetic-access") 108 @Override 109 public void run() { 110 111 callCallback(); 112 } 113 }; 114 115 timer.schedule(timeout); 116 } 117 } 118 119 /** 120 * Appends a stylesheet to the page head.<p> 121 * 122 * @param stylesheet the stylesheet link 123 * @param callback the load handler for the stylesheet link element 124 */ 125 private native void appendStylesheet(String stylesheet, JavaScriptObject callback) /*-{ 126 var headID = $wnd.document.getElementsByTagName("head")[0]; 127 var cssNode = $wnd.document.createElement('link'); 128 cssNode.type = 'text/css'; 129 cssNode.rel = 'stylesheet'; 130 cssNode.href = stylesheet; 131 headID.appendChild(cssNode, callback); 132 cssNode.addEventListener("load", callback); 133 }-*/; 134 135 /** 136 * Calls the callback if it hasn't already been triggered.<p> 137 */ 138 private void callCallback() { 139 140 if (!m_callbackCalled) { 141 m_callbackCalled = true; 142 m_allLoadedCallback.run(); 143 } 144 } 145 146 /** 147 * Checks if all stylesheets have been loaded.<p> 148 */ 149 private void checkAllLoaded() { 150 151 if (m_loadCounter == m_stylesheets.size()) { 152 callCallback(); 153 } 154 } 155 156 /** 157 * Creates the callback for the onload handlers of the link elements.<p> 158 * 159 * @return the callback 160 */ 161 private native JavaScriptObject createJsCallback() /*-{ 162 var self = this; 163 return function() { 164 self.@org.opencms.gwt.client.util.CmsStylesheetLoader::onLoadCallback()(); 165 } 166 }-*/; 167 168 /** 169 * The method which should be called by the onload handlers of the link elements.<p> 170 */ 171 private void onLoadCallback() { 172 173 m_loadCounter += 1; 174 checkAllLoaded(); 175 } 176 177}