The My Opera forums have been replaced with forums.opera.com. Please head over there to discuss Opera's products and features
See the new ForumsYou need to be logged in to post in the forums. If you do not have an account, please sign up first.
scriptStorage is always undefined
Hi!I tried to use opera.scriptStorage to let a user.js-script store informations between different pages.
However, The script tells me, that scriptStorage is undefined even though I set the script-storage-size in my config-page to 500...
I try following code:
if(window.opera){
var storage=window.opera.scriptStorage;
if(!storage){console.log("noscript");}else{
console.log("script");
GM_setValue=function(Name, Wert) {
storage.setItem(Name,Wert);
};
GM_getValue=function(Name) {
return storage.getItem(Name);
};
}
}
Everytime I try to run it, console.log("noscript"); is triggered!
Do you know if I'm using it wrong or didn't set the right settings for using it?
I need much storage in this script, so cookies would be too small!
I presume you're trying to use it in GM compatibility mode (.user.js), but many of Opera's UserJS features only work with .js.
The DnD Sanctuary — a safety net for My Opera's demise.
Thanks for the hint!
I tried to rewrite the script, so I don't need to GM-compatibility...
As the script should be working on a site that build itself dynamically, I first check-looped until there is something like a body.
and "window.opera.scriptStorage" is always undefined!
One funny thing: the page itself has some iframes for its advertisement... If I don't filter the url, the script will be running in those iframes, too, and there is a scriptStorage! But not the Elements I need for my script^^
Are there some pages that doesn't accept scriptStorage?
I tried to rewrite the script, so I don't need to GM-compatibility...
As the script should be working on a site that build itself dynamically, I first check-looped until there is something like a body.
if(window.opera){
var stopp=0;
var stopp2=0;
function bereit(){
var doomda= document.evaluate("//body",document.documentElement,null,XPathResult.ANY_TYPE,null).iterateNext();
if(doomda){stopp=5;stor();}
if(stopp<5){setTimeout(bereit,500);stopp++;}
}
function stor(){
if(window.opera.scriptStorage){stopp2=5;storage=window.opera.scriptStorage;start();}
if(stopp2<5){setTimeout(stor,1000);stopp2++;}
}
bereit();
}else{
start();
}
and "window.opera.scriptStorage" is always undefined!
One funny thing: the page itself has some iframes for its advertisement... If I don't filter the url, the script will be running in those iframes, too, and there is a scriptStorage! But not the Elements I need for my script^^
Are there some pages that doesn't accept scriptStorage?
Couldn't you just use addEventListener with DOMContentLoaded?
Anyway, got any URL or something for testing? Are you keeping a reference? See http://www.opera.com/docs/userjs/specs/#scriptstorage
Anyway, got any URL or something for testing? Are you keeping a reference? See http://www.opera.com/docs/userjs/specs/#scriptstorage
The DnD Sanctuary — a safety net for My Opera's demise.
Thank you for the link (read it some times already^^) and the idea!
If I use DOMContentLoaded document.body is empty!
I go there: http://whitewinged.deviantart.com/
with this:
to Topic: suddenly scriptStorage is available on the page!
Now, how to wait right for the body?^^
If I use DOMContentLoaded document.body is empty!
I go there: http://whitewinged.deviantart.com/
with this:
if(window.opera&&location.href.match(/http:\/\/.+\.deviantart\.com\/?$/i)){
opera.addEventListener('DOMContentLoaded', new function(){alert(document.body.innerHTML);}, false);
}
to Topic: suddenly scriptStorage is available on the page!
Now, how to wait right for the body?^^
DOMContentLoaded is a standard event type. Try using document.addEventListener()
And it's just function(){…} (i.e. no 'new') when defining a function within a event listener declaration. Though I couldn't tell you why.
And it's just function(){…} (i.e. no 'new') when defining a function within a event listener declaration. Though I couldn't tell you why.
MyOpera Community Enhancements — by xErath & BtEO
MyOpera Community Optimizations — by fearphage
Scribit improved posting tools for the MyOpera Community — by xErath
Improve Weeklies Blog — by MisterE & fearphage
MyOpera Community Optimizations — by fearphage
Scribit improved posting tools for the MyOpera Community — by xErath
Improve Weeklies Blog — by MisterE & fearphage
Thanks for the advice!
The event is triggered now, but the old problem pops up again!
It continues to give me "noscript"!
The event is triggered now, but the old problem pops up again!
var storage;
function start(){
if(!storage){console.log("noscript");}else{console.log("script");}
}
if(window.opera&&location.href.match(/http:\/\/.+\.deviantart\.com\/?$/i)){
document.addEventListener('DOMContentLoaded', function(){storage=window.opera.scriptStorage;start();}, false);
}
It continues to give me "noscript"!
Ahh, while the DOMContentLoaded only properly fires from document.addEventListener this has the side effect that it's no longer running in the User JavaScript thread, and doesn't have access to the special window.opera features. Try the following:
(function(){
if (window.opera) {
var storage = window.opera.scriptStorage;
function start(){
if(!storage){console.log("noscript");}else{console.log(storage);}
}
if(location.href.match(/http:\/\/.+\.deviantart\.com\/?$/i)){
document.addEventListener('DOMContentLoaded', start, false);
}
}
})();This wraps the whole script in an anonymous function (which you should be doing pretty much all the time unless you have a reason not to, it provides a degree of separation between your script and any scripts running on the page), and caches a reference to scriptStorage in the main UserJS thread local to the anonymous function. Because start() is also within that anonymous function it can access storage, but no script outside the anonymous function can see it, preventing any accidental leakage of scriptStorage's content.
MyOpera Community Enhancements — by xErath & BtEO
MyOpera Community Optimizations — by fearphage
Scribit improved posting tools for the MyOpera Community — by xErath
Improve Weeklies Blog — by MisterE & fearphage
MyOpera Community Optimizations — by fearphage
Scribit improved posting tools for the MyOpera Community — by xErath
Improve Weeklies Blog — by MisterE & fearphage
You can do that a little more succinctly like this:
Also, you can get Opera to restrict your script to a specific site with a special comment block at the top:
Add as many @include rules as you want and Opera will add the script whenever one of them matches the page URL.
(function(opera, storage){
//code goes here
})(window.opera, window.opera.scriptStorage);
Also, you can get Opera to restrict your script to a specific site with a special comment block at the top:
// ==UserScript== // @include http://*.deviantart.com/* // ==/UserScript==
Add as many @include rules as you want and Opera will add the script whenever one of them matches the page URL.
Opera 12.15 - Win 8 Pro x64 All my Opera tools -Tab Vault: Save tabs for later -AutoStack: tabs opened from a stack stay there
Thank you for your helpful scripts!
Everything works now, except for a event-problem:
If I define something like
obj.onclick=function(){alert(storage.getItem('test'));}
I get an "Referenceerror: security Violation" Exception.
Is there a way to use storage + events?
Everything works now, except for a event-problem:
If I define something like
obj.onclick=function(){alert(storage.getItem('test'));}
I get an "Referenceerror: security Violation" Exception.
Is there a way to use storage + events?
What happens if you try this?
obj.addEventListener('click', function() {
alert(storage.getItem('test'));
}, false);
Opera 12.15 - Win 8 Pro x64 All my Opera tools -Tab Vault: Save tabs for later -AutoStack: tabs opened from a stack stay there
Well, I found a way to use userscripts (.user.js) and scriptStorage, so I tried again to avoid addeventlistener, as this is not permitted...
But I found my error:
I wrote a function to add Events like this:
the security-error occured as I didn't wrote ...+"=callback" but ...+"="+callback; ^^
Now, everything is working fine^^
Thanks for your help!
But I found my error:
I wrote a function to add Events like this:
function eventmod(obj, event, callback){
var bef="obj.";
if(window.opera){
bef+="on"+event+"=callback";
}else{
if(document.addEventListener){
bef+="addEventListener('"+event+"',callback)";
}else{
bef+="attachEvent('on"+event+"',callback)";
}
}
eval(bef);
}
the security-error occured as I didn't wrote ...+"=callback" but ...+"="+callback; ^^
Now, everything is working fine^^
Thanks for your help!
Originally posted by dediggefedde:
Well, I found a way to use userscripts (.user.js) and scriptStorage, so I tried again to avoid addeventlistener, as this is not permitted...
I'm not sure what you mean by this. addEventListener is always permitted. window.opera.addEventListener is not permitted in GM mode (*.user.js) but <object>.addEventListener is never forbidden.
Opera 12.15 - Win 8 Pro x64 All my Opera tools -Tab Vault: Save tabs for later -AutoStack: tabs opened from a stack stay there
Originally posted by spadija:
window.opera.addEventListener is not permitted in GM mode
I'd phrase that as "not available." Not permitted is rendering certain things to canvas. </nitpick>
The DnD Sanctuary — a safety net for My Opera's demise.
Same difference.
Actually, scriptStorage shouldn't be available in GM mode either, so I'm surprised you were able to get it to work.
I don't recommend using eval() though. If there is any possibility that an untrusted page can call your eventmod function, you're letting the page call anything it wants with access to anything in eventmod's scope. For example, if I call this:
and eventmod has access to window.opera.scriptStorage, I just tricked your function into clearing all the data stored by your script.
Actually, scriptStorage shouldn't be available in GM mode either, so I'm surprised you were able to get it to work.
I don't recommend using eval() though. If there is any possibility that an untrusted page can call your eventmod function, you're letting the page call anything it wants with access to anything in eventmod's scope. For example, if I call this:
eventmod(window, "click=function(){}; window.opera.scriptStorage.clear(); a", null) and eventmod has access to window.opera.scriptStorage, I just tricked your function into clearing all the data stored by your script.
Opera 12.15 - Win 8 Pro x64 All my Opera tools -Tab Vault: Save tabs for later -AutoStack: tabs opened from a stack stay there
Ah, thanks for your advices!
Sorry I said it wrong: I'm using a user.js now, but with a Gm-emulator (as a .js-file) from here: http://userscripts.org/scripts/show/105153
with that, scriptstorage is available within user.js...
I tried to use addEventListener, but somehow it didin't work in Opera, so I worked with onevent=function...
As I wanted to write a cross-browser-script, and firefox seem to not like onevents, (and IE only attachevent) I wrote this function...
@spadija:
Thanks for your advice!
I don't know, which functions are available to other scripts... I thought, eventmod would be only available to my script as I'm using it in a anonymous function... I think I will not pass a function but an index to a defined function into this to prevent this abuse... Is that enough or can someone then manipulate those defined functions?
Sorry I said it wrong: I'm using a user.js now, but with a Gm-emulator (as a .js-file) from here: http://userscripts.org/scripts/show/105153
with that, scriptstorage is available within user.js...
I tried to use addEventListener, but somehow it didin't work in Opera, so I worked with onevent=function...
As I wanted to write a cross-browser-script, and firefox seem to not like onevents, (and IE only attachevent) I wrote this function...
@spadija:
Thanks for your advice!
I don't know, which functions are available to other scripts... I thought, eventmod would be only available to my script as I'm using it in a anonymous function... I think I will not pass a function but an index to a defined function into this to prevent this abuse... Is that enough or can someone then manipulate those defined functions?
There is no reason addEventListener should be failing. How are you trying to use it?
As for the security concern, generally if you wrap everything in an anonymous function, you should be safe, but you have to be careful about scope leakage. Here's an example of what I mean. If you give something in global scope a reference to a scope inside your anonymous function, the anonymous function no longer hides the object being referenced. Also, note that, unlike with the on____ events, if you use addEventListener to attach event listeners, you cannot get a reference to the listener function once it is attached. The example I created uses document.onclick to get a reference to the foo function inside the anonymous function, but had I used document.addEventListener('click', foo, false) instead, the code in global scope would have no way of getting to the foo function.
Also, eval() is slower than running regular code. The best practice would be to avoid using eval() unless you really have a good reason to use it.
As for the security concern, generally if you wrap everything in an anonymous function, you should be safe, but you have to be careful about scope leakage. Here's an example of what I mean. If you give something in global scope a reference to a scope inside your anonymous function, the anonymous function no longer hides the object being referenced. Also, note that, unlike with the on____ events, if you use addEventListener to attach event listeners, you cannot get a reference to the listener function once it is attached. The example I created uses document.onclick to get a reference to the foo function inside the anonymous function, but had I used document.addEventListener('click', foo, false) instead, the code in global scope would have no way of getting to the foo function.
Also, eval() is slower than running regular code. The best practice would be to avoid using eval() unless you really have a good reason to use it.
Opera 12.15 - Win 8 Pro x64 All my Opera tools -Tab Vault: Save tabs for later -AutoStack: tabs opened from a stack stay there
Ah... Thank you very much for the example about the global scope!
I think I'm quite safe from this problems, as I don't set a eval-function to the on-events, but only functions that searches the pages for elements and alter its content... I use eval only script-intern...
I think, eval is the only way to change the way of events depending of the browser, isn't it?
I was using document.getElementById('uid').addEventListener('click',function(){alert('test');});
however, there is simply no reaction to this code^^
if I write document.getElementById('uid').onclick=function(){alert('test');};
everything seems to be fine^^
I think I'm quite safe from this problems, as I don't set a eval-function to the on-events, but only functions that searches the pages for elements and alter its content... I use eval only script-intern...
I think, eval is the only way to change the way of events depending of the browser, isn't it?
I was using document.getElementById('uid').addEventListener('click',function(){alert('test');});
however, there is simply no reaction to this code^^
if I write document.getElementById('uid').onclick=function(){alert('test');};
everything seems to be fine^^
Originally posted by spadija:
Same difference.
Nuhuh. The error message is completely different.
(But yes, in practice it doesn't work so there's no difference in that regard.)Originally posted by dediggefedde:
I was using document.getElementById('uid').addEventListener('click',function(){alert('test');});
Wfm in Opera 11.60, however in 11.50 and earlier you have to add the ,false since it doesn't default to that.
The DnD Sanctuary — a safety net for My Opera's demise.
Yep. addEventListener takes three arguments. the last one is only useful when you need to change the order events happen in, so you usually leave it as false. In 11.50 and earlier, the function silently fails if you omit the last argument, though will be fixed in 11.60+.
Opera 12.15 - Win 8 Pro x64 All my Opera tools -Tab Vault: Save tabs for later -AutoStack: tabs opened from a stack stay there