cannot get string length in javascript - javascript

Over 1 hour on this. This is javascript code inside my index.php file.
function dostuff()
{
var thepath = document.location.search.substring(1);
alert('the path is ' + thepath + " (that's the full path)");
alert(thepath);
// TRIED THESE ALL -- NONE OF THEM WORK.
//var pathLen = String.length("thepath");
//var pathLen = String.length(thepath);
//var pathLen = thepath.length();
var pathLen = String.length(document.location.search.substring(1));
alert('pathLen is ' + pathLen);
}
The symptom: the first 2 alert boxes appear no problem and both show 'thepath' has a valid pathname in it, and it is the correct, expected path too.
But no matter what I try -- see the 4 different attempts, tried one at a time -- the final alert() box NEVER shows up.
Why is alert('pathLen is ' + pathLen) not showing up?
(The other thing is -- I'm using XDEBUG and xampp and Netbeans and the debugger will not let me put a breakpoint in this javascript code, so I can't even step into it to see what's happening, hence the use of the alert()'s in the code. I know the XDEBUG debugger I'm using in Netbeans works -- I've been using it all night to debug PHP code in a different.PHP file. When I set a breakpoint though in any Javascript code, a 'broken breakpoint' icon appears and I cannot find what that means in Netbeans documentation.)

I've never seen that syntax before. You might want to try:
var pathLen = thepath.length;
(You'd be best off debugging with Firebug)

var pathLen = thepath.length;
Length is a property of the string, not a function, so no need for the ().

The length is a property of your string rather than a method.
You should be able to access it via the following:
var pathLen = thepath.length;
When you say the alert box never shows up do you mean it never appears at all? If you're using FF you can open the error console from the Tools menu and clear it then refresh your page. It should highlight any JS errors you have in your code. That's the only reason I know of that the alert wouldn't show at all. (I don't think there is a class method for String.length() which is probably where the error is coming from.)
As for XDebug, as far as I know it's a PHP debugger only I don't think it can debug JS.

pathLen.length
No (). length is a property; if you add the (), it tries to use the value of the property as a function to call, resulting in an exception.

Related

Chrome Address Bar Javascript produces different effect than Console

Trying something new, I was attempting to highlight text on this wikia page using javascript within the address bar (i.e. using "javascript:[code]").
When running the following code sample through Chrome's console, it produces the desired effect. When running it from the address bar, it results in only the affected text -- the rest of the page body is removed.
javascript:txt = document.getElementById("Ballas.27_Rebellion_and_Allying_With_Hunhow").parentElement.nextElementSibling;index = txt.innerHTML.indexOf(", but")+2;txt.innerHTML = txt.innerHTML.substring(0,index)+"<span style='background-color:yellow;'>"+txt.innerHTML.substring(index,index+40)+"</span>"+txt.innerHTML.substring(index+40);
Note: if you want to try this you will have to manually type javascript: into the address bar before pasting the code, as Chrome automatically removes it.
I'm curious as to why this would be, and also if there is a way to stop the address bar from removing the rest of the page body. Can anyone offer insight?
Thanks.
The quick solution to the problem you're experiencing is to add false; to the end of your query. This will prevent Chrome from removing the text from your page and should give you the result you expect.
Here's the fixed code:
javascript:txt = document.getElementById("Ballas.27_Rebellion_and_Allying_With_Hunhow").parentElement.nextElementSibling;index = txt.innerHTML.indexOf(", but")+2;txt.innerHTML = txt.innerHTML.substring(0,index)+"<span style='background-color:yellow;'>"+txt.innerHTML.substring(index,index+40)+"</span>"+txt.innerHTML.substring(index+40);false;
To fully answer the question, let me quickly explain what is happening. I'll start by splitting up your JS a bit to make it easier to read.
txt = document.getElementById("Ballas.27_Rebellion_and_Allying_With_Hunhow").parentElement.nextElementSibling;
index = txt.innerHTML.indexOf(", but")+2;
txt.innerHTML = txt.innerHTML.substring(0,index) +
"<span style='background-color:yellow;'>" +
txt.innerHTML.substring(index,index+40) +
"</span>"+txt.innerHTML.substring(index+40);
What you'll note is that the final statement is an assignment operation. In JavaScript the result of an assignment operation is the value of the assignment. In other words, if we say return x = 1 we will both set the value of x to 1 and return the value 1.
This brings us to the reason why Chrome is replacing your page content. The JavaScript you're providing is returning the content of the txt element (the paragraph you're deciding to highlight) and this is then being treated as the content of your new page, the same way that visiting data:text/plain,hello world or javascript:"hello world" in your browser will show the text "hello world"even though you haven't explicitly visited a website.
To fix this, you can return a falsey value in JavaScript - this means any one of the following:
0
false
[]
null
undefined
Hence, adding false; at the end of your JavaScript will have Chrome run the code but not show the resulting text and will prevent it from changing the page content on you unexpectedly.

Eval String of Javascript with Line and Column Offset?

Does anyone know of a way to eval a string so that if it (or a function it defines) generates an error, the line and column numbers shown in the stack trace will be offset by an amount specified in advance?
Alternatively, suppose I want to break up a long source string into chunks and evaluate them separately, but still get stack traces that look as though the entire string was evaluated in one go. Is there any way to achieve this effect, except for using empty lines and columns? (I need a browser-based solution, preferably cross-browser, but I can settle for something that works on at least one of the major browsers.)
I don't think is it possible because the underlying mechanism that is assumed working is actually deprecated. For security reasons browsers don't pass the error object to Javascript anymore.
However, since you are working with a custom programming language that gets compiled into Javascript, you know what the structure of the resulting script will be. You could also introduce statement counters in the resulting Javascript, so you can always know what the last thing executed was. Something like:
function(1); function(2);
function(3);
could be translated as:
var __column=0;
var __line=0;
function(1); __column+=12;
function(2); /*__column+=12;*/ __line++; __column=0;
function(3); /*__column+=12;*/ __line++; __column=0;
Where 12 is "function(n);".length.Of course, the resulting code is ugly, but you could enable this behaviour with a debug flag or something.
The best solution I've found so far is to prepend a sourceURL directive to each string before it's eval'ed, giving it a marker in the form of a unique file name in the stack trace. Stack traces are then parsed (using the parser component stacktracejs) and corrected by looking up the line offsets associated with the markers.
var evalCounter = 0;
var lineCounter = 0;
var lineOffsetTable = {};
function myEval(code) {
lineOffsetTable[evalCounter] = lineCounter;
lineCounter += countLines(code);
return eval("//# sourceURL=" + (evalCounter++) + "\n" + code);
}
window.onerror = function(errorMsg, url, lineNumber, column, e) {
var stackFrames = ErrorStackParser.parse(e);
logStackTrace(stackFrames.map(function(f) {
if(f.fileName in lineOffsetTable)
f.lineNumber += lineOffsetTable[f.fileName];
return f;
}));
};
Unfortunately, this only works in Firefox at the moment. Chrome refuses to pass the error object to the onerror callback (a problem which only happens with eval'ed code, strangely enough) and IE ignores the sourceURL directive.

JavaScript error for eval parent.location

I am working in Classic ASP. The code I'm working with (not my code) was written a very long time ago, perhaps even long before Firefox and Chrome existed.
Anyways, there is the following JavaScript function:
function MM_jumpMenu(targ, selObj, restore) {
eval(targ + ".location ='" + selObj.options[selObj.selectedIndex].getAttribute('value') + "'");
if (restore)
{
selObj.selectedIndex=0;
}
}
That code has all of a sudden stopped working, and I'm trying to figure out why. In Chrome it is giving me the error:
SyntaxError: Unexpected identifier
When I try and run the code, the parameters passed in are as follows:
targ = "parent"
value on selected index of selObj = "edit_details.asp?make=ML&n=&r=DA61CHH&c=Hope Ready Mixed Concrete Ltd - CHY LCV's&cus=HOPEAG02&type=&inc=&id=&fw=&cusid=HOPE03"
restore = 0
Assume code was written solely for IE 6/7 and we're trying to standardise and make it work for all browsers.
eval is evil!! Don't use it!
window[targ].location = selObj.options[selObj.selectedIndex].getAttribute('value');
You have an unescaped single quote in your url.
CHY LCV's&
Espace this:
CHY LCV\'s&
But really, this code is horrible, you should rewrite it if you can.
"value on selected index of selObj " : it has an apostrophe. You'll need to escape that.

Parsing a string returned from ckeditor using javascript string methods

I am trying to get a certain area of data out from ckeditor. In order to do that I use the following code
function get_body_html(){
var email = CKEDITOR.instances['message'].getData();
var before_body = header_to + to + to_subject + subject + subject_body;
var s_index = email.indexOf(before_body)+before_body.length;
var e_index = email.indexOf(body_footer);
return email.substring(s_index,e_index);
}
For some reason that works when I do this on page load
CKEDITOR.instances.message.setData(header_to + to + to_subject+
subject + subject_body + body_text + body_footer);
get_body_html();
it works correctly and gives me the same string that is contained in body_text.
But when I do this
body_text = get_body_html();
CKEDITOR.instances.message.setData(header_to + to + to_subject + subject +
subject_body + body_text + body_footer);
in an onclick function it gets the wrong indexs somehow. Sometimes it can't find the string and returns -1 other times it just gets a weird index that doesn't make sense. These index variations only happen when my code is changed to tackle the problem a different way. So if it is the wrong indices like -5 and 2 then those would continue to be the wrong indices until I made a code change.
There are two facts that you should know about editor.setData.
In some cases it is asynchronous (it depends on the type of editor). That's why it also accepts a callback. Therefore any code that is meant to be executed after setData() should be executed in that callback.
It never is asynchronous before editor is ready. In this period (between editor initialization and instanceReady event) it works in a different mode - it just caches the set value and on getData() it returns exactly that value.
So, as I see on page load you call synchronously setData() and getData() - your function works because you get the value you're expecting to get.
But then, when you try to getData() when editor is already ready you get the HTML parsed, fixed, processed and perhaps differently formatted by CKEditor. I guess that your indexOf() checks are not enough to handle this. You have to rethink your function - e.g. regexp can help.
What also can help is removing htmlwriter plugin, which formats HTML in a way which may make it harder for you to work with it. E.g.:
config.removePlugins = 'htmlwriter';
I was able to get it to work. So the htmlwriter was one of the problems because it must add spaces in between by HTML tags. The other issue I found is that it strips some of the semicolons out in some of the style attributes. Overall CKEditor does a lot of formatting of the source which makes it very hard to index correctly but it's pretty much a trial and error thing. I ended up using the search JavaScript method for strings which can take a regular expression but I used it the same way indexOf would be used so I don't really know if that made a difference or not.

Javascript Bookmarklet Unresponsive

Javascript newb here. Creating a bookmarklet to automate a simple task at work. Mostly a learning exercise. It will scan a transcript on CNN.com, for instance: (http://transcripts.cnn.com/TRANSCRIPTS/1302/28/acd.01.html). It will grab the lead stories at the top of the page, the name and title of the guests on the show, and format them so that they can be copy pasted into another document.
I've come up with a simple version that includes some jQuery that grabs the subheading and then uses a regular expression to find the names of the guests (it will also exclude everything between (begin videoclip) and (end videoclip), but I haven't gotten that far yet. It then alerts them (will eventually print them in a pop-up window, alert is just for troubleshooting purposes).
I'm using http://benalman.com/code/test/jquery-run-code-bookmarklet/ to create the bookmarklet. My problem is that once the bookmarklet is created it is completely unresponsive. Click on it and nothing happens. I've tried minimizing the code first with no result. My guess is that cnn.com's javascript is conflicting with mine but I'm not sure how to get around that. Or do I need to include some code to load and store the text on the current page? Here's the code (I've included comments, but I took these out when I used the bookmarklet generator.) Thanks for any help!
//Grabs the subheading
var leadStories=$(".cnnTransSubHead").text();
//Scans the webpage for guest name and title. Includes a regular expression to find any
//string that starts with a capital letter, includes a comma, and ends in a colon.
var scanForGuests=/[A-Z ].+,[A-Z0-9 ].+:/g;
//Joins the array created by scanForGuests with a semicolon instead of a comma
var guests=scanForGuests.join(‘; ‘);
//Creates an alert in the proper format including stories and guests.
alert(“Lead Stories: “ + leadStories + “. ” + guests + “. SEE TRANSCRIPT FIELD FOR FULL TRANSCRIPT.“)
Go to the page. Open up developer tools (ctrl+shift+j in chrome) and paste your code in the console to see what's wrong.
The $ in var leadStories = $(".cnnTransSubHead").text(); is from jQuery and the link provided does not have jQuery loaded into the page.
On any modern browser you should be able to achieve the same results without jQuery:
var leadStories = document.getElementsByClassName('cnnTransSubHead')
.map(function(el) { return el.innerText } );
next we have:
var scanForGuests=/[A-Z ].+,[A-Z0-9 ].+:/g;
var guests=scanForGuests.join('; ');
scanForGuests IS a regular expression, you never actually matched it to anything - so .join() is going to throw an error. I'm not exactly sure what you're trying to do. Are you trying to scan the full text of the page for that regex? In that case something like this would be your best bet
document.body.innerText.match(scanForGuests);
keep in mind that while innerText removes html markup, it's far from perfect and what pops up in it is very much at the mercy of how the page's html is structured. That said, on my quick test it seems to work.
Finally, for something like this you should use an immediately invoked function or you're sticking all your variables into the global context.
So putting it all together you get something like this:
(function() {
var leadStories = document.getElementsByClassName('cnnTransSubHead')
.map(function(el) { return el.innerText } );
var scanForGuests=/[A-Z ].+,[A-Z0-9 ].+:/g;
var guests = document.body.innerText.match(scanForGuests).join("; ");
alert("Leads: " + leadStories + " Guests: " + guests);
})();

Categories