1 /** 2 * This file Copyright (c) 2010-2013 Magnolia International 3 * Ltd. (http://www.magnolia-cms.com). All rights reserved. 4 * 5 * 6 * This file is dual-licensed under both the Magnolia 7 * Network Agreement and the GNU General Public License. 8 * You may elect to use one or the other of these licenses. 9 * 10 * This file is distributed in the hope that it will be 11 * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the 12 * implied warranty of MERCHANTABILITY or FITNESS FOR A 13 * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. 14 * Redistribution, except as permitted by whichever of the GPL 15 * or MNA you select, is prohibited. 16 * 17 * 1. For the GPL license (GPL), you can redistribute and/or 18 * modify this file under the terms of the GNU General 19 * Public License, Version 3, as published by the Free Software 20 * Foundation. You should have received a copy of the GNU 21 * General Public License, Version 3 along with this program; 22 * if not, write to the Free Software Foundation, Inc., 51 23 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 24 * 25 * 2. For the Magnolia Network Agreement (MNA), this file 26 * and the accompanying materials are made available under the 27 * terms of the MNA which accompanies this distribution, and 28 * is available at http://www.magnolia-cms.com/mna.html 29 * 30 * Any modifications to this file must keep this entire header 31 * intact. 32 * 33 */ 34 package info.magnolia.ui.vaadin.gwt.client.layout; 35 36 import com.google.gwt.core.client.JavaScriptObject; 37 38 /** 39 * Utility class for fetching CSS properties from DOM StyleSheets JS object and 40 * for creating new CSS rules dynamically. 41 */ 42 public class CssRule { 43 44 private final String selector; 45 private final JavaScriptObject rules = null; 46 47 private CssRule(final String selector) { 48 this.selector = selector; 49 } 50 51 /** 52 * @param selector the CSS selector to search for in the stylesheets 53 * @param deep should the search follow any @import statements? 54 */ 55 public CssRule(final String selector, final boolean deep) { 56 this.selector = selector; 57 fetchRule(selector, deep); 58 } 59 60 private native void fetchRule(final String selector, final boolean deep) 61 /*-{ 62 var sheets = $doc.styleSheets; 63 for(var i = 0; i < sheets.length; i++) { 64 var sheet = sheets[i]; 65 if(sheet.href && sheet.href.indexOf("VAADIN/themes")>-1) { 66 this.@info.magnolia.ui.vaadin.gwt.client.layout.CssRule::rules = @info.magnolia.ui.vaadin.gwt.client.layout.CssRule::searchForRule(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;Z)(sheet, selector, deep); 67 return; 68 } 69 } 70 this.@info.magnolia.ui.vaadin.gwt.client.layout.CssRule::rules = []; 71 }-*/; 72 73 /* 74 * Loops through all current style rules and collects all matching to 75 * 'rules' array. The array is reverse ordered (last one found is first). 76 */ 77 private static native JavaScriptObject searchForRule( 78 final JavaScriptObject sheet, final String selector, 79 final boolean deep) 80 /*-{ 81 if(!$doc.styleSheets) 82 return null; 83 84 selector = selector.toLowerCase(); 85 86 var allMatches = []; 87 88 // IE handles imported sheet differently 89 if(deep && sheet.imports.length > 0) { 90 for(var i=0; i < sheet.imports.length; i++) { 91 var imports = @info.magnolia.ui.vaadin.gwt.client.layout.CssRule::searchForRule(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;Z)(sheet.imports[i], selector, deep); 92 allMatches.concat(imports); 93 } 94 } 95 96 var theRules = new Array(); 97 if (sheet.cssRules) 98 theRules = sheet.cssRules 99 else if (sheet.rules) 100 theRules = sheet.rules 101 102 var j = theRules.length; 103 for(var i=0; i<j; i++) { 104 var r = theRules[i]; 105 if(r.type == 1 || sheet.imports) { 106 var selectors = r.selectorText.toLowerCase().split(","); 107 var n = selectors.length; 108 for(var m=0; m<n; m++) { 109 if(selectors[m].replace(/^\s+|\s+$/g, "") == selector) { 110 allMatches.unshift(r); 111 break; // No need to loop other selectors for this rule 112 } 113 } 114 } else if(deep && r.type == 3) { 115 // Search @import stylesheet 116 var imports = @info.magnolia.ui.vaadin.gwt.client.layout.CssRule::searchForRule(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;Z)(r.styleSheet, selector, deep); 117 allMatches.concat(imports); 118 } 119 } 120 121 return allMatches; 122 }-*/; 123 124 /** 125 * Returns a specific property value from this CSS rule. 126 * 127 * @param propertyName camelCase CSS property name 128 * @return the value of the property as a String 129 */ 130 public native String getProperty(final String propertyName) 131 /*-{ 132 var j = this.@info.magnolia.ui.vaadin.gwt.client.layout.CssRule::rules.length; 133 for(var i=0; i<j; i++){ 134 var value = this.@info.magnolia.ui.vaadin.gwt.client.layout.CssRule::rules[i].style[propertyName]; 135 if(value) 136 return value; 137 } 138 return null; 139 }-*/; 140 141 /** 142 * Sets a specific property value for this CSS rule. 143 * 144 * @param propertyName camelCase CSS property name 145 * @param propertyValue the value of the property as a String 146 */ 147 public native void setProperty(final String propertyName, 148 final String propertyValue) 149 /*-{ 150 this.@info.magnolia.ui.vaadin.gwt.client.layout.CssRule::rules[0].style[propertyName] = propertyValue; 151 }-*/; 152 153 public String getSelector() { 154 return selector; 155 } 156 157 public static CssRule create(String selector) { 158 CssRule newRule = new CssRule(selector); 159 createRule(selector, newRule); 160 return newRule; 161 } 162 163 private static native void createRule(final String selector, CssRule rule) 164 /*-{ 165 var sheets = $doc.styleSheets; 166 for(var i = 0; i < sheets.length; i++) { 167 var sheet = sheets[i]; 168 if(sheet.href && sheet.href.indexOf("VAADIN/themes")>-1) { 169 if(sheet.insertRule) { 170 sheet.insertRule(selector + "{}", sheet.cssRules.length); 171 var r = sheet.cssRules[sheet.cssRules.length-1]; 172 } else { // IE 173 sheet.addRule(selector, "foo:bar"); 174 var r = sheet.rules[sheet.rules.length-1]; 175 } 176 rule.@info.magnolia.ui.vaadin.gwt.client.layout.CssRule::rules = [r]; 177 } 178 } 179 }-*/; 180 181 }