Project: chromium Issues People Development process History Sign in
New issue
Advanced search Search tips
Starred by 910 users
Status: Fixed
Owner: ----
Closed: Nov 2014
Components:
EstimatedDays: ----
NextAction: ----
OS: All
Pri: 3
Type: Feature



Sign in to add a comment
Help extensions authors make options pages with a consistent look
Project Member Reported by asargent@chromium.org, Oct 20 2009 Back to list
We recently added support for extensions to declare an "options_page" in their manifest pointing to a page 
bundled in their extension ( Issue 23801 ). This enables a "options/preferences" button in the 
chrome://extensions UI which users can click to open a new tab with that page. The extension author can then 
use localStorage, etc. to store various settings related to their extension.

We'd like to provide some facility to make it easy for extensions authors to create options pages with a 
consistent look, perhaps matching the chrome://extensions page itself (mocks of that are attached to Issue 
12119). The most straightforward way to do this is probably to provide some css classes that are 
automatically injected and available, similar to the "toolstrip-button" class we had for toolstrips. For 
reference, that file was:

http://src.chromium.org/viewvc/chrome/trunk/src/chrome/renderer/resources/extension_toolstrip.css?view=log


Also, there was a thread of discussion on the chromium-extensions group about configuration/options:

https://groups.google.com/group/chromium-extensions/browse_thread/thread/eea7f1b2175a54fa/5830ff8133b5904b



 
Comment 1 Deleted
Comment 2 Deleted
Comment 3 Deleted
Comment 4 Deleted
When this is implemented, will it be a themeable component?
Comment 6 Deleted
Comment 7 Deleted
Comment 8 Deleted
Comment 9 by qbawo...@gmail.com, Feb 21 2011
I agree! We really need this feature.
Do you think about solutions with JSON options file which
is some kind of manifest, and automatically render to options page?
Comment 10 by mega...@gmail.com, Feb 21 2011
@gbawo... That's an interesting idea, I suggest you open a separate bug for that though.
Maybe it can turn options too limited. If you need a non-default option type you don't will do. In otherside, maybe be possible to define a custom-option. Example: http://jsfiddle.net/HqYtu/

Comment 12 by tys...@gmail.com, Feb 22 2011
@david7... That looks like a great place to start. 
For a large percentage of cases, default input types would probably be sufficient. Those requiring custom options are harder to satisfy, especially when extension sync is brought into the picture. 

Some sort of theming for the options pages would allow extension authors to provide continuity of experience between their popups, their icons, and their options page. This wouldn't be necessary for the initial release though. 
It would be nice if extensions had a subpage under the tabbed options page. It could be generated with some configuration specified in the manifest. Extension options would also become searchable then.
If you are using Chromium 11.x you can open Options and see how works currently. It's exactly how you suggest.
I suggest adding this to an extension's manifest.json:

{
    /*...*/
    "options": {
        "title": "My extension's settings" /*should be inserted into page title*/
        "tabs": { /*list of tabs for the left side*/
            "My tab": { /*tab name*/
                "Alert \"Hello\" on startup": "checkbox",
                "Say something after \"Hello\"": "text",
                "Password for example.com": "password"
            }
        }
}

Where the name is the label and the value is the input type (for selects, an array should be used instead)
Then when we need to get a value, in JavaScript:

if (chrome.extension.options.getTab("My tab").getValue("Alert \"Hello\" on startup") == true) {
    alert("Hello world!\n" + (chrome.extension.options.getTab("My tab").getValue("Say something after I say \"Hello\"") ? chrome.extension.options.getTab("My tab").getValue("Say something after \"Hello\"") : "Click OK to close..."));
}

Where getTab's first argument is the tab's name and getValue is the label chosen above. 
Comment 16 Deleted
Need to be less 'workarrounded'. Need supports locale too. Then your example is inconsistent for the case.
Comment 18 by mbre...@gmail.com, Feb 22 2011
@addydmasi: while david7...@gmail.com's comments may be valid, your general idea is along the lines of what I was thinking. This would allow:
 a. MUCH more consistant UI for options pages
 b. easier facilitation for extensions to back up/sync there settings across browsers (as the browser now know how to "read" the options and there values)
We once discussed this ages ago on one of the mailing lists, cant find it right now though. Either way, we concluded (or more appropriately they, as I only voiced my opinions twice or so) that a manifest option page would be too limited for more complicated options pages (e.g. take a look at the all mangas reader option page) or would require a lot of thinking on how to implement it. Personally I would suggest an xml approach would be far better. The structure would be fairly similar to html when it gets down to styling, but it would have to follow a basic structure which would be defined. Most importantly it would not allow e.g. style attributes. It would however be possible to dynamically through javascript add or remove input elements (e.g. to add or remove a list of server). And whatever would be the content of these input elements would always be saved and could be called upon by an JS API.  
Comment 20 by mbre...@gmail.com, Feb 22 2011
@websiteb...@gmail.com: True, this would be too limited for advanced options. But for simple options it would make things MUCH easier. There would also be an option to use an html file for options, just as it works today. As far as styling: it would be trivial to specify classes/id's in the mainfest, you can also add a stylesheet making styling trivial. 
But that misses the point - the idea is to eliminate the needs for styling! Anyone that wants/needs styling can use the current build-your-own method.
Comment 21 by qbawo...@gmail.com, Feb 22 2011
@david7: totally agree!
@websiteb: I agree that it should be optionally.
In 99% cases simple options manifest will be sufficient - in others you may overwrite options page.
In this approach we can even integrate extension options with Browser Options page!
@qbawo...: I have already implemented just that for my own extensions, see for instance my video zoom extension:
https://chrome.google.com/webstore/detail/mpgjeecnfhippncndbojafcnpocpekcj/
Source code available here:
http://code.google.com/p/chrome-window-zoom-extension/

Options structure definition in json:
http://code.google.com/p/chrome-window-zoom-extension/source/browse/trunk/options_structure.json

Automatic rendering of options page based on this structure:
http://code.google.com/p/chrome-window-zoom-extension/source/browse/trunk/options/page.html


Forgot to mention these two:
http://code.google.com/p/chrome-window-zoom-extension/source/browse/trunk/background/load_options.js
http://code.google.com/p/chrome-window-zoom-extension/source/browse/trunk/background/save_options.js
The background page is the only page that does loading and saving of options; the extension script and options page ask the background page for the options or tell it to save them.
Ok, sure, thought it would work pretty well, as it would still be fairly simple in comparison to the current system. So lets thinking about the problems which we would need to solve with a json structure;
 - An array cant be the value, so something along the lines of
  "varName" : {
    description: "bla bla bla",
    defaultValue: "",
    type: "text"
  }
 would work far better, as it would then also be possible to have
  "varName" : {
    description: "bla bla bla",
    defaultValue: "",
    options: ["a","b","c"],
    type: "select/option"
  }
 - Labels in between
 "labelAAA" : {
   description: "bla bla desc",
  type: "label"
 }
  Problem with this approach is that every label would need to have a unique name...
 - You couldn't have subgroups as the ones you have on the current preferences page.
 - Should be possible to change descriptions dynamically... I think... or in some other way have dynamic values. 
 - Localization, not sure... easiest approach would be to be able to have properties like 
 description: {
  EN: "bla bla", 
  NL: "bla bla"
 }
 but I dont have a lot of experience in this field.

Just saw the new comment by skylined which also follows approximately a similar structure as I was thinking about now.

Comment 25 by qbawo...@gmail.com, Feb 22 2011
@skylined@chromium.org
it looks really great!
I think this should be available for all extensions - and still I have chrome://settings/extensions in my mind ;)
Oh and, I forgot to mention that no matter what will be created, a general css should definitely be available for the custom option pages. Possibly these could be even iframed into a chrome://settings/extensions page.
Comment 27 by qbawo...@gmail.com, Feb 22 2011
@websiteb...@gmail.com:
I like your i18n description approach, but shouldn't labels be stored in messages.json (like this http://code.google.com/chrome/extensions/i18n.html)?
The unique name of labels are necessary if we want store values in localStorage.
Another idea: when we have simplified options and storage maybe then we can sync extension's localStorage between browser's instances?
Here's an update to my original comment, with javascript events:

{
    /*...*/
    "options": {
        "javascript": "path/to/options.js" /*a JavaScript file for scripting events*/
        "my tab": [
            {"label": "my label","description": "example select box","type": "select","values": ["one","two","three"]},
            {"label": "another label","description": "a text box with JavaScript applied","type": "text","onkeydown": "myfunction" /*where myfunction is a javscript function*/}
        ]
    }
}

The strings that are shown to the user should be checked for i18n strings as usual. 
In options.js, javascript can be used to read the value, for example:

function myfunction(event){
 alert(event.target.value);
}
@qbawo...@gmail.com:  Yeah, you're probably right about the incorrectness of the localization implementation, as I mentioned I dont have a lot of experience in this field (most of my apps are unlocalized) and for the only app which did have localization I had to create my own version due to all the libraries being to limited for my dynamic approach, so you might be right about that.
 As far as localStorage... labels shouldn't be stored there as far as I know.
 And yeah mbre...@gmail.com was also already mentioning the options of syncing.

 @addydmasi; Wait, with your suggestion, would labels be what I would call variablenames? Aside of that, the idea of having functions is interesting, especially for custom validation, but preventing the javascript from having too much access would be hard (I think). Or wouldn't it have any DOM access... :S? That would do the trick probably.
@websiteb...@gmail.com
1. Not sure exactly what you mean, but I assume you mean giving the label an id so it can be edited via the DOM. I think an extra (optional) "label_id": "mylabel" should be added to the required object for this. 
2. I think DOM access should be granted unlimited access to anything dynamically generated in the script, plus limited access to only elements on the current tab (removeNode, for example, wouldn't be allowed), e.g.:

function mymouseover(event){
 try{document.getElementById("someTextboxOnAnotherTab").value = "this will throw an error";}catch(error){}
 event.target.value = "This will always work"; //sets the value of the input the event was executed on
 var inputs = document.querySelectorAll("input"); //will return input elements only on the current tab
}

Probably the easiest way to disallow DOM access to everything but the current tab would be to set the DOM functions to call, e.g., document.getElementById("whateverTheTabIdIs").getElementById("myinput") when the user runs document.getElementById("myinput"). 
@addydmasi:

I would like to add an id property to each setting:
{
  "id": "mySetting",
  "label": "my label",
  "description": "example select box",
  "type": "select",
  "values": ["one","two","three"]
},

And reference it as:
chrome.extensions.settings.mySetting.value

And I wouldn't use the function you propose but do something like: 
chrome.extensions.settings.mySetting.addListener('change', onchange);
And use this event to validate the setting or update something in the extension.

Also I think it is a good idea to define the settings in a separate json file so the extension manifest doesn't get cluttered
@addydmasi: 1. I was referring to the implementation of the variable access, e.g.
 chrome.extension.options.getTab("My tab").getValue("Alert \"Hello\" on startup")
 Where the "Alert \"Hello\" on startup" would be the variable name. And thats why I was asking whether the label name would be the variable name. 
 2. The danger of this would be of course that I can imagine users running havoc quite quickly, though it could work fairly well and would fairly complicated tabs. So overall I think it would be a really good thing you are proposing.
Comment 33 by qbawo...@gmail.com, Feb 22 2011
@potoms...:
It is better to store options as array or object?
{
 "options1": {
    "label": "My label"
 }
}
or:
[
 {
    "id": "options1,
    "label": "My label"
 }
]
in second approach we have order of options under control...

I agree that options options.json is good idea, but in manifest file we should can make a decision: define options in manifest file or put a string with options file name

@qbawo...@gmail.com
I think using arrays would be better because stuff like labels wouldn't normally need an id, and also so it is always in the order they are in inside the JSON file. 
You also might want to thing about grouping of settings, separated by horizontal lines or behind a popup. Similar to what is present in the tabbed settings today.
@qbawo...@gmail.com: Personally I think 
 {
 "options1": {
    "label": "My label"
 }
}
would be better, as it is *a lot* easier to have an overview. The disadvantage is of course that you should lose the order according to the specification, but I dont think that anybody would kill you for using the order as described in the object. 

Secondly I think it shouldn't be directly inside the manifest, as it can become quite lengthy.
@potoms...@gmail.com
We could just use {"type":"hr"} for that:

{
    /*...*/
    "options": {
        "title": "example",
        [
            /*...*/,
            {"type":"hr"},
            /*...*/
        ]
    }
}
@potoms....@gmail.com: Yeah, thats what type:label would be for in the implementation I was suggesting. You could then have a type:label with description:"<hr>", or even simply have type:seperator which would be even easier/better. The tabbed approach should also give enough grouping options to not need the popups. Reminds me, which HTML would be allowed in the descriptions? I would go for strong, i, bold, hr, maybe tables and that would probably be it. And another thing, it should also be possible to have buttons to link to other parts of the extension (e.g. type:button). Though this could alternatively be handled by the javascript implementation.

Gentlemen, though I appreciate the effort you are showing, this is not the right location to have a design discussion :). If you are serious about designing something, might I suggest you start a Google Code project and take the discussion there? Please cc me.

I'd just like to throw this out into the mix, to see what kind of response I'd get.

Suppose Chromium provided JS and CSS files for a developer's options page. The CSS would add default, customizable styling for an options page, and the JS would handle other styling and events, as well as a option-syncing API. For example,

<div class="-cr-tab"> creates a div that the JS and CSS recognize, and format as a tab. Then individual options could be styled as <input id="foo" class="-cr-textvalue">bar</input>, and then, similar to localStorage, the extension could use something like syncStorage.foo, which returns 'bar'. All of the syncing would be handled by Chromium's default JS file. A class like '-cr-nosync' could be applied to indicate that an element should be styled, but not synchronized.

It sounds simple to me. Developer choice is king, and nothing is synced or styled unless the developer wants it to be.
Now that DOMUI is Stable, could this issue be addressed by adding a section for Extensions to Options?  Searchable Extension settings would naturally follow from that.
Does this relate to  issue 52447  at all?  Perhaps as a dependency?
Comment 43 Deleted
Comment 44 by frnk...@me.com, May 22 2011
Hey guys! I just finished my project called "Fancy Settings".
It does exactly what you all want! Create settings from a manifest!

It has tabs, groups, search, and looks similar to Chrome's HTML settings.
You can create many types of settings, e.g. text, popupButton, radioButtons, button, etc.

It's of course open source and well documented, and you can get it here:
https://github.com/frankkohlhepp/fancy-settings
Comment 45 by dlom...@gmail.com, May 22 2011
This is perfect.
Awesome, Thanks.
Comment 47 by roly...@gmail.com, Dec 4 2011
@frnkkpp thank you that is really useful! You even added grouping/tabbing.
@frnkkpp: Awesome work, wow :) Are you planning to add a color chooser?
Has the fancy-settings project been abandoned?
something simple like the default settings page would really be a tremendous help!
I am guessing chrome team would not appreciate authors reusing chrome's settings UI (like chrome-bootstrap) as it could easily be used for phishing attacks. Not to mention the licensing issues...
Comment 53 by nav...@gtaero.net, Oct 23 2012
@brandom: Considering that this was filed by the Chromium team...  I think it's fine.
The problem only problem with fancy settings is the use of localStorage instead of chrome.storage to store the settings.

The disadvantage of this are the mandatory, resource intensive, background page necessary for content scripts to access settings even in extensions where just content script would suffice.

Besides, chrome.storage provides seamless integration with online storage and sync of chrome settings.f
Latest commit to any Fancy Settings fork is 8 months old. Chrome Bootstrap, on the other hand, is a quality reusable CSS styleguide. I believe we can update Fancy Settings to leverage chrome.storage and use Chrome Bootstrap to style it. It would make for a good contributed package for extension developers, but if we want this in Chrome we need to use the actual CSS the Chrome settings use.
The settings page uses chrome://resources/css/chrome_shared.css
The above file imports chrome://resources/css/widgets.css
Comment 57 Deleted
I've tried to link to those resources directly but they don't seem to be loaded.
Have you tried to use them?

Thanks
Comment 59 by mega...@gmail.com, Nov 23 2012
You cannot link to them directly; only chrome:// pages can load chrome:// files.
Comment 60 by nav...@gtaero.net, Feb 20 2013
Just trying to remind the Chrome team that this exists.

Would be very helpful for extension/app creators if they could plug in their settings for deeper integration.
Comment 61 Deleted
Comment 62 Deleted
Comment 63 by olos...@gmail.com, Mar 24 2013
Is there any documentation how to use this feature? 
Can we get an owner for this?
Comment 65 Deleted
Please don't update issues in this way, especially if you have nothing pertinent to say on the subject, and merely want an update.

If you are interested in participating in the development of this functionality, then please have at it.

However, if you wish to participate as an interested bystander, please star it, but don't bump or ping as it results in emails being sent out to all.

And yes, I'm aware of the irony that the same will happen with this message!
Comment 67 Deleted
Comment 68 by zmy...@gmail.com, Mar 14 2014
Since the library in #44 seems to no longer be available, here is my own version I wrote a few months ago: https://github.com/zmyaro/crx-options-page
Comment 69 by mega...@gmail.com, Mar 14 2014
I forgot about this bug.  I reverse engineered the current design for my own options page, greatly simplifying it in the process (I had no need for the uberframe or whatever it was called).

I didn't generalize it, but anyone is welcome to use what I've made for their own projects:

https://github.com/The-MAZZTer/GBCGCApp
Comment 70 by mega...@gmail.com, Mar 14 2014
Forgot to mention a few things about it:

- Doesn't use HTML5 standard tags like <nav>.  At some point I may go in and do that.  For now you get boring <div>s.
- Options are specified in a JSO and the page code for them is generated on-the-fly using DOM and specifically jQuery.  I think it's pretty sweet.  There are some general purpose things as well as special-purpose types for this app.
- In the code, $.create is a shortcut I made for $(arguments[0] ? document.createElement(arguments[0]) : document.createDocumentFragment()).  I try to avoid parsing HTML strings if I don't need to (old habit, I suspect it's relatively slower than pure JS DOM calls), which jQuery seems to encourage for making new nodes.
- This was one of my first jQuery projects (I was trying to learn it) so there's probably stuff that needs cleaning up in that regard).
- There is the glow outline over the tabs on the left... that wasn't there when I made it so it's likely a change in how Chrome is styling buttons since then or whatever.  A CSS outline: none; will get rid of that.
- There's no fancy CSS transitions between tabs like the official page because the way they did it needed their fancy complicated frames or somesuch.  I couldn't get it to work with my simplified variant.
- You'll need to make a saved state in the emulator to see one of the UI controls I made based off of the saved passwords table.  (I would probably get rid of the weird hover thing I did with the thumbnail if I went back to work on it more but that's not relevant to this conversation.)
- Chrome's page has a set min/max width, mine doesn't care and fills the whole width.
- This thing is pretty old but still matches the latest Settings style.  Yay!
Library in #68 does not have an indicated license; another candidate is https://github.com/roykolak/chrome-bootstrap which is MIT-licensed

Demo here: http://roykolak.github.io/chrome-bootstrap/
This is exciting news, but I have a question about the spec.

I have a link in my UI (popup or release notes page) that opens the options menu. The spec says that if I just navigate to the options page, you will open it in a tab (do nothing special). But what if I _want_ to open the new UI progrmmatically like the context menu item does?

I cannot rely on Chrome styling if there are situations when the CSS won't be injected.

There should be a new function in chrome.extension or chrome.runtime to display the new UI. Should I make it a separate feature request?
Comment 75 by roly...@gmail.com, Apr 25 2016
I made an implementation for this myself

https://github.com/fent/chrome-options

Made before I knew about fancy-settings or crx-options-page. It uses chrome-bootstrap for styling and structure. Supports adding tabs on the left, or no tabs, and work with the new version of options.

Anyway, there's more info about it on the readme.
Comment 76 by smaud...@gmail.com, Apr 25 2016
nice, thanks for sharing
Sign in to add a comment