JEP 107 - Page Mods

23 views
Skip to first unread message

Myk Melez

unread,
Feb 15, 2010, 2:18:07 PM2/15/10
to mozilla-la...@googlegroups.com
Hi all,

I recommend some changes to the Page Mods JEP:
  1. The API should be provided by a module named page-mod that provides a CamelCased PageMod constructor function, for consistency with JavaScript convention and the other APIs.

  2. As Erik suggested in an earlier thread, we should delay implementation of dynamic updating of pages when a PageMod is updated to a second phase of development, as it complicates the implementation and raises a number of issues that need to be thought through carefully.

    In the meantime, I don't favor a user preference for whether or not to reload pages. We should instead gather feedback on the use cases for dynamic updating in the initial implementation and implement the most commonly expected behavior.

  3. After construction, instance properties should be modified by directly manipulating the properties instead of via add, remove, and empty methods, for simplicity and consistency with API guidelines.

  4. All properties should accept either a single or a set of values, for consistency with other APIs, and to simplify the common case in which those properties have single values.

  5. As Erik and BlindWanderer noted, property names should have consistent grammatical number. However, I think they should all be singular, which is better aligned with the common case of assigning them a single value.

  6. Both Stylish and Greasemonkey have authors specify style as a string containing multiple CSS declarations rather than a data structure in which the selectors are the keys of an unordered collection (i.e. object).

    This API should do that too, especially since CSS doesn't map well to unordered collections, given that its selectors are supposed to be repeatable, rulesets can be applied to multiple selectors, etc.

  7. It's possible to distinguish between URLs and literals, so it isn't necessary to separate the two into separate properties (includes and style/script). Instead, URLs should be specifiable as values of the style and script properties, just as they are for the content properties of other APIs.

  8. The matches and ignores properties should be renamed to the more conventional include and exclude.

  9. It should be clarified that include/exclude rules match whole URLs rather than just domain names, and the behavior of wildcards in include/exclude rules needs to be carefully specified to reduce the chance of accidental or intentional mismatches. Specifically, the API should require explicit wildcards at the beginnings and ends of rules intended to match anywhere in a page URL.

  10. The include/exclude properties should accept both strings with simple wildcard matching (for simplicity) and regular expressions (for power).

  11. Instances should have a destroy method that destroys the page mod, for consistency with API guidelines.

One effect of these changes is that page mods can be as simple as:
let PageMod = require("page-mod").PageMod;
new PageMod({
  include: "http://evil.com/*",
  style: "body { color: black; background-color: red; }",
  script: function() alert("Danger, Will Robinson!")
});

Thoughts?

-myk

BlindWanderer

unread,
Feb 16, 2010, 4:51:11 AM2/16/10
to mozilla-labs-jetpack
1) Sounds reasonable.
2) I'm going to assume you are referring to having to having a
callback function so the JP can unload itself from the page. I have no
problem with having this shelved.
3) No. Directly manipulating the array of pattern-callback's in JEP 17
was onerous. The user would get a free ride with the constructor/'add'
and after that the would have to do all the work themselves. This is
an unfriendly API. In JEP 17 since the simple matching patters was
being converted into RexExpr, there wasn't even an easy way to figure
out which simple patters matched which pattern-callback pairs.
4) Sounds reasonable.
5) Acceptable - Needs to be properly documented. JEP 17 didn't have
this in the documentation and was a bit of a surprise to find in the
source (on the order of "Why is this here?").
6) Yeah CSS is a bit too complicated to represent unless you actually
use the proper classes; I tried to bolt @font-face into Firebug with
mixed success (I should have done a better job of it).
7) Other api example please? I do not fully understand (maybe it will
make sense in the morning).
8) Sounds reasonable.
9) Good documentation is always a good idea.
10) Agreed.
11) Is there something contentious about this one I should know about?
Code Example) Looks ok.

To give you an idea as to what I want to do here is a crude mockup (my
usecase is a bit hard to explain):

let PageMod = require("page-mod").PageMod;

let Directory = new PageMod({
include: "http://somedirectory.com/*",
script: function(){ /*some code that lets the user select a
website; addWebsite or removeWebsite gets called with the protocol +
domain name*/ }
});
let Websites = new PageMod({
include: null, //start off by loading this into no pages.
script: function(){ /*some cool code that ties all of the
websites together.*/ }
});

function removeWebsite(url){
Websites.remove({include: url + "/*"});
}
function addWebsite(url){
Websites.add({include: url + "/*"});
}

I would really like to read the API Guidelines, if someone can point
me to them...

I really liked how GM executed the script in a sandbox. I prefer the
webpage not know what I'm up to until after I've done it.

BW

On Feb 15, 2:18 pm, Myk Melez <m...@mozilla.org> wrote:
> Hi all,
>
> I recommend some changes to the Page Mods JEP:
>

>    1. The API should be provided by a module named page-mod that


>       provides a CamelCased PageMod constructor function, for
>       consistency with JavaScript convention and the other APIs.
>

>    2. As Erik suggested in an earlier thread, we should delay


>       implementation of dynamic updating of pages when a PageMod is
>       updated to a second phase of development, as it complicates the
>       implementation and raises a number of issues that need to be
>       thought through carefully.
>
>       In the meantime, I don't favor a user preference for whether or
>       not to reload pages. We should instead gather feedback on the use
>       cases for dynamic updating in the initial implementation and
>       implement the most commonly expected behavior.
>

>    3. After construction, instance properties should be modified by


>       directly manipulating the properties instead of via add, remove,
>       and empty methods, for simplicity and consistency with API guidelines.
>

>    4. All properties should accept either a single or a set of values,


>       for consistency with other APIs, and to simplify the common case
>       in which those properties have single values.
>

>    5. As Erik and BlindWanderer noted, property names should have


>       consistent grammatical number. However, I think they should all be
>       singular, which is better aligned with the common case of
>       assigning them a single value.
>

>    6. Both Stylish and Greasemonkey have authors specify style as a


>       string containing multiple CSS declarations rather than a data
>       structure in which the selectors are the keys of an unordered
>       collection (i.e. object).
>
>       This API should do that too, especially since CSS doesn't map well
>       to unordered collections, given that its selectors are supposed to
>       be repeatable, rulesets can be applied to multiple selectors, etc.
>

>    7. It's possible to distinguish between URLs and literals, so it


>       isn't necessary to separate the two into separate properties
>       (includes and style/script). Instead, URLs should be specifiable
>       as values of the style and script properties, just as they are for
>       the content properties of other APIs.
>

>    8. The matches and ignores properties should be renamed to the more
>       conventional include and exclude.
>
>    9. It should be clarified that include/exclude rules match whole URLs


>       rather than just domain names, and the behavior of wildcards in
>       include/exclude rules needs to be carefully specified to reduce
>       the chance of accidental or intentional mismatches. Specifically,
>       the API should require explicit wildcards at the beginnings and
>       ends of rules intended to match anywhere in a page URL.
>

>   10. The include/exclude properties should accept both strings with


>       simple wildcard matching (for simplicity) and regular expressions
>       (for power).
>

>   11. Instances should have a destroy method that destroys the page mod,

BlindWanderer

unread,
Feb 16, 2010, 12:56:59 PM2/16/10
to mozilla-labs-jetpack
Ok, sleep did help.

7. I think it's a good idea but I have reservations. Having parameters
inside and outside the object is going to be confusing to users; so
lets keep things consistent (as you suggest). However I do want to say
that instead of hacking named parameters into the language in such an
ugly fashion, we should be lobbying for named parameters. The
advantage of using proper parameters is that you can look at the
method signature and have a good idea about how to call the function;
you don't get that with this hack. And if Javascript does get named
parameters, people will complain about API's like this. Looking at it
from another angle, there are entire schools of thought that say
optional parameters shouldn't be in the constructor, we are most
definitely violating that ideal. Considering it would be years before
we could use named parameters and this simplifies construction, I
don't think we have any other choice.

BW

On Feb 15, 2:18 pm, Myk Melez <m...@mozilla.org> wrote:

> Hi all,
>
> I recommend some changes to the Page Mods JEP:
>

>    1. The API should be provided by a module named page-mod that


>       provides a CamelCased PageMod constructor function, for
>       consistency with JavaScript convention and the other APIs.
>

>    2. As Erik suggested in an earlier thread, we should delay


>       implementation of dynamic updating of pages when a PageMod is
>       updated to a second phase of development, as it complicates the
>       implementation and raises a number of issues that need to be
>       thought through carefully.
>
>       In the meantime, I don't favor a user preference for whether or
>       not to reload pages. We should instead gather feedback on the use
>       cases for dynamic updating in the initial implementation and
>       implement the most commonly expected behavior.
>

>    3. After construction, instance properties should be modified by


>       directly manipulating the properties instead of via add, remove,
>       and empty methods, for simplicity and consistency with API guidelines.
>

>    4. All properties should accept either a single or a set of values,


>       for consistency with other APIs, and to simplify the common case
>       in which those properties have single values.
>

>    5. As Erik and BlindWanderer noted, property names should have


>       consistent grammatical number. However, I think they should all be
>       singular, which is better aligned with the common case of
>       assigning them a single value.
>

>    6. Both Stylish and Greasemonkey have authors specify style as a


>       string containing multiple CSS declarations rather than a data
>       structure in which the selectors are the keys of an unordered
>       collection (i.e. object).
>
>       This API should do that too, especially since CSS doesn't map well
>       to unordered collections, given that its selectors are supposed to
>       be repeatable, rulesets can be applied to multiple selectors, etc.
>

>    7. It's possible to distinguish between URLs and literals, so it


>       isn't necessary to separate the two into separate properties
>       (includes and style/script). Instead, URLs should be specifiable
>       as values of the style and script properties, just as they are for
>       the content properties of other APIs.
>

>    8. The matches and ignores properties should be renamed to the more
>       conventional include and exclude.
>
>    9. It should be clarified that include/exclude rules match whole URLs


>       rather than just domain names, and the behavior of wildcards in
>       include/exclude rules needs to be carefully specified to reduce
>       the chance of accidental or intentional mismatches. Specifically,
>       the API should require explicit wildcards at the beginnings and
>       ends of rules intended to match anywhere in a page URL.
>

>   10. The include/exclude properties should accept both strings with


>       simple wildcard matching (for simplicity) and regular expressions
>       (for power).
>

>   11. Instances should have a destroy method that destroys the page mod,

Myk Melez

unread,
Feb 17, 2010, 6:48:24 PM2/17/10
to mozilla-la...@googlegroups.com, BlindWanderer, Daniel Buchner
On 02/16/2010 01:51 AM, BlindWanderer wrote:
3) No. Directly manipulating the array of pattern-callback's in JEP 17
was onerous. The user would get a free ride with the constructor/'add'
and after that the would have to do all the work themselves. This is
an unfriendly API. In JEP 17 since the simple matching patters was
being converted into RexExpr, there wasn't even an easy way to figure
out which simple patters matched which pattern-callback pairs.
  
Points well taken!

I'd still like it to be possible to assign new values to these properties directly, since that is the simplest possible interface for the common case where the properties only have single values (or multiple values that don't need to be independently managed).

However, for the case where properties have multiple values that need to be independently managed, I suggest we use the same design pattern we use for callback properties, which is to support add/remove methods of each property that add and remove members of the set of values for the property:

let PageMod = require("page-mod").PageMod;
let mod = new PageMod({

include: "http://evil.com/*",
style: "body { color: black; background-color: red; }",
script: function() alert("Danger, Will Robinson!")
});

mod.include.add(["http://eviler.com/*", "http://evilest.com/*"]);
mod.include.remove("http://evil.com/*");

When removing values, the values passed to the remove method would be compared to the set of existing values using strict equality, per Javascript's comparison operators reference, which behaves differently for primitive values than it does for objects but in ways that are reasonable and expectable. Some examples:

// This works (the strings are primitive values).
mod.style.add("body { color: black; background-color: red; }");
mod.style.remove("body { color: black; background-color: red; }");

// This works too (both variables refer to the same object).
let foo = function() alert("Danger, Will Robinson!");
mod.script.add(foo);
let bar = foo;
mod.script.remove(bar);

// This doesn't work (the two functions aren't the same object).
mod.script.add(function() alert("Danger, Will Robinson!"));
mod.script.remove(function() alert("Danger, Will Robinson!"));

5) Acceptable - Needs to be properly documented. JEP 17 didn't have
this in the documentation and was a bit of a surprise to find in the
source (on the order of "Why is this here?").
  
Yes, we should definitely document this for the properties that support it!


7) Other api example please? I do not fully understand (maybe it will
make sense in the morning).
  
Here's a page mod that adds both an external stylesheet and a style literal:

let mod = new PageMod({
  include: "http://some-site.example.com/*",
  style:   ["http://my-site.example.com/style.css",
            "body { color: black; }"]
});


Note also my proposal elsewhere in this discussion forum that we be more explicit when setting such properties to URLs.


11) Is there something contentious about this one I should know about?
  
Hmm, I don't think so. There might be some details to work out.


Code Example) Looks ok.

To give you an idea as to what I want to do here is a crude mockup (my
usecase is a bit hard to explain):
  
This seems doable (although there might be some security implications of having injected script call extension functions that we'll need to work though), and it should be supported by the property-specific add/remove syntax I describe above.


I would really like to read the API Guidelines, if someone can point
me to them...
  
They're on this page of the wiki:

https://wiki.mozilla.org/Labs/Jetpack/Design_Guidelines

Feedback on them is welcome!


I really liked how GM executed the script in a sandbox. I prefer the
webpage not know what I'm up to until after I've done it.
  
Yes, that's a good point. The sandbox approach is also safer, I think, and we should consider doing it instead. cc:ing Daniel to make sure he sees this.

Daniel: what's the motivation for injecting script directly into the page rather than into a sandbox that has access to the page, as Greasemonkey does it?

-myk

Myk Melez

unread,
Feb 17, 2010, 6:57:34 PM2/17/10
to mozilla-la...@googlegroups.com, BlindWanderer
On 02/16/2010 09:56 AM, BlindWanderer wrote:
However I do want to say
that instead of hacking named parameters into the language in such an
ugly fashion, we should be lobbying for named parameters.
I did just that a few years back, and my memory about it is fuzzy now, but I think Javascript developers were skeptical, and I recall one of them telling me that such proposals haven't been successful in ECMAScript standardization procedures.

In any case, absent native support, JS libraries have adopted property collection parameters in many cases, and they work pretty well.

The advantage of using proper parameters is that you can look at the
method signature and have a good idea about how to call the function;
you don't get that with this hack.
Aza has been using a JSDoc extension to document the properties that can get passed in a property collection, an example of which is available in the Single UI Element JEP. We should at least use something like this (along with a JSDoc extension to label optional properties) to document such functions.

-myk

BlindWanderer

unread,
Feb 18, 2010, 3:19:53 AM2/18/10
to mozilla-labs-jetpack
Wow. Thank you for taking the time to respond. Your comments have
cleared up most (if not all) of my concerns.

On Feb 17, 6:48 pm, Myk Melez <m...@mozilla.org> wrote:
>     // This doesn't work (the two functions aren't the same object).
>     mod.script.add(function() alert("Danger, Will Robinson!"));
>     mod.script.remove(function() alert("Danger, Will Robinson!"));

No worries, I wouldn't expect that to work. Besides being a beast to
code, I'm pretty sure I know the other reasons it's a bad idea to
support it: 1) Huge performance hit 2) easy for the user to sabotage
the comparison (just one mismatched variable in the scope chain).

> > 5) Acceptable - Needs to be properly documented. JEP 17 didn't have
> > this in the documentation and was a bit of a surprise to find in the
> > source (on the order of "Why is this here?").
>
> Yes, we should definitely document this for the properties that support it!
>

You mention JSDoc in your next email. The example you give with JEP
102 looks excellent.

> > I would really like to read the API Guidelines, if someone can point
> > me to them...
>
> They're on this page of the wiki:
>
> https://wiki.mozilla.org/Labs/Jetpack/Design_Guidelines
>

*cough* I feel a bit stupid.

> > I really liked how GM executed the script in a sandbox. I prefer the
> > webpage not know what I'm up to until after I've done it.
>
> Yes, that's a good point. The sandbox approach is also safer, I think,
> and we should consider doing it instead. cc:ing Daniel to make sure he
> sees this.
>
> Daniel: what's the motivation for injecting script directly into the
> page rather than into a sandbox that has access to the page, as
> Greasemonkey does it?

From personal experience there have been a couple times with GM
scripts where I have wanted to inject scripts into the document. I
must admit, it's pretty rare when I want to inject code into the
webpage.
Maybe we need both injectable scripts and sandboxed scripts.

Considering how useful both might be, maybe they should be separate
JEP's that 107 depends upon.

One last thought that just popped into my sleepy head.
How is Jetpack going to handle frames? If memory serves me, parents
can't access with javascript child frames that aren't in the same
domain (XSS protection). If a child frame doesn't match the domain of
the parent, will Jetpack be able to access the child? GM solves this
problem by treating tabs and frames are equal: as targets. This should
probably get it's own thread.

BW

Erik Vold

unread,
Feb 19, 2010, 2:12:15 AM2/19/10
to mozilla-labs-jetpack

>    1. The API should be provided by a module named page-mod that

>       provides a CamelCased PageMod constructor function, for
>       consistency with JavaScript convention and the other APIs.

yes

>    2. As Erik suggested in an earlier thread, we should delay


>       implementation of dynamic updating of pages when a PageMod is
>       updated to a second phase of development, as it complicates the
>       implementation and raises a number of issues that need to be
>       thought through carefully.
>
>       In the meantime, I don't favor a user preference for whether or
>       not to reload pages. We should instead gather feedback on the use
>       cases for dynamic updating in the initial implementation and
>       implement the most commonly expected behavior.

I agree

>    3. After construction, instance properties should be modified by


>       directly manipulating the properties instead of via add, remove,
>       and empty methods, for simplicity and consistency with API guidelines.

I agree

>    4. All properties should accept either a single or a set of values,


>       for consistency with other APIs, and to simplify the common case
>       in which those properties have single values.

yes

>    5. As Erik and BlindWanderer noted, property names should have


>       consistent grammatical number. However, I think they should all be
>       singular, which is better aligned with the common case of
>       assigning them a single value.

how about using 'js' and 'css' instead of 'script' and 'style'? 'js'
and 'css' have the nice property of being both singular and plural,
and it is what is used for Google Chrome extensions' content script's
manifest file which is similar to page mods. After all, it's not like
XSL would be valid input for 'style', but might be something worth
adding, way later on.

>    6. Both Stylish and Greasemonkey have authors specify style as a


>       string containing multiple CSS declarations rather than a data
>       structure in which the selectors are the keys of an unordered
>       collection (i.e. object).
>
>       This API should do that too, especially since CSS doesn't map well
>       to unordered collections, given that its selectors are supposed to
>       be repeatable, rulesets can be applied to multiple selectors, etc.

yes

>    7. It's possible to distinguish between URLs and literals, so it


>       isn't necessary to separate the two into separate properties
>       (includes and style/script). Instead, URLs should be specifiable
>       as values of the style and script properties, just as they are for
>       the content properties of other APIs.

yes

>    8. The matches and ignores properties should be renamed to the more
>       conventional include and exclude.
>
>    9. It should be clarified that include/exclude rules match whole URLs


>       rather than just domain names, and the behavior of wildcards in
>       include/exclude rules needs to be carefully specified to reduce
>       the chance of accidental or intentional mismatches. Specifically,
>       the API should require explicit wildcards at the beginnings and
>       ends of rules intended to match anywhere in a page URL.
>

>   10. The include/exclude properties should accept both strings with


>       simple wildcard matching (for simplicity) and regular expressions
>       (for power).

This sounds good to me; it looked to me like jetpack page mods were
following the path Google Chrome user scripts laid down w/ @match, but
I never liked this. The reason @match was created, afaik, was so that
the domains the user script runs on could be determined, and presented
to the end user. I've described what I think to be a decent solution
for this issue, should it ever arise, here:
http://github.com/greasemonkey/greasemonkey/issues#issue/1016

>   11. Instances should have a destroy method that destroys the page mod,


>       for consistency with API guidelines.

yes

E

Daniel

unread,
Feb 19, 2010, 2:35:23 PM2/19/10
to mozilla-labs-jetpack
In relation to the following:

let mod = new PageMod({
include: "http://some-site.example.com/*",
style: ["http://my-site.example.com/style.css", "body { color:
black; }"]
});

Though we certainly CAN distinguish and parse URLs and directly
applied styles, as the reference suggests, I believe this will
degrades the readability and expressiveness of the code.

Additionally, if we do support the future enhancement of being able to
remove styles on a per property basis, I would think we will be
parsing such values including them in a look-up hash anyway. If that
is the case, this is essentially a "friendly to some, but alien to
others" ergonomic issue. Why not apply single styles in object format
and leave it up to folks to wrap that implementation with another
level of string parse abstraction if they please?

Further, even if we patterned our API after jQuery, jQuery 1.4
recently followed in the best-practice footsteps of frameworks such as
Mootools and Prototype by enabling multi-event additions and element
creation/prop additions via an object structure:
http://ryanflorence.com/jquery-1-4-mootools-1-2-compared/ I say we
stay neutral of mandating a top-level abstraction here by going with
the object method (which likely will be required anyway for
implementation of the feature) and letting devs sprinkle further sugar
if they want to make really large arrays composed of long
strings...just my 3 cents ;)

- Daniel

Daniel

unread,
Feb 19, 2010, 2:46:51 PM2/19/10
to mozilla-labs-jetpack
So this is what code could start looking like:

let mod = new PageMod({

include: "http://some-site.example.com/*",

style: ["http://my-site.example.com/style.css", "body
{ color:

black; } div.result_left { width: 20%; left: -24px; } div.result_left
img { width: 100%; } div.result_center { width: 65%; left: -18px; }
div.result_center dl dt { font-size: 1.4em; font-weight: bold; }
div.result_center dl dd { font-size: 0.8em; } div.result_right
{ width: 15%; left: -12px; } div.result_score { font-weight: bold; }
div.result_score span { font-size: 1.4em; } div.result_score span span
{ font-size: 0.8em; }"]

});

Or if the intent of the example was that each selector addition was to
have its own array item:

let mod = new PageMod({

include: "http://some-site.example.com/*",

style: ["http://my-site.example.com/style.css", "body
{ color:

black; }", "div.result_left { width: 20%; left: -24px; }",
"div.result_left img { width: 100%; }", "div.result_center { width:
65%; left: -18px; }", "div.result_center dl dt { font-size: 1.4em;
font-weight: bold; }", "div.result_center dl dd { font-size:
0.8em; }", "div.result_right { width: 15%; left: -12px; }",
"div.result_score { font-weight: bold; }", "div.result_score span
{ font-size: 1.4em; }", "div.result_score span span { font-size:
0.8em; }"]

});

Either expression forces programmatic application of properties to use
a plethora of '+' and would likely make me cry if I had to be the
second developer to ever read it - an important thing for code that
will be included in a hyper-collaborative development environment such
as FlightDeck...ok, so that's my 4 cents!

Let me know what your thoughts are on this.

- Daniel

Erik Vold

unread,
Feb 19, 2010, 6:36:21 PM2/19/10
to mozilla-labs-jetpack

> Though we certainly CAN distinguish and parse URLs and directly
> applied styles, as the reference suggests, I believe this will
> degrades the readability and expressiveness of the code.

I don't think it degrades readability or expressiveness, it's the kind
of css I'm used to reading and writing.

> Additionally, if we do support the future enhancement of being able to
> remove styles on a per property basis, I would think we will be
> parsing such values including them in a look-up hash anyway.  If that
> is the case, this is essentially a "friendly to some, but alien to
> others" ergonomic issue.  Why not apply single styles in object format
> and leave it up to folks to wrap that implementation with another
> level of string parse abstraction if they please?

I'm thinking that the mod.css property should think in css blobs and
not individual rules+properties, in which case a mod.css.add(cssBlob)
and mod.css.remove(cssBlob) just think in terms of css blobs, where a
cssBlob can be a large css string or a url to a css file. If this is
the case then creating a module/object providing the granular support
to manipulate the cssBlobs which are feed to the Page Mod would be a
piece of cake to create and use, if desired. This method seems like it
will provide the best performance and be the easiest for web devs to
understand, because it is how they have to work on the web at the
moment.

Also, I think the mod.css.remove() method will only need to be a used
in edge cases, because css should define a default state and
alternative states via classes, then elements are moved from state to
state via js. If a developer is manipulating css via js, I'm assuming
to dynamically alter the default state, that would make the code
harder to read imo.

Erik

Daniel

unread,
Feb 19, 2010, 7:34:10 PM2/19/10
to mozilla-labs-jetpack
Perhaps it is easier for some who use this PageMods JS API to think of
adding stringy css blobs while others (bias: I am one) feel more
comfortable thinking of it in the JS sense, properties > values. My
point is this - to most easily create a removal ability, and most
clear way to do so is to track css property additions to selectors in
a JS object hash. That said, to parse these blobs, you'd need to add
a layer of needless complexity by RegEx-ing strings into just the type
of objects you dislike.

I would also submit for consideration that the way you do JS additions
to styles is as follows: document.body.style.someProp - an object no
less! Since this is a JS API, why should we provide a further
abstraction layer on top that is not native to how JS handles styles
and that only a segment of devs agree with?

My point is not that you should love adding CSS with an object, but
that it IS the base no matter what, so why not just write the CSS
RegEx-to-object converter yourself and wrap the PageMods API to add
such an abstraction layer. This is the specific purpose of the new
reboot, to allow these very kinds of augmentations to be done by
developers :)

- Daniel

Jeff Balogh

unread,
Feb 19, 2010, 7:49:18 PM2/19/10
to mozilla-la...@googlegroups.com
On Fri, Feb 19, 2010 at 4:34 PM, Daniel <dani...@gmail.com> wrote:
> Perhaps it is easier for some who use this PageMods JS API to think of
> adding stringy css blobs while others (bias: I am one) feel more
> comfortable thinking of it in the JS sense, properties > values.  My
> point is this - to most easily create a removal ability, and most
> clear way to do so is to track css property additions to selectors in
> a JS object hash.  That said, to parse these blobs, you'd need to add
> a layer of needless complexity by RegEx-ing strings into just the type
> of objects you dislike.

Why would you want to parse blobs and remove bits of CSS? If I want
to remove some style, I'll override it with my cascading style sheets.
If I'm changing a style, I'll reload the page or do something in js.

> I would also submit for consideration that the way you do JS additions
> to styles is as follows: document.body.style.someProp - an object no
> less!  Since this is a JS API, why should we provide a further
> abstraction layer on top that is not native to how JS handles styles
> and that only a segment of devs agree with?

Your link above: http://ryanflorence.com/jquery-1-4-mootools-1-2-compared/

If you look at that page, you'll see that the jquery/mootools code is
creating/fetching an object and then applying some style *to that
object*. The property-based css feels natural there, because you're
writing js code.

But the pageMods API in question is adding style *to a page*, not an
object. The normal way of styling a page is with cascading style
sheets.

> My point is not that you should love adding CSS with an object, but
> that it IS the base no matter what, so why not just write the CSS
> RegEx-to-object converter yourself and wrap the PageMods API to add
> such an abstraction layer.

But isn't jetpack about using HTML and CSS and js in a way that feels
natural to web developers?

Daniel

unread,
Feb 19, 2010, 7:52:28 PM2/19/10
to mozilla-labs-jetpack
Here is that same code done in an object style - I think it is really
hard to claim that it is more readable as a giant string, but again
this could just be my opinion:

let mod = new PageMod({

include: "http://some-site.example.com/*",

style: {
body: {
color: 'black'
}
div.result_left: {
width: '20%',


left: '-24px'
}
'div.result_left img': {
width: '100%'
}
div.result_center: {

width: '65%',


left: '-18px'
}
'div.result_center dl dt': {

font-size: '1.4em',


font-weight: 'bold'
}
'div.result_center dl dd' {
font-size: '0.8em'
}
div.result_right {

width: '15%',


left: '-12px'
}
div.result_score: {
font-weight: 'bold'
}
'div.result_score span:' {
font-size: '1.4em'
}
'div.result_score span span': {
font-size: '0.8em'
}

});

Daniel

unread,
Feb 19, 2010, 7:56:10 PM2/19/10
to mozilla-labs-jetpack
So I forgot the object ending commas and a curly brace, sue me! :)

let mod = new PageMod({

include: "http://some-site.example.com/*",

style: {
body: {
color: 'black'
},


div.result_left: {
width: '20%',
left: '-24px'

},
'div.result_left img': {
width: '100%'
},

div.result_center: {
width: '65%',
left: '-18px'

},


'div.result_center dl dt': {
font-size: '1.4em',
font-weight: 'bold'

},


'div.result_center dl dd' {
font-size: '0.8em'

},


div.result_right {
width: '15%',
left: '-12px'

},
div.result_score: {
font-weight: 'bold'
},
'div.result_score span:' {
font-size: '1.4em'
},

'div.result_score span span': {
font-size: '0.8em'
}
}

});

Christoph Dorn

unread,
Feb 19, 2010, 8:30:14 PM2/19/10
to mozilla-la...@googlegroups.com
I have not been following this thread in detail but wanted to leave my
comments.

I like the JSON notation for CSS below as it makes writing tools on top
a bit easier however I am not sure it will hold up.

The notation below leaves out some important CSS features like multiple
comma separated selectors for the same rule. It also stops short from
objectifying the entire CSS syntax (e.g. spaces in property names).

If JSON-based CSS rules are desired I believe one must devise a complete
schema that can accommodate all of the CSS syntax in a proper object
graph. The end result will likely be a JSON structure you will not want
to edit by hand but one could then provide some converters that take
more simple JSON structures (with a defined subset of CSS features as
presented below).

The CSS syntax is a domain language that has evolved to express certain
types of features in as brief and intuitive manner as possible. Any
attempt to provide a more convenient syntax will fail if it is not
derived from an academic perspective that addresses the entire CSS
syntax as its foundation and will accommodate future additions.

My 2 cents.

Christoph

Daniel

unread,
Feb 19, 2010, 8:38:58 PM2/19/10
to mozilla-labs-jetpack
Hmm not sure what you mean, I think your examples would in fact be
covered if I understand you right, consider the following:

'#someID, div.someClass, ul' {
margin: '10px auto 20px'
}

I believe the things you stated are completely supported ;)

- Daniel

On Feb 19, 5:30 pm, Christoph Dorn <christoph...@christophdorn.com>
wrote:

johnjbarton

unread,
Feb 19, 2010, 8:40:38 PM2/19/10
to mozilla-labs-jetpack

On Feb 19, 5:30 pm, Christoph Dorn <christoph...@christophdorn.com>
wrote:

> I have not been following this thread in detail but wanted to leave my
> comments.
>
> I like the JSON notation for CSS below as it makes writing tools on top
> a bit easier however I am not sure it will hold up.
>
> The notation below leaves out some important CSS features like multiple
> comma separated selectors for the same rule. It also stops short from
> objectifying the entire CSS syntax (e.g. spaces in property names).
>
> If JSON-based CSS rules are desired I believe one must devise a complete
> schema that can accommodate all of the CSS syntax in a proper object
> graph. The end result will likely be a JSON structure you will not want
> to edit by hand but one could then provide some converters that take
> more simple JSON structures (with a defined subset of CSS features as
> presented below).
>
> The CSS syntax is a domain language that has evolved to express certain
> types of features in as brief and intuitive manner as possible. Any
> attempt to provide a more convenient syntax will fail if it is not
> derived from an academic perspective that addresses the entire CSS
> syntax as its foundation and will accommodate future additions.

Plus implementing, documenting, testing, educating, and maintaining a
completely new CSS syntax is a significant responsibility. Is someone
really signing up to do that?

jjb

Daniel

unread,
Feb 19, 2010, 8:52:24 PM2/19/10
to mozilla-labs-jetpack
I am really not sure how this turned into a new syntax...

Here is what css looks like in a css file:

#someID, div.someClass, ul {
margin: 10px auto 20px;
}

And as an object:

'#someID, div.someClass, ul': {
margin: '10px auto 20px'
}

I can sum up the docs for us in one sentence: Add quotes around your
CSS selectors and the values of your CSS properties, then add a colon
after your selector. Pretty simple stuff guys, I mean I just showed
the CSS declaration example above, it is an object in structure
anyway... Am I taking crazy pills here?

- Daniel

Christoph Dorn

unread,
Feb 19, 2010, 8:46:49 PM2/19/10
to mozilla-la...@googlegroups.com
I guess I don't understand the objective of the alternate syntax.

Is it just to be able to put CSS rules into a JSON structure?

If that is the case what you have should work I guess, but I see the
property names getting very long and hard to parse visually especially
because you cannot break them into multiple lines.

Christoph

Drew

unread,
Feb 19, 2010, 8:59:16 PM2/19/10
to mozilla-la...@googlegroups.com
Setting aside other criticisms, you haven't addressed a major one that
Myk pointed out:

> 6. Both Stylish and Greasemonkey have authors specify style as a
> string containing multiple CSS declarations rather than a data
> structure in which the selectors are the keys of an unordered
> collection (i.e. object).
>
> This API should do that too, especially since CSS doesn't map well
> to unordered collections, given that its selectors are supposed to
> be repeatable, rulesets can be applied to multiple selectors, etc.

IMO, if I'm new to Jetpack and looking to mod a page with CSS, all I'd
want is to be able to write my CSS in a separate file like I normally do
and then have an easy glue to apply it to my pages.

Drew

Daniel

unread,
Feb 19, 2010, 9:13:20 PM2/19/10
to mozilla-labs-jetpack
So the longest CSS property name I can think of off the top of my head
is this: -moz-border-radius-bottomright - the mozilla specific
border radius property.

More apropos to the discussion of "hard to visually parse" is this:

One gigantic string - PROs: hmm, allows developers to copy and paste
massive sections of css into a call... CONs: WAYYY harder to read
whether you have wrapping turned on or not

"body{ color: black; } div.result_left { width: 20%; left:


-24px; } div.result_left img { width: 100%; } div.result_center

{ width: 65%; left: -18px; } div.result_center dl dt { font-size:
1.4em; font-weight: bold; }"

CSS Objects - PROs: easy to read, structured, promotes good coding
practices, has to end up in an object to track changes on the
instance, we are using a JS API - I think using JSON as the vector is
more than appropriate, and lastly easier to debug and write catches
for (RegEx fails anyone? have fun!) CONs: Takes slightly more effort
than just copy and pasting from a stylesheet...

body: {
color: 'black'
},
div.result_left: {
width: '20%',
left: '-24px'
},
'div.result_left img': {
width: '100%'
},
div.result_center: {
width: '65%',
left: '-18px'
},
'div.result_center dl dt': {
font-size: '1.4em',
font-weight: 'bold'
}

I don't mean to be too persistent here, but this is a better practice
than just pasting in giant html/css strings that will leave those who
review and inherit your code with a commingled spaghetti of a mess -
of course some of this is opinion, but I think a well informed opinion
- I digress... :(

- Daniel

On Feb 19, 5:46 pm, Christoph Dorn <christoph...@christophdorn.com>

Erik Vold

unread,
Feb 19, 2010, 9:49:28 PM2/19/10
to mozilla-labs-jetpack
I think we all agree on your point Drew, although I think you are
referring more to Myk's 7th point than his 6th point.

E

Drew

unread,
Feb 19, 2010, 9:55:15 PM2/19/10
to mozilla-la...@googlegroups.com
Sorry, should have been clearer. Myk's 6th point is about the fact that
objects are unordered sets and therefore unsuitable for CSS rules.
(Unless you stuff them in arrays, but that approaches
obviously-worse-than-strings territory.) Which syntax is more ergonomic
-- strings or JSON-like objects -- is irrelevant.

The "IMO" part was my general impression of page mods and applying styles.

Drew

Erik Vold

unread,
Feb 19, 2010, 10:50:24 PM2/19/10
to mozilla-labs-jetpack
Ah yes, I did forget about that point, but you can just stuff css
rules in to an object literal which in turn goes into an array, rather
than a object, like you say. Then we are back to where were though..
although referring to a JSON-like object of css object literal was
incorrect, should be an array of JSON-like objects..

E

Erik Vold

unread,
Feb 19, 2010, 10:59:57 PM2/19/10
to mozilla-labs-jetpack
This is a good point.

This JSON-like syntax needs to accommodate things like @media,
@namespace, @variables, and @import and be able to handle whatever
else new css specifications throw at it in the future.. which I think
it might be able to do, but more thought needs to be put into it as it
stands now, and it would be a pain in the arse to have to update this
syntax.

E

On Feb 19, 5:30 pm, Christoph Dorn <christoph...@christophdorn.com>
wrote:

Christoph Dorn

unread,
Feb 19, 2010, 11:25:49 PM2/19/10
to mozilla-la...@googlegroups.com
I am referring to the selector [javascript/json] property, not the CSS
property property :)

Take a look at: chrome://browser/skin/browser.css

How are you going to accommodate:

toolbarbutton.bookmark-item[container]:hover:active > .toolbarbutton-text,
toolbarbutton.bookmark-item[container][open="true"] > .toolbarbutton-text,
#home-button.bookmark-item:hover:active > .toolbarbutton-icon,
toolbarbutton.bookmark-item[container][chromedir="rtl"]:hover:active >
.toolbarbutton-menu-dropmarker,
toolbarbutton.bookmark-item[container][chromedir="rtl"][open="true"] >
.toolbarbutton-menu-dropmarker,
#home-button.bookmark-item:hover:active[chromedir="rtl"] >
.toolbarbutton-text {
background: url("chrome://browser/skin/bookmark-open-mid.png")
repeat-x !important;
}


I realize that such a complex selector may not ever be needed for a web
page, but it is valid CSS.

Again, I am not sure of the motivations of "Page Mods" but from
experience implementing API features such as the one being proposed
needs very careful consideration. Once it is live it is very difficult
to remove.

I would simply link to a CSS file. That way you get the benefit of
caching etc... and it is what people are used to. No education required
whatsoever. Once this is live and you can see how people use it you can
propose an alternate shortcut if appropriate.

Christoph

Daniel

unread,
Feb 20, 2010, 12:42:09 PM2/20/10
to mozilla-labs-jetpack
Ok, so I thought about it more and there is a pretty easy way to allow
for removal of singular styles using giant strings that can be
implemented w/o an object structure at any point in the chain. If the
feeling of the community is strongly in favor of going the array-o-
strings or array-o-largeStrings route then that is more important. In
the end it is very important developers like the APIs and find them
easy to use :)

- Daniel

Myk Melez

unread,
Feb 20, 2010, 4:46:53 PM2/20/10
to mozilla-la...@googlegroups.com
On 02/18/2010 12:19 AM, BlindWanderer wrote:
> From personal experience there have been a couple times with GM
> scripts where I have wanted to inject scripts into the document. I
> must admit, it's pretty rare when I want to inject code into the
> webpage.
> Maybe we need both injectable scripts and sandboxed scripts.
>
Since the sandbox has access to the document, I'm more inclined to have
the page mod manually inject scripts at this point, although if it turns
out to be a common enough pattern, we can consider making it easier to do.

> How is Jetpack going to handle frames? If memory serves me, parents
> can't access with javascript child frames that aren't in the same
> domain (XSS protection). If a child frame doesn't match the domain of
> the parent, will Jetpack be able to access the child? GM solves this
> problem by treating tabs and frames are equal: as targets. This should
> probably get it's own thread.
>

Initially, the page mod will have access to child frames, although
ultimately I think we'll implement a security model that allows
extensions to specify the domains they intend to access and restricts
page mods (and other APIs) to just those domains.

-myk

Myk Melez

unread,
Feb 20, 2010, 5:50:10 PM2/20/10
to mozilla-la...@googlegroups.com
On 02/18/2010 11:12 PM, Erik Vold wrote:
> how about using 'js' and 'css' instead of 'script' and 'style'?
Hmm, js and css are certainly reasonable names, but I think script and
style are preferable, since they are analogous to the tags with which
one inserts such code into web pages (and, to a lesser degree, because
they are not acronyms, which, like abbreviations vis-�-vis
non-abbreviated words and phrases vis-�-vis their single-word
equivalents, are IMHO slightly less readable and memorable).

> This sounds good to me; it looked to me like jetpack page mods were
> following the path Google Chrome user scripts laid down w/ @match, but
> I never liked this. The reason @match was created, afaik, was so that
> the domains the user script runs on could be determined, and presented
> to the end user. I've described what I think to be a decent solution
> for this issue, should it ever arise, here:
> http://github.com/greasemonkey/greasemonkey/issues#issue/1016
>

We definitely share Google Chrome's goal of being able to inform users
about the domains/pages to which extensions are requesting access. And
it's possible that would cause us to change this syntax in the future.

However, it's also possible (and I find it likelier) that the access
specification will be a layer above this API that then applies to all
Jetpack APIs (page mods, XHR, etc.).

For example, it might be a property in the extension manifest that
specifies its access characteristics, which a page mod's include
property can then refine if the pages it wants to modify are a subset of
all pages to which it has access (and otherwise it can simply specify "*").

-myk

Myk Melez

unread,
Feb 20, 2010, 7:35:08 PM2/20/10
to mozilla-la...@googlegroups.com
On 02/19/2010 11:35 AM, Daniel wrote:
> Further, even if we patterned our API after jQuery, jQuery 1.4
> recently followed in the best-practice footsteps of frameworks such as
> Mootools and Prototype by enabling multi-event additions and element
> creation/prop additions via an object structure:
> http://ryanflorence.com/jquery-1-4-mootools-1-2-compared/
The interface the JEP proposes is not the one jQuery and MooTools
implement in that blog post.

The post demonstrates jQuery and MooTools APIs for adding style rules to
individual elements via a property collection (i.e. object) whose names
represent individual CSS properties. This is a reasonable and
appropriate use of a property collection, since CSS properties are
simple strings and can have only one value.

The JEP, by contrast, proposes adding stylesheet statements to an entire
page via a property collection whose names represent CSS selectors. This
is a problematic use of a property collection, since CSS selectors can
be complex strings and have multiple values.

I can find no MooTools or jQuery interface that specifies stylesheet
statements using a property collection whose names are CSS selectors.
And note that neither interface provides a method for removing style
rules that were added via the API, they only allow you to set CSS
properties to new values.


On 02/19/2010 04:34 PM, Daniel wrote:
> I would also submit for consideration that the way you do JS additions
> to styles is as follows: document.body.style.someProp - an object no
> less!

This is another example of a property collection being used to provide
access to the set of simple, non-repeating CSS properties as opposed to
a collection of potentially complex and repeating CSS selectors.

> Perhaps it is easier for some who use this PageMods JS API to think of
> adding stringy css blobs while others (bias: I am one) feel more
> comfortable thinking of it in the JS sense, properties> values. My
> point is this - to most easily create a removal ability, and most
> clear way to do so is to track css property additions to selectors in
> a JS object hash.

This is certainly a valid goal! The questions are just how important it
is, how best to go about achieving it, and the various tradeoffs involved.

If dynamic manipulation of the style property is the best way for page
modders to make dynamic style changes, then I could imagine an interface
in which the values of the style property could be named and thus
removed or updated by name.

But the specification of static style and the dynamic modification of
style feel like different use cases. And given the popularity of
interfaces for dynamically modifying styles that are provided by
libraries like jQuery and MooTools, it seems likelier for developers to
want to use similar interfaces for dynamic changes, and we should
reserve the style property for relatively static style, with a different
interface (or perhaps access from the sandbox to developers' libraries
of choice) for dynamic updates.


On 02/20/2010 09:42 AM, Daniel wrote:
> Ok, so I thought about it more and there is a pretty easy way to allow
> for removal of singular styles using giant strings that can be
> implemented w/o an object structure at any point in the chain. If the
> feeling of the community is strongly in favor of going the array-o-
> strings or array-o-largeStrings route then that is more important. In
> the end it is very important developers like the APIs and find them
> easy to use :)
>

Indeed, although keep in mind that we're currently talking to a small
and particularly savvy segment of the community!

We need to cast the broadest possible net, looking at related
implementations, discussing proposed APIs with the folks here in this
forum, talking to extension and API developers who aren't currently
participating here, and last but not least reasoning on the basis of our
own knowledge and experience, taking into account the big picture goals
and principles of the project.

And then we need to make a decision (and implement it, see how it works,
refine it as needed), even if we don't come to agreement. As the guy
currently driving this API design process, I can do that, although I
would prefer at least rough consensus.

And it sounds like you've come around to accepting the viability of the
approach on the table (in which style can be a single or a set of
non-named values), so I sense that we're there (or close enough). So
let's go with that approach and then revisit after a round of feedback
on the initial implementation.

Thanks everyone for your thorough and trenchant input!

-myk

Daniel

unread,
Feb 25, 2010, 4:33:00 PM2/25/10
to mozilla-labs-jetpack
Just so you can all see what I meant when I suggested there are great
use-cases for removal of CSS, and what is made possible, take a look
at the RAR I just uploaded called "PageMods". Look in the Demo dir >
open the html doc named "Google". You'll notice a button in the lower
left corner of the screen - now click that thang!

- Daniel

Daniel

unread,
Feb 25, 2010, 7:20:59 PM2/25/10
to mozilla-labs-jetpack

Jeff Balogh

unread,
Feb 25, 2010, 7:54:41 PM2/25/10
to mozilla-la...@googlegroups.com
On Thu, Feb 25, 2010 at 4:20 PM, Daniel <dani...@gmail.com> wrote:
> Have it up on the net now: http://people.mozilla.com/~dbuchner/demos/web/PageMods/demo.html

You can put everything in one stylesheet, then change the body class
from "night" to "day".

Daniel

unread,
Feb 25, 2010, 7:58:31 PM2/25/10
to mozilla-labs-jetpack
Ok so the method names here are different, look past that, the point
is that this get's you add/remove/update and it is pretty close to a
common ground:

sheet.addRules({
'body, #fctr, #sbl, #ghead': {
background: '#000000',
color: '#CFCFCF'
},
'a': {
color: '#ffffff'
}
});

OR

sheet.addRules({
"body, #fctr, #sbl, #ghead": "background: #000000; color:
#CFCFCF;",
"a": "color: #ffffff;"
});

OR singularly with addRule

sheet.addRule("body, #fctr, #sbl, #ghead", "background: #000000;
color: #CFCFCF;");

Here are a few add-ons that want style toggling:
https://addons.mozilla.org/en-US/firefox/addon/46442
https://addons.mozilla.org/en-US/firefox/addon/5758
https://addons.mozilla.org/en-US/firefox/addon/8624

The GoogleDark add-on makes you go to > Tools > Add-ons > GoogleDark >
Options > "Turn off styles" - THEN it makes you reload each page that
contains the styles - wow I bet users just love that flow.

With this style of API you can toggle on and off styles and mods like
a champ. It allows for less hackish, reloadish, lameish user-flows.

Thoughts anyone?

- Daniel

Erik Vold

unread,
Feb 25, 2010, 10:14:47 PM2/25/10
to mozilla-labs-jetpack
So that this conversation doesn't get overly complex, let's try to
distill the issue:

Why would one need to remove css rules from a page when they can
simply change the classes on elements?

The separation of css and javascript is always possible as far as I
can tell.. in what use case would it not be possible? If there is a
use case, then the debate is over.

As far as I can tell all of those 3 firefox extensions could separate
css and js and still work w/out requiring page reloads w/ simple best
practices.

This is part of the concept of Unobtrusive JavaScript, or separation
of structure/presentation/behavior:
http://onlinetools.org/articles/unobtrusivejavascript/cssjsseparation.html

I am fine with allowing removal of css blobs / files though obviously,
because some extensions might otherwise add ~MBs+ worth of css blobs
to pages in extreme cases. Once you allow the removal of css blobs, it
is easy to build a module that will allow you to add/remove rules, and
if we don't create a built-in way to do this, the market can decide on
the best module to do the job, or if they even want one.

One way to build a module such as I describe would be to have a
module, let's call it X, which you can pass in individual css rules in
a JSON like syntax. Module X would then provide add() and remove()
methods, and when you add or remove you are returned 2 css blobs, the
old css blob and the new one. Then you simply need to add the new css
blob and remove the old one, in that order.

For another example: module Y could add the css rules in individual
style tags, and when you want to add() it makes new style tags, and
when you want to remove it removes the style tag for the css rule that
you want to remove.

I think module X is better than Y though, but for a small number of
css rules perhaps something like Y would be better. One could even
write module Z which could by a smart hybrid of X and Y.

E

On Feb 25, 4:58 pm, Daniel <daniel...@gmail.com> wrote:
> Ok so the method names here are different, look past that, the point
> is that this get's you add/remove/update and it is pretty close to a
> common ground:
>
> sheet.addRules({
>     'body, #fctr, #sbl, #ghead': {
>         background: '#000000',
>         color: '#CFCFCF'
>     },
>     'a': {
>         color: '#ffffff'
>     }
>  });
>
> OR
>
> sheet.addRules({
>     "body, #fctr, #sbl, #ghead": "background: #000000; color:
> #CFCFCF;",
>     "a": "color: #ffffff;"
>  });
>
> OR singularly with addRule
>
> sheet.addRule("body, #fctr, #sbl, #ghead", "background: #000000;
> color: #CFCFCF;");
>

> Here are a few add-ons that want style toggling:https://addons.mozilla.org/en-US/firefox/addon/46442https://addons.mozilla.org/en-US/firefox/addon/5758https://addons.mozilla.org/en-US/firefox/addon/8624

Daniel

unread,
Feb 26, 2010, 12:10:17 AM2/26/10
to mozilla-labs-jetpack
Jeff - Of course you are right, when adding styles tied to a single
action or state of the document it is easy to group them under a class
that is then applied to the parent...but I was just trying to show the
mechanism how it works.

So another case would be an active style writer where I want to give
the user a space to define styles and save them to the domain
actively, but also allow them to delete styles one by one (firebug
does this, but does not persist it). There are tons of add-ons with
this functionality in their guts. It is a good use-case, and one that
has existing parallels in the add-ons ecosystem.

- Daniel

On Feb 25, 4:54 pm, Jeff Balogh <m...@jeffbalogh.org> wrote:

Daniel

unread,
Feb 26, 2010, 12:35:36 AM2/26/10
to mozilla-labs-jetpack
"The separation of css and javascript is always possible as far as I
can tell.. in what use case would it not be possible? If there is a
use case, then the debate is over."

Actually anytime you are adding something to a domain without giving
the Mod an included CSS file in your package, JavaScript IS going to
be the way any dynamic Mod is constructed.

"This is part of the concept of Unobtrusive JavaScript, or separation
of structure/presentation/behavior:"

Actually that is one of the aims of taking this route - that said, we
could allow completely string based inputs, just know that to do
anything dynamic that escapes the requirement of reloading the page
will be converted into objects for application to the page...

I talked with Aza today and we feel the same way as far as the
reloading of pages - If restarts caused buy extensions are nasty for
users to deal with...then so to are reloads of pages cause by
extensions just to dump css style(s) props from a document - this is
*completely* avoidable. It is a crappier experience for the user, and
there is no contest there.

Likely we will code it to take both, perhaps strings first, then the
other so you have a choice - that choice being either a jarring
experience for the user, or a clean, seamless, no-reload one.

- Daniel

On Feb 25, 7:14 pm, Erik Vold <erikvv...@gmail.com> wrote:
> So that this conversation doesn't get overly complex, let's try to
> distill the issue:
>
> Why would one need to remove css rules from a page when they can
> simply change the classes on elements?
>
> The separation of css and javascript is always possible as far as I
> can tell.. in what use case would it not be possible? If there is a
> use case, then the debate is over.
>
> As far as I can tell all of those 3 firefox extensions could separate
> css and js and still work w/out requiring page reloads w/ simple best
> practices.
>
> This is part of the concept of Unobtrusive JavaScript, or separation

> of structure/presentation/behavior:http://onlinetools.org/articles/unobtrusivejavascript/cssjsseparation...

> > Here are a few add-ons that want style toggling:https://addons.mozilla.org/en-US/firefox/addon/46442https://addons.mo...

Daniel

unread,
Feb 26, 2010, 12:58:02 AM2/26/10
to mozilla-labs-jetpack
To conclude, I am going to defer to Myk Melez on a final decision on
this JEP API, as he is the primary API syntax and standardization
developer for Jetpack. Though I may disagree with some of the points
in this thread, Myk has tons of experience in this area and will
carefully consider all the options presented here.

- Daniel

> ...
>
> read more »

Erik Vold

unread,
Feb 26, 2010, 2:53:50 AM2/26/10
to mozilla-labs-jetpack
>> "The separation of css and javascript is always possible as far as I
>> can tell.. in what use case would it not be possible? If there is a
>> use case, then the debate is over."
>
> Actually anytime you are adding something to a domain without giving
> the Mod an included CSS file in your package, JavaScript IS going to
> be the way any dynamic Mod is constructed.

I would say that using a css blob (to be put into a style tag), even a
css blob template (where dynamic values are injected) is separation,
but your point about dynamic mods is correct. If a developer wants to
create a mod where the user can choose the color, or font, etc.. then
that use case is a reason to allow removal of css, which I'm not
against at all. However, the cascade can also achieve this..

(side note: perhaps a replace(old,new) method would be useful for this
dynamic css use case)

I'm still debating about the JSON-like syntax though (and this is what
I think everyone else is against, not reloads when css is removed),
which I do not see as a separation of css & js but quite the opposite,
I'm not debating the need to avoid reloads when css is removed.

My concern is really more about building in this JSON-like syntax in
when we don't have to. Providing the add()/remove() (where a remove of
a blob == removal of style tag, and remove of a css file == removal of
link tag) of css blobs is enough in my opinion; this is my only point.

>> "This is part of the concept of Unobtrusive JavaScript, or separation
>> of structure/presentation/behavior:"
>
> Actually that is one of the aims of taking this route - that said, we
> could allow completely string based inputs, just know that to do
> anything dynamic that escapes the requirement of reloading the page
> will be converted into objects for application to the page...
>
> I talked with Aza today and we feel the same way as far as the
> reloading of pages - If restarts caused buy extensions are nasty for
> users to deal with...then so to are reloads of pages  cause by
> extensions just to dump css style(s) props from a document - this is
> *completely* avoidable.  It is a crappier experience for the user, and
> there is no contest there.

I don't think reloads of pages are necessary in the case of css/styles
either. I happened to say otherwise in another thread on feb 12th
totally by mistake when I was considering the JSON-like syntax, but
even in that case the removal of css is easy as I expressed clearly in
this thread at least. My point in the other thread was really directed
towards the removal of scripts.

I don't think anyone really would have a case against the forcing
reloads when you delete a style/link tag, that position wouldn't make
any sense at all, because even if Jetpack did force reloads developers
can easily bypass it and inject style/link tags into the document
manually via js, which they would all do if they had to. The forcing
of a reload problem was always related to the deletion of a script and
not css to my mind, because when you delete a script tag, effects of
the code that were in that script tag would still linger.

Sorry if I was not clear enough Daniel.

It's good that we're fleshing out the issues, which I think we mostly
agree on, besides the desirability of a JSON-like syntax, but even
here you seem to agree that at least holding off on that is best.

E

Daniel

unread,
Feb 26, 2010, 11:48:34 AM2/26/10
to mozilla-labs-jetpack

/*

I don't think anyone really would have a case against the forcing
reloads when you delete a style/link tag, that position wouldn't make
any sense at all, because even if Jetpack did force reloads developers
can easily bypass it and inject style/link tags into the document
manually via js, which they would all do if they had to. The forcing
of a reload problem was always related to the deletion of a script and
not css to my mind, because when you delete a script tag, effects of
the code that were in that script tag would still linger.
*/

I was not under the impression that removing styles from pages
automatically caused reloads :) I just wanted to ensure that a well
thought out remove method was in place that didn't do so via a flawed
implementation route.

/*


My concern is really more about building in this JSON-like syntax in
when we don't have to. Providing the add()/remove() (where a remove of
a blob == removal of style tag, and remove of a css file == removal of
link tag) of css blobs is enough in my opinion; this is my only point.

*/

Ahh now we arrive at our true issue - I had already thought of a few
implementations that were purely blob based - and here is the crux of
their failing: granular ability in style addition/removal

If each blob got its own tag for insertion and you tracked the tags
with a variable, you could easily delete them from the page - this is
true and correct. So under this route, say we want 3, 4, 5, 6
distinct and separate blobs... that leads to 3, 4, 5, 6 tags in the
page...

But for a breaking case we don't really need even that level of stuff,
consider the following:

I have a single blob of css that I have added to the page:

"body, #fctr, #sbl, #ghead, #home-button.bookmark-
item:hover:active[chromedir='rtl'] { background: #000000; color:
#CFCFCF; }"

Now let's say I want to remove the background property from #home-
button.bookmark-item:hover:active[chromedir='rtl'].

How would you do that? The only ways I had thought of was to have the
dev carefully manipulate their blobs with some ungodly regexs or
string splitting/reassembly then to pass in a method that would swap
out the new tag that contained the css blob minus what was removed,
much in the way Eric described.

That is pretty nasty though. I am just spit balling here, but what I
would do, much like the script in the demo, is to break the selector
group down and associate the given styles with each one, which would
end up looking like this strictly on the implementation end:

"body": { "background": "#000000", "color": "#CFCFCF"' }
"#fctr": { "background": "#000000", "color": "#CFCFCF"' }
"#sbl": { "background": "#000000", "color": "#CFCFCF"' }


"#ghead": { "background": "#000000", "color": "#CFCFCF"' }

"#home-button.bookmark-item:hover:active[chromedir='rtl']":
{ "background": "#000000", "color": "#CFCFCF"' }

Why would you do that you say? It alleviates forcing the devs to
write The One Regex: A Super Geeky Regex to Rule Them All or doing a
bunch of crazy string snipping/assembly - "Help me...help you"
right? :)

Because then all you would need to allow you to remove a particular
style in a blob is for you to pass the selector, and optionally the
granular styles it contains, that you want to delete as strings. After
deletion, run a for(in) loop and add the styles into a blob and inject
them.

So we certainly should allow blobs to be entered developer-side, but I
think if folks do a deep-dive into the implementation side they'd find
that sane mgmt and removal of styles within those blobs best be served
by boiling them down to a tracking hash in the end :) Perhaps not
though, maybe I am not seeing something obvious that would allow for
you to stay in blob land 100% of the time even when doing really
specific style removals, but I would certainly be open to an example
that does so.

Thanks for the continued discussion, I just want to arrive at the most
optimal solution. By the post count here and the content of this
thread, we have seen so many ideas surface and I am really happy about
that! You guys/gals really care and it is going to make the final
product/APIs better :)

- Daniel

Erik Vold

unread,
Feb 26, 2010, 4:29:17 PM2/26/10
to mozilla-labs-jetpack

> /*
> I don't think anyone really would have a case against the forcing
> reloads when you delete a style/link tag, that position wouldn't make
> any sense at all,

ugh I said that wrong, should be "I don't think anyone really would
have a case FOR forcing reloads when you delete a style/link tag"
sigh.. you got my point though.

> /*
> My concern is really more about building in this JSON-like syntax in
> when we don't have to. Providing the add()/remove() (where a remove of
> a blob == removal of style tag, and remove of a css file == removal of
> link tag) of css blobs is enough in my opinion; this is my only point.
> */

> If each blob got its own tag for insertion and you tracked the tags


> with a variable, you could easily delete them from the page - this is
> true and correct.  So under this route, say we want 3, 4, 5, 6
> distinct and separate blobs... that leads to 3, 4, 5, 6 tags in the
> page...

If the modules X,Y, and Z that I describe were managing a large array
of small strings (where each string was 1 css rule) instead of a JSON-
like syntax, then for module Y yes you would have a tag for each rule,
but not for module X or Z.

> consider the following:
>
> I have a single blob of css that I have added to the page:
>
> "body, #fctr, #sbl, #ghead, #home-button.bookmark-
> item:hover:active[chromedir='rtl'] { background: #000000; color:
> #CFCFCF; }"
>
> Now let's say I want to remove the background property from #home-
> button.bookmark-item:hover:active[chromedir='rtl'].
>
> How would you do that?

Well one way would be to a class like:

".someClassName { background: #000000; color: #CFCFCF; }"

then attach the class to the "body, #fctr, #sbl, #ghead, #home-
button.bookmark-item:hover:active[chromedir='rtl']" elements and
remove the class from the elements when I don't want to use it instead
of removing the css rule from the document.

Another way would be to add a class to the body only, and alter the
css rule you provided to be:

> "body.someClass, body.someClass #fctr, body.someClass #sbl, body.someClass #ghead, body.someClass #home-button.bookmark-item:hover:active[chromedir='rtl'] { background: #000000; color:
> #CFCFCF; }"

A sort of css rule delegation. With this method you could add less
classes to the document & avoid issues around dynamically added
elements.

These methods separate presentation and behavior, and granular removal
of css rules via js does not.

> The only ways I had thought of was to have the
> dev carefully manipulate their blobs with some ungodly regexs or
> string splitting/reassembly then to pass in a method that would swap
> out the new tag that contained the css blob minus what was removed,

> much in the way Erik described.

I don't think Regex's will ever be needed in order to add granularity
either, certainly not w/ the modules I described. The developer would
need to split up the selectors in to individual strings however, such
as you describe below.

> That is pretty nasty though. I am just spit balling here, but what I
> would do, much like the script in the demo, is to break the selector
> group down and associate the given styles with each one, which would
> end up looking like this strictly on the implementation end:
>
> "body": { "background": "#000000", "color": "#CFCFCF"' }
> "#fctr": { "background": "#000000", "color": "#CFCFCF"' }
> "#sbl": { "background": "#000000", "color": "#CFCFCF"' }
> "#ghead": { "background": "#000000", "color": "#CFCFCF"' }
> "#home-button.bookmark-item:hover:active[chromedir='rtl']":
> { "background": "#000000", "color": "#CFCFCF"' }
>
> Why would you do that you say?  It alleviates forcing the devs to
> write The One Regex: A Super Geeky Regex to Rule Them All or doing a
> bunch of crazy string snipping/assembly - "Help me...help you"
> right?  :)

Aside: The reg exp shouldn't be very hard to write =], even though we
agree that it's not necessary, but I'm the kind of person that loves
drawing DFA & NFA graphs..

> So we certainly should allow blobs to be entered developer-side, but I
> think if folks do a deep-dive into the implementation side they'd find
> that sane mgmt and removal of styles within those blobs best be served
> by boiling them down to a tracking hash in the end :)

No I don't agree here.

> Perhaps not
> though, maybe I am not seeing something obvious that would allow for
> you to stay in blob land 100% of the time even when doing really
> specific style removals, but I would certainly be open to an example
> that does so.

I'm the opposite, I don't see why you would ever need to leave blob
land it separates css and js as much as is possible which is always
desirable. I am trying to envision a use case where it is not possible
though.. Removal of blobs will be necessary of course, and this
feature is built-in to the dom, because you can remove style/link tags
w/ js. Albeit this may not be obvious, I'm certainly sure that many
webdevs end up mixing js&css when they should not, the fact that
jQuery and Mootools have built-in ways to help a developer manipulate
style attributes of html elements is indicative that it isn't obvious;
or maybe I'm missing some use case where this was necessary.. At the
moment this just seems like unnecessary bloat that should be a plugin
to me (ok Mootools is modular so I assume you can get a copy of the
lib w/out this feature, at least I hope that is true, but then your
version of the lib is unlikely to be cached on the users comp b4
arriving at your site).

E

Erik Vold

unread,
Feb 26, 2010, 6:37:58 PM2/26/10
to mozilla-labs-jetpack
On Feb 20, 2:50 pm, Myk Melez <m...@mozilla.org> wrote:
> On 02/18/2010 11:12 PM, Erik Vold wrote:> how about using 'js' and 'css' instead of 'script' and 'style'?
>
> Hmm, js and css are certainly reasonable names, but I think script and
> style are preferable, since they are analogous to the tags with which
> one inserts such code into web pages

Indeed script and style are analogous to the tags with which one
inserts code into web pages, but with those tags one can choose a type
w/ the type attribute, and this is not available in the JEP. Since
there may be more than one style type in the future (which is why the
type attribute exists), and there are already more than one type of
script type that can be used I would lean towards making the same
decision that the Google Chrome folks made.

E

Reply all
Reply to author
Forward
0 new messages