[commit #9641] deprecated setStylesheet and removeStyleSheet in favor of jquery.stylesheet

16 views
Skip to first unread message

s...@tiddlywiki.org

unread,
May 11, 2009, 11:29:27 AM5/11/09
to
http://trac.tiddlywiki.org/changeset/9641

FND
2009-05-11 15:29:27 +0000 (Mon, 11 May 2009)
131
deprecated setStylesheet and removeStyleSheet in favor of jquery.stylesheet

This is a new stand-alone jQuery plugin.

ticket #1046

---------------

A Trunk/core/deprecated/Dom.js
U Trunk/core/deprecated/split.recipe
A Trunk/core/jquery/plugins/jquery.stylesheet.js
U Trunk/core/jquery/plugins/split.recipe
A Trunk/core/jquery/plugins/test/jquery.stylesheet.html
A Trunk/core/jquery/plugins/test/js/jquery.stylesheet.js
U Trunk/core/js/Dom.js

---------------

Added: Trunk/core/deprecated/Dom.js
===================================================================
--- Trunk/core/deprecated/Dom.js (rev 0)
+++ Trunk/core/deprecated/Dom.js 2009-05-11 15:29:27 UTC (rev 9641)
@@ -0,0 +1,15 @@
+//--
+//-- Deprecated DOM utilities
+//--
+
+// @Deprecated: Use jQuery.stylesheet instead
+function setStylesheet(s,id,doc)
+{
+ jQuery.stylesheet(s,{ id: id, doc: doc });
+}
+
+// @Deprecated: Use jQuery.stylesheet.remove instead
+function removeStyleSheet(id)
+{
+ jQuery.stylesheet.remove({ id: id });
+}

Modified: Trunk/core/deprecated/split.recipe
===================================================================
--- Trunk/core/deprecated/split.recipe 2009-05-11 09:59:48 UTC (rev 9640)
+++ Trunk/core/deprecated/split.recipe 2009-05-11 15:29:27 UTC (rev 9641)
@@ -1,4 +1,5 @@
+jsdeprecated: Crypto.js
+jsdeprecated: Dom.js
jsdeprecated: FileSystem.js
+jsdeprecated: Http.js
jsdeprecated: Tiddler.js
-jsdeprecated: Http.js
-jsdeprecated: Crypto.js

Added: Trunk/core/jquery/plugins/jquery.stylesheet.js
===================================================================
--- Trunk/core/jquery/plugins/jquery.stylesheet.js (rev 0)
+++ Trunk/core/jquery/plugins/jquery.stylesheet.js 2009-05-11 15:29:27 UTC (rev 9641)
@@ -0,0 +1,64 @@
+/*
+jquery.stylesheet.js
+
+jQuery plugin to dynamically insert CSS rules into a document
+
+Usage:
+ jQuery.stylesheet applies style definitions
+ jQuery.stylesheet.remove neutralizes style definitions
+
+Copyright (c) UnaMesa Association 2009
+
+Triple licensed under the BSD, MIT and GPL licenses:
+ http://www.opensource.org/licenses/bsd-license.php
+ http://www.opensource.org/licenses/mit-license.php
+ http://www.gnu.org/licenses/gpl.html
+*/
+
+(function($) {
+
+var defaultId = "customStyleSheet"; // XXX: rename to dynamicStyleSheet?
+
+// Add or replace a style sheet
+// css argument is a string of CSS rule sets
+// options.id is an optional name identifying the style sheet
+// options.doc is an optional document reference
+// N.B.: Uses DOM methods instead of jQuery to ensure cross-browser comaptibility.
+$.stylesheet = function(css, options) {
+ options = options || {};
+ var id = options.id || defaultId;
+ var doc = options.doc || document;
+ var el = doc.getElementById(id);
+ if(doc.createStyleSheet) { // IE-specific handling
+ if(el) {
+ el.parentNode.removeChild(el);
+ }
+ doc.getElementsByTagName("head")[0].insertAdjacentHTML("beforeEnd",
+ "&nbsp;<style id='" + id + "'>" + css + "</style>"); // fails without &nbsp;
+ } else { // modern browsers
+ if(el) {
+ el.replaceChild(doc.createTextNode(css), el.firstChild);
+ } else {
+ el = doc.createElement("style");
+ el.type = "text/css";
+ el.id = id;
+ el.appendChild(doc.createTextNode(css));
+ doc.getElementsByTagName("head")[0].appendChild(el);
+ }
+ }
+};
+
+// Remove existing style sheet
+// options.id is an optional name identifying the style sheet
+// options.doc is an optional document reference
+$.stylesheet.remove = function(options) {
+ options = options || {};
+ var id = options.id || defaultId;
+ var doc = options.doc || document;
+ var el = doc.getElementById(id);
+ if(el) {
+ el.parentNode.removeChild(el);
+ }
+};
+
+})(jQuery);

Modified: Trunk/core/jquery/plugins/split.recipe
===================================================================
--- Trunk/core/jquery/plugins/split.recipe 2009-05-11 09:59:48 UTC (rev 9640)
+++ Trunk/core/jquery/plugins/split.recipe 2009-05-11 15:29:27 UTC (rev 9641)
@@ -1,2 +1,3 @@
+jquery: jquery.encoding.digests.sha1.js
jquery: jquery.file.js
-jquery: jquery.encoding.digests.sha1.js
+jquery: jquery.stylesheet.js

Added: Trunk/core/jquery/plugins/test/jquery.stylesheet.html
===================================================================
--- Trunk/core/jquery/plugins/test/jquery.stylesheet.html (rev 0)
+++ Trunk/core/jquery/plugins/test/jquery.stylesheet.html 2009-05-11 15:29:27 UTC (rev 9641)
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en">
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Tests</title>
+ <link rel="stylesheet" type="text/css" href="../../../test/qunit/testsuite.css">
+ <script src="../../jquery-1.3.2.min.js" type="text/javascript"></script>
+ <!-- test suite -->
+ <script src="../../../test/qunit/testrunner.js" type="text/javascript"></script>
+ <script src="../../../test/qunit/raiseAssertion.js" type="text/javascript"></script>
+ <!-- plugin -->
+ <script src="../jquery.stylesheet.js" type="text/javascript"></script>
+ <!-- test code -->
+ <script src="js/jquery.stylesheet.js" type="text/javascript"></script>
+</head>
+
+<body>
+ <h2 id="banner"></h2>
+ <h2 id="userAgent"></h2>
+ <ol id="tests"></ol>
+ <div id="main"></div>
+</body>
+
+</html>

Added: Trunk/core/jquery/plugins/test/js/jquery.stylesheet.js
===================================================================
--- Trunk/core/jquery/plugins/test/js/jquery.stylesheet.js (rev 0)
+++ Trunk/core/jquery/plugins/test/js/jquery.stylesheet.js 2009-05-11 15:29:27 UTC (rev 9641)
@@ -0,0 +1,69 @@
+jQuery(document).ready(function() {
+ module("jquery.stylesheet");
+
+ test("apply", function() {
+ var actual, expected, el;
+
+ el = jQuery('<div />').appendTo(document.body);
+ jQuery.stylesheet("div { overflow: hidden; }");
+ actual = jQuery(el).css("overflow");
+ expected = "hidden";
+ same(actual, expected, "applies style definitions to document");
+ // teardown
+ jQuery(el).remove();
+ jQuery.stylesheet.remove();
+
+ el = jQuery('<div />').appendTo(document.body);
+ jQuery.stylesheet("div { font-style: italic; }");
+ actual = jQuery(el).css("font-style");
+ expected = "italic";
+ same(actual, expected, "applies style definitions to newly-created elements");
+ // teardown
+ jQuery(el).remove();
+ jQuery.stylesheet.remove();
+
+ jQuery.stylesheet("", { id: "dummyStyleSheet" });
+ actual = jQuery("#dummyStyleSheet").length;
+ expected = 1;
+ same(actual, expected, "generates style element using given ID");
+ // teardown
+ jQuery.stylesheet.remove({ id: "dummyStyleSheet" });
+
+ // TODO: test for options.doc argument
+
+ });
+
+ test("remove", function() {
+ var actual, expected;
+
+ // setup
+ el = jQuery('<div />').appendTo(document.body);
+ jQuery.stylesheet("div { overflow: hidden; }");
+ // test
+ jQuery.stylesheet.remove();
+ actual = jQuery(el).css("overflow");
+ expected = "visible";
+ same(actual, expected, "neutralizes style definitions");
+ // teardown
+ jQuery(el).remove();
+
+ // setup
+ jQuery.stylesheet("");
+ // test
+ jQuery.stylesheet.remove();
+ actual = jQuery("#customStyleSheet").length;
+ expected = 0;
+ same(actual, expected, "removes default style sheet if no ID is given");
+
+ // setup
+ jQuery.stylesheet("", { id: "dummyStyleSheet" });
+ // test
+ jQuery.stylesheet.remove({ id: "dummyStyleSheet" });
+ actual = jQuery("#dummyStyleSheet").length;
+ expected = 0;
+ same(actual, expected, "removes style element using given ID");
+
+ // TODO: test for options.doc argument
+
+ });
+});

Modified: Trunk/core/js/Dom.js
===================================================================
--- Trunk/core/js/Dom.js 2009-05-11 09:59:48 UTC (rev 9640)
+++ Trunk/core/js/Dom.js 2009-05-11 15:29:27 UTC (rev 9641)
@@ -196,40 +196,6 @@
return e;
}

-// Add a stylesheet, replacing any previous custom stylesheet
-function setStylesheet(s,id,doc)
-{
- if(!id)
- id = "customStyleSheet";
- if(!doc)
- doc = document;
- var n = doc.getElementById(id);
- if(doc.createStyleSheet) {
- // Test for IE's non-standard createStyleSheet method
- if(n)
- n.parentNode.removeChild(n);
- // This failed without the &nbsp;
- doc.getElementsByTagName("head")[0].insertAdjacentHTML("beforeEnd","&nbsp;<style id='" + id + "'>" + s + "</style>");
- } else {
- if(n) {
- n.replaceChild(doc.createTextNode(s),n.firstChild);
- } else {
- n = doc.createElement("style");
- n.type = "text/css";
- n.id = id;
- n.appendChild(doc.createTextNode(s));
- doc.getElementsByTagName("head")[0].appendChild(n);
- }
- }
-}
-
-function removeStyleSheet(id)
-{
- var e = document.getElementById(id);
- if(e)
- e.parentNode.removeChild(e);
-}
-
// Force the browser to do a document reflow when needed to workaround browser bugs
function forceReflow()
{

chris...@gmail.com

unread,
May 11, 2009, 11:54:15 AM5/11/09
to TiddlyWikiDev


On May 11, 4:29 pm, s...@tiddlywiki.org wrote:
> +// Add or replace a style sheet
> +// css argument is a string of CSS rule sets
> +// options.id is an optional name identifying the style sheet
> +// options.doc is an optional document reference
> +// N.B.: Uses DOM methods instead of jQuery to ensure cross-browser comaptibility.

I though much of the point of libraries like jQuery was to make it so
you didn't have to ensure cross-browser compatibility? They do that
for you.

?

FND

unread,
May 11, 2009, 12:44:16 PM5/11/09
to Tiddly...@googlegroups.com
Thanks for taking the time to review the code, Chris!

>> +// N.B.: Uses DOM methods instead of jQuery to ensure cross-browser comaptibility.
>
> I though much of the point of libraries like jQuery was to make it so
> you didn't have to ensure cross-browser compatibility?

I've discussed this with Jeremy.
Since the CSS rules have to be evaluated after being injected into the
document, browsers are quite peculiar here. That's why we're relying on
the proven (and partially browser-specific) low-level methods for now.

Having said that, I do have a jQuery-fied version of the internals on my
local Git branch, and plan on testing that in various browsers to see
whether it works (would save quite a few LoC).


-- F.

Jeremy Ruston

unread,
May 11, 2009, 2:31:20 PM5/11/09
to Tiddly...@googlegroups.com
>> +// N.B.: Uses DOM methods instead of jQuery to ensure cross-browser comaptibility.
>
> I though much of the point of libraries like jQuery was to make it so
> you didn't have to ensure cross-browser compatibility?

More background:

TiddlyWiki's implementation of setStylesheet() is an intricate piece of coding that dynamically adds (or removes) a set of stylesheet definitions. Unlike similar functionality in other libraries, the stylesheet is specified in ordinary CSS syntax, and not, say, as a set of name/value pairs.

Getting it working originally (before jQuery was invented) was one of those horribly familiar exercises in cross-browser compatibility. It takes a slightly different approach for IE from other browsers, and the precise sequence of operations turns out to be critical.

One of the basic operations, for example, is to append something to the DOM tree. In ordinary jQuery development, that is encapsulated in the jQuery.append() method. What Fred was getting at was that an observer might expect the stylesheet code to use jQuery.append() where it can to do the appending. It turns out, though, that jQuery does much complex processing behind the scenes for append() than might be expected at first glance. It's not always clear which code path is going to be used in given circumstances. This has implications for the stylesheet code, which, as discussed, is very vulnerable to changes in the sequence of operations.

So, Fred's choice was something like this:

a) Use the existing stylesheet code, which has been tested through use in production for more than three years
b) Reimplement that code using jQuery primitives, and then retest in all those browser/operating system combinations

We selected (a) because it's the more conservative, economical course.

Cheers

Jerm

 

I've discussed this with Jeremy.
Since the CSS rules have to be evaluated after being injected into the
document, browsers are quite peculiar here. That's why we're relying on
the proven (and partially browser-specific) low-level methods for now.

Having said that, I do have a jQuery-fied version of the internals on my
local Git branch, and plan on testing that in various browsers to see
whether it works (would save quite a few LoC).


-- F.





--
Jeremy Ruston
mailto:jer...@osmosoft.com
http://www.tiddlywiki.com
Reply all
Reply to author
Forward
0 new messages