localStorage script broken in Manifest 2 extension

802 views
Skip to first unread message

Corbin Davenport

unread,
Aug 16, 2012, 5:01:07 PM8/16/12
to chromi...@chromium.org
A while ago I migrated my Wikipedia Search extension to Manifest 2 and almost everything works. In my extension, the extension options page has a list of available languages. You select one from the list and it saves using localStorage. The problem is that it does not work in the latest version of Wikipedia Search. The script is based on an old Chrome API example so I'm guessing that something changed. Can anyone help?

<script type="text/javascript">

// Saves options to localStorage.
function save_options() {
  var select = document.getElementById("language");
  var language = select.children[select.selectedIndex].value;
  localStorage["favorite_color"] = language;

  // Update status to let user know options were saved.
  var status = document.getElementById("status");
  status.innerHTML = "Saved!";
  setTimeout(function() {
    status.innerHTML = "";
  }, 750);
}

// Restores select box state to saved value from localStorage.
function restore_options() {
  var favorite = localStorage["favorite_color"];
  if (!favorite) {
    return;
  }
  var select = document.getElementById("language");
  for (var i = 0; i < select.children.length; i++) {
    var child = select.children[i];
    if (child.value == favorite) {
      child.selected = "true";
      break;
    }
  }
}

</script>

Thanks in advance!

Corbin Davenport

unread,
Aug 17, 2012, 3:54:32 PM8/17/12
to chromi...@chromium.org
Bump...

Joshua Woodward

unread,
Aug 17, 2012, 4:00:16 PM8/17/12
to Corbin Davenport, chromi...@chromium.org
The code you have shared doesn't appear to have any chrome extension API specific code.

Can you share more, or are you getting any errors in devtools you can provide?

On Fri, Aug 17, 2012 at 12:54 PM, Corbin Davenport <davenpo...@gmail.com> wrote:
Bump...

--
You received this message because you are subscribed to the Google Groups "Chromium Apps" group.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msg/chromium-apps/-/RvAtVyMJLQ8J.
To post to this group, send email to chromi...@chromium.org.
To unsubscribe from this group, send email to chromium-app...@chromium.org.
For more options, visit this group at http://groups.google.com/a/chromium.org/group/chromium-apps/?hl=en.



--



Twitter - @howtohtml5

Abraham Williams

unread,
Aug 17, 2012, 4:02:15 PM8/17/12
to Corbin Davenport, chromi...@chromium.org
Move the code to a js file and use <script type="text/javascript" src="file.js"></script> instead.

Abraham
--
Abraham Williams | abrah.am | abraham+ | addvocate.co
@abraham | github.com/abraham | blog.abrah.am
This email is: [ ] shareable [x] ask first [ ] private.



--
You received this message because you are subscribed to the Google Groups "Chromium Apps" group.

Joshua Woodward

unread,
Aug 17, 2012, 4:25:01 PM8/17/12
to Abraham Williams, Corbin Davenport, chromi...@chromium.org
type="text/javascript" is no longer required, especially if using <!DOCTYPE html> (HTML5), javascript is the default

Just saved 24 bytes per script tag ;)

Corbin Davenport

unread,
Aug 17, 2012, 5:05:27 PM8/17/12
to chromi...@chromium.org
None of those suggestions seemed to work. However I did run it in the Developer's Tools console and it said: Refused to execute inline event handler because it violates the following Content Security Policy directive: "script-src 'self' chrome-extension-resource:".

Since you said more code might help, here's basically the entire extension:

Options page:

<html>
<head>
<title>Wikipedia Search - Options</title>
<link rel="icon" type="image/png" href="icon16.png">
<script" src="language.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
[useless css code]
</style>
</head>
<body onLoad="restore_options()">
<div align="center">
<img src="icon.png"><br />
<b>Wikipedia Search 3.1</b><br />By Corbin Davenport<br />
<div id="content"><select name="language" size="10" id="language">
<option value="ar" lang="ar">العربية</option><!-- Al-ʿArabīyah --> 
<option value="bg" lang="bg">Български</option><!-- Bulgarski --> 
<option value="ca" lang="ca">Català</option> 
<option value="cs" lang="cs">Česky</option> 
<option value="da" lang="da">Dansk</option> 
<option value="de" lang="de">Deutsch</option> 
<option value="en" lang="en" selected="selected">English</option> 
<option value="es" lang="es">Español</option> 
<option value="eo" lang="eo">Esperanto</option> 
<option value="eu" lang="eu">Euskara</option> 
<option value="fa" lang="fa">فارسی</option><!-- Fārsi --> 
<option value="fr" lang="fr">Français</option> 
<option value="ko" lang="ko">한국어</option><!-- Hangugeo --> 
<option value="hi" lang="hi">हिन्दी</option><!-- Hindī --> 
<option value="id" lang="id">Bahasa Indonesia</option> 
<option value="it" lang="it">Italiano</option> 
<option value="he" lang="he">עברית</option><!-- 'Ivrit --> 
<option value="lt" lang="lt">Lietuvių</option> 
<option value="hu" lang="hu">Magyar</option> 
<option value="ms" lang="ms">Bahasa Melayu</option> 
<option value="nl" lang="nl">Nederlands</option> 
<option value="ja" lang="ja">日本語</option><!-- Nihongo --> 
<option value="no" lang="nb">Norsk (bokmål)</option> 
<option value="pl" lang="pl">Polski</option> 
<option value="pt" lang="pt">Português</option> 
<option value="kk" lang="kk">Қазақша / Qazaqşa / قازاقشا</option> 
<option value="ro" lang="ro">Română</option> 
<option value="ru" lang="ru">Русский</option><!-- Russkiy --> 
<option value="sk" lang="sk">Slovenčina</option> 
<option value="sl" lang="sl">Slovenščina</option> 
<option value="sr" lang="sr">Српски / Srpski</option> 
<option value="fi" lang="fi">Suomi</option> 
<option value="sv" lang="sv">Svenska</option> 
<option value="tr" lang="tr">Türkçe</option> 
<option value="uk" lang="uk">Українська</option><!-- Ukrayins'ka --> 
<option value="vi" lang="vi">Tiếng Việt</option> 
<option value="vo" lang="vo">Volapük</option> 
<option value="war" lang="war">Winaray</option> 
<option value="zh" lang="zh">中文</option><!-- Zhōngwén --> 
</select><table width="100%" border="0" cellpadding="0" cellspacing="0">
  <tr>
    <td><div id="status"></div></td>
    <td width="80"><input type="button" onClick="window.location.reload()" value="Cancel" /></td>
    <td width="80" style="text-align:right"><input type="button" onClick="save_options()" value="Save" /></td>
  </tr>
</table>
</div>
</div>
</body>
</html>

Extension pop-up page:

<!DOCTYPE html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css">
[more useless CSS code]
</style>
<script" src="language.js"></script>
</head>
<body onload="restore_options()">
<form id="searchform" action="http://www.wikipedia.org/search-redirect.php" target="_blank"> 
<input id="searchInput" class="textfield" name="search" type="text" placeholder="Type to search..." autofocus /> 

<select id="language" name="language">
 <option value="ar" lang="ar">العربية</option><!-- Al-ʿArabīyah --> 
<option value="bg" lang="bg">Български</option><!-- Bulgarski --> 
<option value="ca" lang="ca">Català</option> 
<option value="cs" lang="cs">Česky</option> 
<option value="da" lang="da">Dansk</option> 
<option value="de" lang="de">Deutsch</option> 
<option value="en" lang="en" selected="selected">English</option> 
<option value="es" lang="es">Español</option> 
<option value="eo" lang="eo">Esperanto</option> 
<option value="eu" lang="eu">Euskara</option> 
<option value="fa" lang="fa">فارسی</option><!-- Fārsi --> 
<option value="fr" lang="fr">Français</option> 
<option value="ko" lang="ko">한국어</option><!-- Hangugeo --> 
<option value="hi" lang="hi">हिन्दी</option><!-- Hindī --> 
<option value="id" lang="id">Bahasa Indonesia</option> 
<option value="it" lang="it">Italiano</option> 
<option value="he" lang="he">עברית</option><!-- 'Ivrit --> 
<option value="lt" lang="lt">Lietuvių</option> 
<option value="hu" lang="hu">Magyar</option> 
<option value="ms" lang="ms">Bahasa Melayu</option> 
<option value="nl" lang="nl">Nederlands</option> 
<option value="ja" lang="ja">日本語</option><!-- Nihongo --> 
<option value="no" lang="nb">Norsk (bokmål)</option> 
<option value="pl" lang="pl">Polski</option> 
<option value="pt" lang="pt">Português</option> 
<option value="kk" lang="kk">Қазақша / Qazaqşa / قازاقشا</option> 
<option value="ro" lang="ro">Română</option> 
<option value="ru" lang="ru">Русский</option><!-- Russkiy --> 
<option value="sk" lang="sk">Slovenčina</option> 
<option value="sl" lang="sl">Slovenščina</option> 
<option value="sr" lang="sr">Српски / Srpski</option> 
<option value="fi" lang="fi">Suomi</option> 
<option value="sv" lang="sv">Svenska</option> 
<option value="tr" lang="tr">Türkçe</option> 
<option value="uk" lang="uk">Українська</option><!-- Ukrayins'ka --> 
<option value="vi" lang="vi">Tiếng Việt</option> 
<option value="vo" lang="vo">Volapük</option> 
<option value="war" lang="war">Winaray</option> 
<option value="zh" lang="zh">中文</option><!-- Zhōngwén --> 
</select>
<input class="searchButton" type="submit" value="  →  " name="go" style="display:none" /> 
<input type="hidden" value="Go" name="go" style="display:none" />
</form>
</body>
</html>

Language.js

// Saves options to localStorage.
function save_options() {
  var select = document.getElementById("language");
  var language = select.children[select.selectedIndex].value;
  localStorage["favorite_color"] = language;

  // Update status to let user know options were saved.
  var status = document.getElementById("status");
  status.innerHTML = "Saved!";
  setTimeout(function() {
    status.innerHTML = "";
  }, 750);
}

// Restores select box state to saved value from localStorage.
function restore_options() {
  var favorite = localStorage["favorite_color"];
  if (!favorite) {
    return;
  }
  var select = document.getElementById("language");
  for (var i = 0; i < select.children.length; i++) {
    var child = select.children[i];
    if (child.value == favorite) {
      child.selected = "true";
      break;
    }
  }
}

This is basically all the code in the entire extension. Any help would be very much appreciated :)

Abraham Williams

unread,
Aug 17, 2012, 5:08:53 PM8/17/12
to Corbin Davenport, chromi...@chromium.org
The first Google result for "Refused to execute inline event handler" was a Stack Overflow answer that covers your situation nicely.



Abraham
--
Abraham Williams | abrah.am | abraham+ | addvocate.co
@abraham | github.com/abraham | blog.abrah.am
This email is: [ ] shareable [x] ask first [ ] private.



--
You received this message because you are subscribed to the Google Groups "Chromium Apps" group.

Joshua Woodward

unread,
Aug 17, 2012, 5:09:57 PM8/17/12
to Corbin Davenport, chromi...@chromium.org
so in body, where you have onload, that is not allowed anymore

also any inline script, like onclick or anything, is not allowed in v2 either

for body do....  

document.body.addEventListener('load',function(){
 var favorite = localStorage["favorite_color"];
  if (!favorite) {
    return;
  }
  var select = document.getElementById("language");
  for (var i = 0; i < select.children.length; i++) {
    var child = select.children[i];
    if (child.value == favorite) {
      child.selected = "true";
      break;
    }
  }
});

and similar for onclicks or others

document.getElementById( {elem id} ).addEventListener('click',function(){

});

OR

document.getElementById( {elem id} ).addEventListener( {event}, {function name});

On Fri, Aug 17, 2012 at 2:05 PM, Corbin Davenport <davenpo...@gmail.com> wrote:
--
You received this message because you are subscribed to the Google Groups "Chromium Apps" group.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msg/chromium-apps/-/jFGHgGEPiGoJ.

To post to this group, send email to chromi...@chromium.org.
To unsubscribe from this group, send email to chromium-app...@chromium.org.
For more options, visit this group at http://groups.google.com/a/chromium.org/group/chromium-apps/?hl=en.

Joe Marini

unread,
Aug 17, 2012, 5:10:08 PM8/17/12
to Corbin Davenport, chromi...@chromium.org
Ah, there's your problem. Content Security Policy disallows the use of inline event handlers (you can't use "onxxx=func()".).

Put the code into the JS file and use addEventListener.

Joe



On Fri, Aug 17, 2012 at 2:05 PM, Corbin Davenport <davenpo...@gmail.com> wrote:

--
You received this message because you are subscribed to the Google Groups "Chromium Apps" group.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msg/chromium-apps/-/jFGHgGEPiGoJ.

To post to this group, send email to chromi...@chromium.org.
To unsubscribe from this group, send email to chromium-app...@chromium.org.
For more options, visit this group at http://groups.google.com/a/chromium.org/group/chromium-apps/?hl=en.



--
Joe Marini
Developer Advocate / Chrome


Corbin Davenport

unread,
Aug 17, 2012, 6:23:57 PM8/17/12
to chromi...@chromium.org
Hello everyone!

First off, thanks for all your suggestions. Now when I click the Save button on the Options page it displays the 'Saved!' message. However when I search in the extension it only goes to English Wikipedia. I did the Console on the options page again and it said: Uncaught TypeError: Cannot call method 'addEventListener' of null

Here's the new language.js file, with all of the additions you guys suggested:

// Saves options to localStorage.
function save_options() {
  var select = document.getElementById("language");
  var language = select.children[select.selectedIndex].value;
  localStorage["favorite_color"] = language;

  // Update status to let user know options were saved.
  var status = document.getElementById("status");
  status.innerHTML = "Saved!";
  setTimeout(function() {
    status.innerHTML = "";
  }, 750);
}

// Restores select box state to saved value from localStorage.
function restore_options() {
  var favorite = localStorage["favorite_color"];
  if (!favorite) {
    return;
  }
  var select = document.getElementById("language");
  for (var i = 0; i < select.children.length; i++) {
    var child = select.children[i];
    if (child.value == favorite) {
      child.selected = "true";
      break;
    }
  }
}

// Replaces onclick for the Save button
window.onload = function(){
    document.querySelector('input[value="Save"]').onclick=save_options;
}

// Replaces body onLoad
document.body.addEventListener('load',function(){
 var favorite = localStorage["favorite_color"];
  if (!favorite) {
    return;
  }
  var select = document.getElementById("language");
  for (var i = 0; i < select.children.length; i++) {
    var child = select.children[i];
    if (child.value == favorite) {
      child.selected = "true";
      break;
    }
  }
});

Thanks again for your help so far!

Mihai Parparita

unread,
Aug 17, 2012, 6:31:49 PM8/17/12
to Corbin Davenport, chromi...@chromium.org
I'm guessing that your script is included in the <head> section of the page, so the page body doesn't exist yet.

Instead of document.body.addEventListener, you should use window.addEventListener.

Mihai

--
You received this message because you are subscribed to the Google Groups "Chromium Apps" group.

Corbin Davenport

unread,
Aug 17, 2012, 6:47:13 PM8/17/12
to chromi...@chromium.org
Thank you so much Mihai, that worked!

Thanks guys for helping me out everyone, now my 5,000+ users will be happy :D
Reply all
Reply to author
Forward
0 new messages