I'm writing a restartless Firefoxextension where I have to enumerate all open tabs and work with them.
Here's the code-part that throws the error:
getInfoString : function ()
{
infos = "";
HELPER.alerting("url", "URL-Function");
var winMediator = Components.classes["#mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator);
HELPER.alerting("url", "Mediator initialized");
var mrw = winMediator.getEnumerator(null);
while(mrw.hasMoreElements())
{
var win = mrw.getNext();
var t = win.gBrowser.browsers.length;
HELPER.alerting("url", "browsers: " + t);
for (var i = 0; i < t; i++)
{
var b = win.gBrowser.getBrowserAtIndex(i);
if(b.currentURI.spec.substr(0,3) != "http")
{
continue;
}
HELPER.alerting(b.title,b.currentURI.spec);
var doc = b.contentDocument;
var src = doc.documentElement.innerHTML;
infos = infos + src
HELPER.alerting("doc", src);
}
}
return infos;
}
I have a JavascriptDebugger-Addon running while testing this and Firefox executes everything fine to the line
HELPER.alerting("url", "browsers: " + t);
But AFTER this line, the debugger-addons throws an error, saying that:
win.gBrowser is undefined
... pointing to the line:
var t = win.gBrowser.browsers.length;
But before it throws the error I get my alertmessage which gives me the correct number of tabs. So the error is thrown after the line was executed and not directly WHEN it was executed.
Does anyone has an idea how to fix this, because the extension stops working after the error has been thrown.
Greetz
P.S.: If someone has a better headline for this, feel free to edit it.
Using winMediator.getEnumerator(null) would give you all types of window, that may or may not be browser windows. You should try changing the following line
var mrw = winMediator.getEnumerator(null);
with
var mrw = winMediator.getEnumerator('navigator:browser');
I finally figured out that this behavior can happen sometimes.
I just rearranged the code a bit, removing some alerts inside the for-loop and it works just fine again.
So if someone has this error too, just rearrange your code and it should work like a charm again.
Related
I'm creating some scripts voor InDesign to speed up the process.
I have created a script where a certain line, I think, should work but InDesign disagrees.
It fails on ("Geen"||"None"); in the following
app.changeGrepPreferences.appliedCharacterStyle = myDoc.characterStyles.item("[Geen]"||"[None]");
I expect it to change to a characterStyle [Geen] or [None]. Depending on what is available in the predefined character styles.
What am I doing wrong? This seems kinda basic.
Unfortunately is not that easy. If you use doc.characterStyles.item('foo') it still will give you an [object CharacterStyle]. Even tough it does not exsist.
var doc = app.activeDocument;
$.writeln(doc.characterStyles.item('foo'));
// writes [object CharacterStyle] into the console
What you can do is use a try{}catch(error){} block and ask for the name property of that object. In that case InDesign will throw an error that you can catch. Then you can fall back to the default character style [None]
var doc = app.activeDocument;
try{
$.writeln(doc.characterStyles.item('foo').name);
}catch(e) {
$.writeln(e);
$.writeln(doc.characterStyles.item('[None]').name);
}
Edit: As mentioned by mdomino. You can use the isValid property.
var doc = app.activeDocument;
if(doc.characterStyles.item('foo').isValid === true) {
$.writeln('doc.characterStyles.item(\'foo\') exists');
} else {
$.writeln('use doc.characterStyles.item(\'[None]\') because ');
var defaultStyle = doc.characterStyles.item('[None]');
$.writeln(defaultStyle.name + ' is ' + defaultStyle.isValid);
}
i'm developing a phonegap app using a lot of javascript. Now i'm debugging it using Safari Developer Tool, in particular i'm focused on some button that on the device seems to be a bit luggy.
So I've added some console.timeEnd() to better understand where the code slow down, but the "problem" is that when i open the console the code start running faster without lag, if i close it again, the lag is back.
Maybe my question is silly but i can't figure it out
Thanks
EDIT: Added the code
function scriviNumeroTastiera(tasto){
console.time('Funzione ScriviNumeroTastiera');
contenutoInput = document.getElementById('artInserito').value;
if ($('#cursoreImg').css('display') == 'none'){
//$('#cursoreImg').show();
}
else if (tasto == 'cancella'){
//alert(contenutoInput.length);
if (contenutoInput.length == 0) {
}
else {
indicePerTaglioStringa = (contenutoInput.length)-1;
contenutoInput = contenutoInput.substr(0, indicePerTaglioStringa);
$('#artInserito').val(contenutoInput);
//alert('tastoCanc');
margineAttualeImg = $('#cursoreImg').css('margin-left');
indicePerTaglioStringa = margineAttualeImg.indexOf('p');
margineAttualeImg = margineAttualeImg.substr(0, indicePerTaglioStringa);
margineAggiornato = parseInt(margineAttualeImg)-20;
$('#cursoreImg').css('margin-left', margineAggiornato+'px');
}
}
else {
//contenutoInput = document.getElementById('artInserito').value;
contenutoAggiornato = contenutoInput+tasto;
margineAttualeImg = $('#cursoreImg').css('margin-left');
indicePerTaglioStringa = margineAttualeImg.indexOf('p');
margineAttualeImg = margineAttualeImg.substr(0, indicePerTaglioStringa);
margineAggiornato = parseInt(margineAttualeImg)+20;
$('#cursoreImg').css('margin-left', margineAggiornato+'px');
$('#artInserito').val(contenutoAggiornato);
}
console.timeEnd('Funzione ScriviNumeroTastiera');
}
The code is a bit crappy, but it's just a beginning ;)
This could happen because PhoneGap/Cordova creates its own console object (in cordova.js), and it gets overwritten when you open the Safari console (safari's might be faster than phonegap's, that could be why you notice it faster).
So, one way to measure the time properly, without opening the console, would be to go to the good old alert, so you'd first add this code anywhere in your app:
var TIMER = {
start: function(name, reset){
if(!name) { return; }
var time = new Date().getTime();
if(!TIMER.stimeCounters) { TIMER.stimeCounters = {} };
var key = "KEY" + name.toString();
if(!reset && TIMER.stimeCounters[key]) { return; }
TIMER.stimeCounters[key] = time;
},
end: function(name){
var time = new Date().getTime();
if(!TIMER.stimeCounters) { return; }
var key = "KEY" + name.toString();
var timeCounter = TIMER.stimeCounters[key];
if(timeCounter) {
var diff = time - timeCounter;
var label = name + ": " + diff + "ms";
console.info(label);
delete TIMER.stimeCounters[key];
}
return diff;
}
};
(This just mimics the console.time and console.timeEnd methods, but it returns the value so we can alert it).
Then, instead of calling:
console.time('Funzione ScriviNumeroTastiera');
you'd call:
TIMER.start('Funzione ScriviNumeroTastiera');
and instead of calling:
console.timeEnd('Funzione ScriviNumeroTastiera');
you'd call:
var timeScriviNumeroTastiera = TIMER.end('Funzione ScriviNumeroTastiera');
alert('Ellapsed time: ' + timeScriviNumeroTastiera);
This would give you the proper ellapsed time without opening the console, so it computes the real time in the phonegap app.
Hope this helps.
Cheers
This really isn't something you would normally expect - opening the console should not speed up anything. If anything, it will make things slower because of additional debugging hooks and status display. However, I've had a case like that myself. The reason turned out to be very simple: opening the console makes the displayed portion of the website smaller and the code efficiency was largely dependent on the viewport size. So if I am right, making the browser window smaller should have the same effect as opening the console.
I have a Windows app that contains a browser control that loads pages from my website. However, due to the Windows app, I cannot debug Javascript in the usual ways (Firebug, console, alerts, etc).
I was hoping to write a jQuery plug-in to log to an external browser window such that I can simply do something like:
$.log('test');
So far, with the following, I am able to create the window and display the templateContent, but cannot write messages to it:
var consoleWindow;
function getConsoleWindow() {
if (typeof (consoleWindow) === 'undefined') {
consoleWindow = createConsoleWindow();
}
return consoleWindow;
}
function createConsoleWindow() {
var newConsoleWindow = window.open('consoleLog', '', 'status,height=200,width=300');
var templateContent = '<html><head><title>Console</title></head>' +
'<body><h1>Console</h1><div id="console">' +
'<span id="consoleText"></span></div></body></html>';
newConsoleWindow.document.write(templateContent);
newConsoleWindow.document.close();
return newConsoleWindow;
}
function writeToConsole(message) {
var console = getConsoleWindow();
var consoleDoc = console.document.open();
var consoleMessage = document.createElement('span');
consoleMessage.innerHTML = message;
consoleDoc.getElementById('consoleText').appendChild(consoleMessage);
consoleDoc.close();
}
jQuery.log = function (message) {
if (window.console) {
console.log(message);
} else {
writeToConsole(message);
}
};
Currently, getElementById('consoleText') is failing. Is what I'm after possible, and if so, what am I missing?
Try adding
consoleDoc.getElementById('consoleText');
right before
consoleDoc.getElementById('consoleText').appendChild(consoleMessage);
If the line you added is the one that fails, then that means consoleDoc is not right, if the next line is the only one that fails then ..ById('consoleText') is not matching up
If I don't close() the document, it appears to work as I hoped.
I grabbed a bit of code to do some paging with jQuery, via Luca Matteis here
Paging Through Records Using jQuery
I've made some edits to the paging script so that I can use the same code to provide paging of different content in different locations on the same site.
For the most part, I think it works, except that I get a jsonObj is undefined error in firebug.
When I use alert(jsonObj.toSource()), I am shown the variables that I am trying to populate, but at the same time, the script dies because of the error.
I can't figure out why I am getting this conflict of 'undefined' and yet I can easily out put the 'undefined' values in an alert. I can even say alert(jsonObj.name), and it will give me that value, but still launch an jsonObj is undefined error.
Here's the code I'm using
var pagedContent = {
data: null
,holder: null
,currentIndex : 0
,init: function(data, holder) {
this.data = data;
this.holder=holder;
this.show(0); // show last
}
,show: function(index) {
var jsonObj = this.data[index];
if(!jsonObj) {
return;
}
var holdSubset='';
for(i=0;i<=4; i++){
jsonObj=this.data[index+i];
this.currentIndex = index;
if(this.holder=='div#firstList'){
var returnedId = jsonObj.id;
var returnedName = jsonObj.name;
var calcScore=this.data[index+i].score/this.data[0].score*100;
var resultInput="<div ' id='"+returnedId+"'><div class='name'>"+returnedName+"</div><div class='score'><div style='width:"+calcScore+"%;'></div></div>";
}
if(this.holder=='div#secondList'){
var name=jsonObj.name;
var city=jsonObj.city;
var region=jsonObj.state;
var resultInput='<li><div>'+name+'</div<div>'+city+'</div><div>'+region+'</div></li>';
}
holdSubset= holdSubset+resultInput;
}
jQuery(this.holder).html('<br/>'+holdSubset);
if(index!=0){
var previous = jQuery("<a>").attr("href","#").click(this.previousHandler).text("< previous");
jQuery(this.holder).append(previous);
}
if(index+i<this.data.length){
var next = jQuery("<a style='float:right;'>").attr("href","#").click(this.nextHandler).text("next >");
jQuery(this.holder).append(next);
}
}
,nextHandler: function() {
pagedContent.show(pagedContent.currentIndex + 5);
return false;
}
,previousHandler: function() {
pagedContent.show(pagedContent.currentIndex - 5);
return false
}
};
I call the function like this
pagedContent.init(json.users.locations, 'div#secondList');
The json looks like this
{"locations" : [ {"id":"21319","name":"Naugatuck American Legion","city":"Ansonia","region":"Connecticut"},{"id":"26614","name":"Studio B789","city":"Acton","region":"Maine"},{"id":"26674","name":"Deering Grange Hall","city":"Bailey Island","region":"Maine"},{"id":"27554","name":"Accu Billiards","city":"Acushnet","region":"Massachusetts"}]}
I may have found the problem with your code:
for(i=0;i<=4; i++){
jsonObj=this.data[index+i];
(...)
When you call show(0) you set index to 0. You expect a fixed number of items in the array (5 in the range [0..4]) but there are only 4 locations in your data.
If you are using console.log to trace the problems in firebug you might find that it is a problem with firebug. Try just running console.log on it's own.
If it is a problem with firebug try updating it. There are some development versions around which might fix the problem.
I had a similar problem and fixed it by doing the above.
I'm initiating an email create, by calling the code below, and adding an attachment to it.
I want the user to be able to type in the receipient, and modify the contents of the message, so I'm not sending it immediately.
Why do I get a RangeError the 2nd time the method is called?
(The first time it works correctly.)
function NewMailItem(p_recipient, p_subject, p_body, p_file, p_attachmentname)
{
try
{
var objO = new ActiveXObject('Outlook.Application');
var objNS = objO.GetNameSpace('MAPI');
var mItm = objO.CreateItem(0);
mItm.Display();
if (p_recipient.length > 0)
{
mItm.To = p_recipient;
}
mItm.Subject = p_subject;
if (p_file.length > 0)
{
var mAts = mItm.Attachments;
mAts.add(p_file, 1, p_body.length + 1, p_attachmentname);
}
mItm.Body = p_body;
mItm.GetInspector.WindowState = 2;
} catch(e)
{
alert('unable to create new mail item');
}
}
The error is occuring on the mAts.add line. So when it tries to attach the document, it fails.
Also the file name (p_file) is a http address to a image.
Won't work outside of IE, the user needs to have Outlook on the machine and an account configured on it. Are you sure you want to send an email this way?
I'm trying it with this little snippet, and it works flawlessly:
var objO = new ActiveXObject('Outlook.Application');
var mItm = objO.CreateItem(0);
var mAts = mItm.Attachments;
var p_file = [
"http://stackoverflow.com/content/img/vote-arrow-up.png",
"http://stackoverflow.com/content/img/vote-arrow-down.png"
];
for (var i = 0; i < p_file.length; i++) {
mAts.add(p_file[i]);
}
Note that I left off all optional arguments to Attachments.Add(). The method defaults to adding the attachments at the end, which is what you seem to want anyway.
Can you try this standalone snippet? If it works for you, please do a step-by-step reduction of your code towards this absolute minimum, and you will find what causes the error.
first do mItm.display()
then write mItm.GetInspector.WindowState = 2;
this will work