{"id":3743,"date":"2010-04-01T14:00:14","date_gmt":"2010-04-01T21:00:14","guid":{"rendered":"http:\/\/3.150"},"modified":"2012-04-12T19:37:01","modified_gmt":"2012-04-12T19:37:01","slug":"jetpack-page-mod-vs-user-script","status":"publish","type":"post","link":"https:\/\/blog.mozilla.org\/labs\/2010\/04\/jetpack-page-mod-vs-user-script\/","title":{"rendered":"Jetpack Page Mods vs. User Scripts"},"content":{"rendered":"<p><a title=\"Jetpack 0.4 \u2013 Audio Recording &amp; Page Mods APIs\" href=\"https:\/\/mozillalabs.com\/blog\/2009\/07\/jetpack-0-4-audio-recording-page-mods\/\">Page mods were introduced to the Jetpack prototype in July of last year<\/a>, and I haven&#8217;t yet seen an article comparing them to user scripts yet, so I&#8217;d like outline some of the differences that I&#8217;ve been able to discern. However, I will be focusing especially on the non-prototype version of <a href=\"https:\/\/wiki.mozilla.org\/Labs\/Jetpack\/Reboot\/JEP\/107\">Jetpack Page Mods (JEP 107)<\/a>, rather than the prototype version which was released last July. There are many similarities between the two, and the differences are mainly improvements. The new Page Mods API found in Jetpack Enhancement Proposal (JEP) 107 has not been implemented yet, but it will be soon, so we&#8217;ll take a look at what&#8217;s in the works.<\/p>\n<p>The purpose of both Jetpack page mods and user scripts is basically to add features and functionality to any website. This means that if you wish to change a website, either by mashing it up with data from another website, improving elements of the site, or whatever else, then you can with an understanding of JavaScript, HTML, and CSS. Both of these APIs have their own set of benefits unique to them, I&#8217;ll talk a bit about each and highlight which API is best given your development goals.<\/p>\n<p>Before I discuss Jetpack page mods, let&#8217;s take a look at user scripts.. <!--more--><\/p>\n<h2>User Scripts<\/h2>\n<h3>Introduction<\/h3>\n<p>Ever since <a title=\"Greasemonkey - Firefox Add-on\" href=\"http:\/\/addons.mozilla.org\/en-US\/firefox\/addon\/748\">Greasemonkey<\/a> was created in late 2004, and <a title=\"Firefox Users Monkey With the Web\" rel=\"external nofollow\" href=\"http:\/\/www.wired.com\/science\/discoveries\/news\/2005\/05\/67527\">was introduced to the world<\/a> in 2005, it has made user scripts very popular and today there are over <a title=\"40,000 More Extensions!\" rel=\"external nofollow\" href=\"http:\/\/blog.chromium.org\/2010\/02\/40000-more-extensions.html\">40,000 user scripts available<\/a> at <a title=\"Userscripts.org\" rel=\"external nofollow\" href=\"http:\/\/userscripts.org\">userscripts.org<\/a> alone, which should show you just how simple they are to write and how many ideas web users have come up with in the time that has past (on average over 20 user scripts are written per day). If you would like to read more about Greasemonkey user scripts then please read the <a title=\"GreaseSpot Wiki\" rel=\"external nofollow\" href=\"http:\/\/wiki.greasespot.net\/Main_Page\">Greasemonkey wiki<\/a>.<\/p>\n<h3>Cross browser adaptations<\/h3>\n<p>Greasemonkey&#8217;s popularization of user scripts has lead browsers such as <a title=\"Take control with User JavaScript\" rel=\"external nofollow\" href=\"http:\/\/www.opera.com\/browser\/tutorials\/userjs\/\">Opera<\/a> and <a title=\"User Scripts - The Chromium Projects\" href=\"http:\/\/dev.chromium.org\/developers\/design-documents\/user-scripts\">Google Chrome<\/a> to support user scripts to varying degrees. For Safari there is the <a title=\"GreaseKit\" rel=\"external nofollow\" href=\"http:\/\/8-p.info\/greasekit\/\">GreaseKit<\/a> plug-in, and user scripts are available in IE 7 with the <a title=\"IE7Pro\" rel=\"external nofollow\" href=\"http:\/\/www.ie7pro.com\/\">IE7Pro<\/a> plug-in. These adaptations do not all fully support the <a title=\"Greasemonkey API\" rel=\"external nofollow\" href=\"http:\/\/wiki.greasespot.net\/Greasemonkey_Manual:API\">Greasemonkey API<\/a>, but they do support a large subset of Greasemonkey user scripts. Some user scripts may need to be written in a way that is not as reliant on Firefox&#8217;s JavaScript &amp; DOM implementation to fully take advantage of user script compatibility in these browsers.<\/p>\n<h3>Greasemonkey API<\/h3>\n<p>There are a few chrome privileges user scripts have been granted by the Greasemonkey API thus far, including <a title=\"GM_xmlhttpRequest\" rel=\"external nofollow\" href=\"http:\/\/wiki.greasespot.net\/GM_xmlhttpRequest\">GM_xmlhttpRequest<\/a> which allows one to make cross domain requests, <a title=\"Greasemonkey Values\" rel=\"external nofollow\" href=\"http:\/\/wiki.greasespot.net\/Greasemonkey_Manual:API#Values\">GM_getValue\/GM_setValue\/GM_deleteValue<\/a> allow one to save simple persistent values, and <a title=\"GM_registerMenuCommand\" rel=\"external nofollow\" href=\"http:\/\/wiki.greasespot.net\/GM_registerMenuCommand\">GM_registerMenuCommand<\/a> which allow one to create a simple Greasemonkey menu item.<\/p>\n<h3>Scripts are reloaded for every page load<\/h3>\n<p>User scripts are completely reloaded after every page load, the same way native JavaScript is required to. This means that if a single script is meant to run on every page or a large collection of pages, then the script is completely reloaded for each. In this situation, and others, one might instead want to have a single piece of code that can be referenced by all pages that it is supposed to be run on.<\/p>\n<h3>Code reuse<\/h3>\n<p>With user scripts one can use the <a title=\"@require - Greasemonkey Header\" rel=\"external nofollow\" href=\"http:\/\/wiki.greasespot.net\/Metadata_Block#.40require\">@require<\/a> header to have external JavaScript downloaded when the user installs the script. More crude methods would be to add a <a title=\"HTML Script Element - MDC\" href=\"https:\/\/developer.mozilla.org\/En\/HTML\/Element\/Script\">script element<\/a> to the page to fetch the code (although this would mean that you would have to wait for the script to download and load before you use it), or simply copying &amp; pasting the desired code. In all three cases however, the JavaScript is loaded on every page load and this has the potential to reduce the performance of the user&#8217;s browser.<\/p>\n<h3>Settings<\/h3>\n<p>With user scripts one can set, get, and remove strings, booleans, and integers only with the <a title=\"Greasemonkey Values\" rel=\"external nofollow\" href=\"http:\/\/wiki.greasespot.net\/Greasemonkey_Manual:API#Values\">GM_getValue\/GM_setValue\/GM_deleteValue<\/a> functions, but they will need to provide an html interface for the user to change these settings, and there are frameworks that have been built using the aforementioned @require header, such as <a title=\"GM_Config - Google Code\" rel=\"external nofollow\" href=\"http:\/\/code.google.com\/p\/gmconfig\/\">GM_Config<\/a>.<\/p>\n<p>I should also mention that if the user script is being run on Greasemonkey for Firefox then the user can also change stored values (which are often settings) by going to <a title=\"about:config - MozillaZine\" href=\"http:\/\/kb.mozillazine.org\/About:config\">about:config<\/a>, but this method obviously isn&#8217;t user friendly.<\/p>\n<h3>JavaScript libraries<\/h3>\n<p>With user scripts there is not a JavaScript library available by default, one can use the @require header to have one downloaded, but this has the associated issue I previously mentioned, which is that the library will be reloaded on every page for the user, and if the user has other user scripts that are running on the same pages, which also include libraries, then the user could find themselves in a situation where they have <a title=\"jQuery - A JavaScript Library\" rel=\"external\" href=\"http:\/\/jquery.com\/\">jQuery<\/a> loading 10 times per page load for some pages, or worse.<\/p>\n<h2>Jetpack Page Mods<\/h2>\n<h3>Introduction<\/h3>\n<p>The best documentation available for making Jetpack page mods made with Jetpack&#8217;s prototype was <a title=\"JEP 17 - Page Mods\" href=\"https:\/\/wiki.mozilla.org\/Labs\/Jetpack\/JEP\/17\">JEP 17<\/a>, but now after <a title=\"Evolving the Firefox Add-on Platform\" href=\"http:\/\/mozillalabs.com\/jetpack\/2010\/01\/11\/evolving-the-firefox-add-on-platform\/\">the reboot<\/a>, the best documentation for Jetpack page mods that are made with <a title=\"Announcing the Jetpack SDK\" href=\"http:\/\/mozillalabs.com\/jetpack\/2010\/03\/09\/announcing-the-jetpack-sdk\/\">the SDK<\/a> is <a title=\"JEP 107 - Page Mods\" href=\"https:\/\/wiki.mozilla.org\/Labs\/Jetpack\/Reboot\/JEP\/107\">JEP 107<\/a>; although JEP 107 is in progress at the moment it&#8217;s preferable to discuss, simply because it&#8217;s Jetpack&#8217;s future.<\/p>\n<h3>Limited to Firefox<\/h3>\n<p>Jetpack (and therefore Jetpack page mods) are basically limited to Firefox for the near future, but compatibility may come in later phases of the project.<\/p>\n<h3>Chrome privileged code<\/h3>\n<p>A Jetpack developer will not only have access to the built-in APIs defined in <a title=\"Jetpack Reboot JEPs\" href=\"https:\/\/wiki.mozilla.org\/Labs\/Jetpack\/Reboot\/JEP\">the JEPs<\/a>, which offer a great deal of <a title=\"Chrome - MDC\" href=\"https:\/\/developer.mozilla.org\/en\/Chrome\">chrome<\/a> functionality, but they may also create Jetpack Chrome Modules which have access to the browser&#8217;s chrome (aka a Privileged Jetpack Module). Therefore a Jetpack page mod has access to a wider variety of\u00a0 browser methods, functionality, and UI elements.<\/p>\n<h3>Multi-page Modding<\/h3>\n<p>With Jetpack page mods your JavaScript variables and functions can mod many different pages by registering your script and styles in a single <code>pageMod<\/code> instance.\u00a0 This means that you can define a function or variable once and have it used on page load in all the pages you specify. This is preferable to having the same function defined many times for each page you apply your mods to.<\/p>\n<p>Pseudo Example:<br \/>\n<code><br \/>\n\/\/ execution counter<br \/>\nvar counter = 0;<br \/>\nvar mainFunction = function(){<br \/>\ncounter++;<br \/>\n\/\/ do stuff<br \/>\n};<br \/>\nvar myMods = new pageMod({<br \/>\n'include': ['*.google.com'],<br \/>\n'exclude': ['https:\/\/mail.google.com\/*'],<br \/>\n'script': [ mainFunction ]<br \/>\n});<br \/>\n<\/code><br \/>\nIn this example <code>counter<\/code> would be equal to number of pages the page mod was executed on during the time that the user had Firefox browser open, only once the user closes Firefox or removes the Jetpack will the counter variable be removed from memory.<\/p>\n<h3>Code reuse<\/h3>\n<p>With Jetpack you can make modules, which can be reused by other Jetpacks; this wasn&#8217;t possible with the Jetpack prototype.<\/p>\n<h3>Settings<\/h3>\n<p>For the Jetpack prototype there was the <a title=\"Settings JEP 24 - Jetpack\" href=\"https:\/\/wiki.mozilla.org\/Labs\/Jetpack\/JEP\/24\">Settings JEP 24<\/a> which defined a convenient area for users to configure their settings for their Jetpacks. After the reboot however, Jetpacks are Firefox extensions, and they can be given settings in a similar fashion, there is not a JEP proposing a simple API to provide settings any longer, but when everyone can create modules anyone can create a module to solve this problem, so I expect we will see a solution in due time.<\/p>\n<h3>JavaScript Libraries<\/h3>\n<p>Support for major JavaScript libraries within Jetpack is something that the platform aims to support in future releases.<\/p>\n<h2>Summary<\/h2>\n<p>Write user scripts for simple problems or when you want\/need a cross browser solution, and Jetpack page mods can be used when you need to do what a user script cannot do. Also, consider the fact that some user scripts will perform better as Jetpack page mods because of multi-page modding and the ability to access deeper levels of the browser&#8217;s functionality.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Page mods were introduced to the Jetpack prototype in July of last year, and I haven&#8217;t yet seen an article comparing them to user scripts yet, so I&#8217;d like outline some of the differences that I&#8217;ve been able to discern. However, I will be focusing especially on the non-prototype version of Jetpack Page Mods (JEP 107), rather than the prototype version which was released last July. There are many similarities between the two, and the differences are mainly improvements. The new Page Mods API found in Jetpack Enhancement Proposal (JEP) 107 has not been implemented yet, but it will be soon, so we&#8217;ll take a look at what&#8217;s in the works&#8230; <a class=\"go\" href=\"https:\/\/blog.mozilla.org\/labs\/2010\/04\/jetpack-page-mod-vs-user-script\/\">Continue reading<\/a><\/p>\n","protected":false},"author":456,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.mozilla.org\/labs\/wp-json\/wp\/v2\/posts\/3743"}],"collection":[{"href":"https:\/\/blog.mozilla.org\/labs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mozilla.org\/labs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/labs\/wp-json\/wp\/v2\/users\/456"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/labs\/wp-json\/wp\/v2\/comments?post=3743"}],"version-history":[{"count":0,"href":"https:\/\/blog.mozilla.org\/labs\/wp-json\/wp\/v2\/posts\/3743\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.mozilla.org\/labs\/wp-json\/wp\/v2\/media?parent=3743"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mozilla.org\/labs\/wp-json\/wp\/v2\/categories?post=3743"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mozilla.org\/labs\/wp-json\/wp\/v2\/tags?post=3743"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}