styles.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.html.styles"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.html.styles"] = true;
  8. dojo.provide("dojox.html.styles");
  9. // summary:
  10. // Methods for creating and minipulating dynamic CSS Styles and Style Sheets
  11. //
  12. // example:
  13. // | dojox.html.createStyle("#myDiv input", "font-size:24px");
  14. // Creates Style #myDiv input, which can now be applied to myDiv, and
  15. // the inner input will be targeted
  16. // | dojox.html.createStyle(".myStyle", "color:#FF0000");
  17. // Now the class myStyle can be assigned to a node's className
  18. (function(){
  19. var dynamicStyleMap = {};
  20. var pageStyleSheets = {};
  21. var titledSheets = [];
  22. var styleIndicies = [];
  23. dojox.html.insertCssRule = function(/*String*/selector, /*String*/declaration, /*String*/styleSheetName){
  24. // summary:
  25. // Creates a style and attaches it to a dynamically created stylesheet
  26. // arguments:
  27. // selector:
  28. // A fully qualified class name, as it would appear in
  29. // a CSS dojo.doc. Start classes with periods, target
  30. // nodes with '#'. Large selectors can also be created
  31. // like:
  32. // | "#myDiv.myClass span input"
  33. // declaration:
  34. // A single string that would make up a style block, not
  35. // including the curly braces. Include semi-colons between
  36. // statements. Do not use JavaScript style declarations
  37. // in camel case, use as you would in a CSS dojo.doc:
  38. // | "color:#ffoooo;font-size:12px;margin-left:5px;"
  39. // styleSheetName: ( optional )
  40. // Name of the dynamic style sheet this rule should be
  41. // inserted into. If is not found by that name, it is
  42. // created. If no name is passed, the name "default" is
  43. // used.
  44. //
  45. var ss = dojox.html.getDynamicStyleSheet(styleSheetName);
  46. var styleText = selector + " {" + declaration + "}";
  47. console.log("insertRule:", styleText)
  48. if(dojo.isIE){
  49. // Note: check for if(ss.cssText) does not work
  50. ss.cssText+=styleText;
  51. console.log("ss.cssText:", ss.cssText)
  52. }else if(ss.sheet){
  53. ss.sheet.insertRule(styleText, ss._indicies.length);
  54. }else{
  55. ss.appendChild(dojo.doc.createTextNode(styleText));
  56. }
  57. ss._indicies.push(selector+" "+declaration);
  58. return selector; // String
  59. }
  60. dojox.html.removeCssRule = function(/*String*/selector, /*String*/declaration, /*String*/styleSheetName){
  61. // summary:
  62. // Removes a cssRule base on the selector and declaration passed
  63. // The declaration is needed for cases of dupe selectors
  64. // description: Only removes DYNAMICALLY created cssRules. If you
  65. // created it with dojox.html.insertCssRule, it can be removed.
  66. //
  67. var ss;
  68. var index=-1;
  69. for(var nm in dynamicStyleMap){
  70. if(styleSheetName && styleSheetName!=nm) {continue;}
  71. ss = dynamicStyleMap[nm];
  72. for(var i=0;i<ss._indicies.length;i++){
  73. if(selector+" "+declaration == ss._indicies[i]){
  74. index = i;
  75. break;
  76. }
  77. }
  78. if(index>-1) { break; }
  79. }
  80. if(!ss){
  81. console.log("No dynamic style sheet has been created from which to remove a rule.");
  82. return false;
  83. }
  84. if(index==-1){
  85. console.log("The css rule was not found and could not be removed.");
  86. return false;
  87. }
  88. ss._indicies.splice(index, 1);
  89. if(dojo.isIE){
  90. // Note: check for if(ss.removeRule) does not work
  91. ss.removeRule(index);
  92. }else if(ss.sheet){
  93. ss.sheet.deleteRule(index);
  94. }else if(document.styleSheets[0]){
  95. console.log("what browser hath useth thith?")
  96. //
  97. }
  98. return true; //Boolean
  99. }
  100. /* TODO
  101. dojox.html.modifyCssRule = function(selector, declaration, styleSheetName){
  102. Not implemented - it seems to have some merit for changing some complex
  103. selectors. It's not much use for changing simple ones like "span".
  104. For now, simply write a new rule which will cascade over the first.
  105. // summary
  106. // Modfies an existing cssRule
  107. }
  108. */
  109. dojox.html.getStyleSheet = function(/*String*/styleSheetName){
  110. // summary:
  111. // Returns a style sheet based on the argument.
  112. // Searches dynamic style sheets first. If no matches,
  113. // searches document style sheets.
  114. //
  115. // argument: (optional)
  116. // A title or an href to a style sheet. Title can be
  117. // an attribute in a tag, or a dynamic style sheet
  118. // reference. Href can be the name of the file.
  119. // If no argument, the assumed created dynamic style
  120. // sheet is used.
  121. // try dynamic sheets first
  122. if(dynamicStyleMap[styleSheetName || "default"]){
  123. return dynamicStyleMap[styleSheetName || "default"];
  124. }
  125. if(!styleSheetName){
  126. // no arg is nly good for the default style sheet
  127. // and it has not been created yet.
  128. return false;
  129. }
  130. var allSheets = dojox.html.getStyleSheets();
  131. // now try document style sheets by name
  132. if(allSheets[styleSheetName]){
  133. return dojox.html.getStyleSheets()[styleSheetName];
  134. }
  135. // check for partial matches in hrefs (so that a fully
  136. //qualified name does not have to be passed)
  137. for ( var nm in allSheets){
  138. if( allSheets[nm].href && allSheets[nm].href.indexOf(styleSheetName)>-1){
  139. return allSheets[nm];
  140. }
  141. }
  142. return false; //StyleSheet or false
  143. }
  144. dojox.html.getDynamicStyleSheet = function(/*String*/styleSheetName){
  145. // summary:
  146. // Creates and returns a dynamically created style sheet
  147. // used for dynamic styles
  148. //
  149. // argument:
  150. // styleSheetName /* optional String */
  151. // The name given the style sheet so that multiple
  152. // style sheets can be created and referenced. If
  153. // no argument is given, the name "default" is used.
  154. //
  155. if(!styleSheetName){ styleSheetName="default"; }
  156. if(!dynamicStyleMap[styleSheetName]){
  157. if(dojo.doc.createStyleSheet){ //IE
  158. dynamicStyleMap[styleSheetName] = dojo.doc.createStyleSheet();
  159. if(dojo.isIE < 9) {
  160. // IE9 calls this read-only. Loving the new browser so far.
  161. dynamicStyleMap[styleSheetName].title = styleSheetName;
  162. }
  163. }else{
  164. dynamicStyleMap[styleSheetName] = dojo.doc.createElement("style");
  165. dynamicStyleMap[styleSheetName].setAttribute("type", "text/css");
  166. dojo.doc.getElementsByTagName("head")[0].appendChild(dynamicStyleMap[styleSheetName]);
  167. console.log(styleSheetName, " ss created: ", dynamicStyleMap[styleSheetName].sheet);
  168. }
  169. dynamicStyleMap[styleSheetName]._indicies = [];
  170. }
  171. return dynamicStyleMap[styleSheetName]; //StyleSheet
  172. }
  173. dojox.html.enableStyleSheet = function(/*String*/styleSheetName){
  174. // summary:
  175. // Enables the style sheet with the name passed in the
  176. // argument. Deafults to the default style sheet.
  177. //
  178. var ss = dojox.html.getStyleSheet(styleSheetName);
  179. if(ss){
  180. if(ss.sheet){
  181. ss.sheet.disabled = false;
  182. }else{
  183. ss.disabled = false;
  184. }
  185. }
  186. }
  187. dojox.html.disableStyleSheet = function(styleSheetName){
  188. // summary:
  189. // Disables the dynamic style sheet with the name passed in the
  190. // argument. If no arg is passed, defaults to the default style sheet.
  191. //
  192. var ss = dojox.html.getStyleSheet(styleSheetName);
  193. if(ss){
  194. if(ss.sheet){
  195. ss.sheet.disabled = true;
  196. }else{
  197. ss.disabled = true;
  198. }
  199. }
  200. }
  201. dojox.html.activeStyleSheet = function(/*?String*/title){
  202. // summary:
  203. // Getter/Setter
  204. // description:
  205. // If passed a title, enables a that style sheet. All other
  206. // toggle-able style sheets are disabled.
  207. // If no argument is passed, returns currently enabled
  208. // style sheet.
  209. //
  210. var sheets = dojox.html.getToggledStyleSheets();
  211. if(arguments.length == 1){
  212. //console.log("sheets:", sheets);
  213. dojo.forEach(sheets, function(s){
  214. s.disabled = (s.title == title) ? false : true;
  215. //console.log("SWITCHED:", s.title, s.disabled, s.id);
  216. });
  217. }else{
  218. for(var i=0; i<sheets.length;i++){
  219. if(sheets[i].disabled == false){
  220. return sheets[i];
  221. }
  222. }
  223. }
  224. return true; //StyleSheet or Boolean - FIXME - doesn't make a lot of sense
  225. }
  226. dojox.html.getPreferredStyleSheet = function(){
  227. // summary
  228. // Returns the style sheet that was initially enabled
  229. // on document launch.
  230. //TODO
  231. }
  232. dojox.html.getToggledStyleSheets = function(){
  233. // summary:
  234. // Searches HTML for style sheets that are "toggle-able" -
  235. // can be enabled and disabled. These would include sheets
  236. // with the title attribute, as well as the REL attribute.
  237. // returns:
  238. // An array of all toggle-able style sheets
  239. // TODO: Sets of style sheets could be grouped according to
  240. // an ID and used in sets, much like different
  241. // groups of radio buttons. It would not however be
  242. // according to W3C spec
  243. //
  244. if(!titledSheets.length){
  245. var sObjects = dojox.html.getStyleSheets();
  246. for(var nm in sObjects){
  247. if(sObjects[nm].title){
  248. //console.log("TITLE:", sObjects[nm].title, sObjects[nm])
  249. titledSheets.push(sObjects[nm]);
  250. }
  251. }
  252. }
  253. return titledSheets; //Array
  254. }
  255. dojox.html.getStyleSheets = function(){
  256. // summary:
  257. // Collects all the style sheets referenced in the HTML page,
  258. // including any incuded via @import.
  259. //
  260. // returns:
  261. // An hash map of all the style sheets.
  262. //
  263. // TODO: Does not recursively search for @imports, so it will
  264. // only go one level deep.
  265. //
  266. if(pageStyleSheets.collected) {return pageStyleSheets;}
  267. var sheets = dojo.doc.styleSheets;
  268. //console.log("styleSheets:", sheets);
  269. dojo.forEach(sheets, function(n){
  270. var s = (n.sheet) ? n.sheet : n;
  271. var name = s.title || s.href;
  272. if(dojo.isIE){
  273. // IE attaches a style sheet for VML - do not include this
  274. if(s.cssText.indexOf("#default#VML")==-1){
  275. if(s.href){
  276. // linked
  277. pageStyleSheets[name] = s;
  278. }else if(s.imports.length){
  279. // Imported via @import
  280. dojo.forEach(s.imports, function(si){
  281. pageStyleSheets[si.title || si.href] = si;
  282. });
  283. }else{
  284. //embedded within page
  285. pageStyleSheets[name] = s;
  286. }
  287. }
  288. }else{
  289. //linked or embedded
  290. pageStyleSheets[name] = s;
  291. pageStyleSheets[name].id = s.ownerNode.id;
  292. dojo.forEach(s.cssRules, function(r){
  293. if(r.href){
  294. // imported
  295. pageStyleSheets[r.href] = r.styleSheet;
  296. pageStyleSheets[r.href].id = s.ownerNode.id;
  297. }
  298. });
  299. }
  300. });
  301. //console.log("pageStyleSheets:", pageStyleSheets);
  302. pageStyleSheets.collected = true;
  303. return pageStyleSheets; //Object
  304. }
  305. })();
  306. }