JavaScript...Cannot call method match of undefined - javascript

I'm getting this error: Uncaught TypeError: Cannot call method 'match' of undefined in my JavaScript. I'm trying to write this without jQuery since it'll be the only js on the site.
My code is supposed to add a class, "active", to the <a href="...> in the navigation that links to the current page.
I'm guessing it might be the contentLoaded function?....source
Here's my code...(error occurs on line 9)...fiddle
(function(window, document, undefined) { contentLoaded(window, function() {
var page = document.location.pathname.match(/[A-z]+$/)[0],
nav_anchors = document.getElementsByTagName('header')[0]
.getElementsByTagName('nav')[0]
.getElementsByTagName('a');
for(i in nav_anchors)
if(nav_anchors[i].href.match(/[A-z]+$/)[0] = page) //LINE 9 <-- Error
nav_anchors[i].classList.add('active');
})
})(this, this.document)
Thanks!

NodeLists have length, item and namedItem properties.
Use for (var i = 0; i < foo.length; i++) not for i in foo to iterate over them and only hit the nodes.

(function(window, document, undefined) { contentLoaded(window, function() {
var page = document.location.pathname.match(/[A-z]+$/)[0],
nav_anchors = document.getElementsByTagName('header')[0]
.getElementsByTagName('nav')[0]
.getElementsByTagName('a');
for(var i=0;i<nav_anchors.length;i++)
if(typeof nav_anchors[i].href != "undefined" && nav_anchors[i].href.match(/[A-z]+$/)[0] == page)
nav_anchors[i].classList.add('active');
})
})(this, this.document)
Added a check if the href of the anchor is set, in case you have page anchors without href attributes (Such as <a name="top"> called using #top). Added a second = in the IF for it to work as exepected. And corrected the for syntax.

if(nav_anchors[i].href.match(/[A-z]+$/)[0] = page) //LINE 9 <-- Error
In javaScript the equals sign = is an assignment operator. You probably mean double equals == where you can check values without type coercion (5 == "5") or triple equals === for strong typed checks (where 5 !== "5").

Sometimes document.location.pathname.match(/[A-z]+$/) can be null. If you try to use document.location.pathname.match(/[A-z]+$/)[0] you can not access the 0 Element of null.

Related

Slideshow stopped working console shows no related errors? But this one unrelated

Here is the error that shows "TypeError: undefined is not an object (evaluating 'tjq("#price-range").data('url-noprice').replace')"
That has nothing to do with the slideshow that I can think of? If you look at the page source you can see the images are there, but the photos tab at the top no longer expands and shows the slide images.
Example bag:
http://www.foreversummer.net/accommodation/villas-pappagallo-3/?adults=1&kids=0&rooms=1&date_from&date_to&child_ages%5B0%5D=0
Here is the part of the script that it is having an issue with.
if (tjq(".filters-container").length > 0) {
// price range
var price_slide_min_val = 0;
var price_slide_step = tjq("#price-range").data('slide-step');
var price_slide_last_val = tjq("#price-range").data('slide-last-val');
var price_slide_max_val = price_slide_last_val + price_slide_step;
var def_currency = tjq("#price-range").data('def-currency');
var min_price = tjq("#price-range").data('min-price');
var max_price = tjq("#price-range").data('max-price');
if (max_price == "no_max") { max_price = price_slide_max_val; }
var url_noprice = tjq("#price-range").data('url-noprice').replace(/&/g, '&');
if ((min_price != 0) || (max_price != price_slide_max_val)) {
tjq('#price-filter').collapse('show');
tjq('a[href="#price-filter"]').removeClass('collapsed');
}
Any help would be appreciated, if you spot something I have missed. This one has me stumped. Could this issue be causing the rest of the query to malfunction?
I've looked into the URL you added and saw the aforementioned js code.
It seems that you're looking for a dom element with the id "price-range", but it does not exist in your document dom. The element itself is missing.
The following line:
var url_noprice = tjq("#price-range").data('url-noprice').replace(/&/g, '&');
raises an error because the script is trying to use the method "replace" on
an undefined object. Step by step:
tjq("#price-range") → returns an empty array of objects
data('url-noprice') → is executed on each of the objects in the empty object array and returns 'undefined'
.replace(/&/g, '&') → is executed on 'undefined'

Strange results with javascript array.length function

I have piece of JavaScript code which cycles through form elements and builds an object.
I have a mixture of HTML input fields and ASP.NET input fields. ASP.NET changes the ID of the fields to the form xxxxx_yyyy_id, so I am attempting to use the split function to extract the original id.
// Iterate over all the text fields and build an object
$(':text').each(function () {
var tokens = this.id.split("_");
if (tokens.length = 3) {
// Assume this is a .net inputbox - extract the original id
inFormData[tokens[2]] = this.value;
} else {
inFormData[this.id] = this.value;
}
});
Stepping through the above code, the first id is ctl00_ContentPlaceHolderCol1_forenameField, so the tokens.length = 3 code is run.
On the second iteration, the id is forenameField2 so I would expect the tokens.length to be 1, but it is actually 3. The else statement is never run.
This could be something simple, but I cant work it out. If I inspect the tokens array it has only 1 element in on the second iteration. I have also tried setting the array.length to 0 after each iteration.
Any help appreciated.
Correct this:
== instead of =. === is more better
if (tokens.length == 3) {
// Assume this is a .net inputbox - extract the original id
inFormData[tokens[2]] = this.value;
} else {
inFormData[this.id] = this.value;
}
Change your = 3 to === 3
At the moment you're overwriting tokens.length every time.
NB: === is preferred to == because it's an exact equality check. The two-equals version will attempt to cast the two operands to the same type before comparison, which is 1. unnecessary, 2. inefficient, 3. sometimes error prone.
That is why you should always put the constant first when testing. If you forget a comparison sign it will throw an error:
if( 3 = tokens.length ) // throws an error
if( 3 == tokens.length ) // ok
if( 3 === tokens.length) // ok
from:
if (tokens.length = 3) {
to:
if (tokens.length == 3) {

javascript error in ie7

I am getting a javascript error on a page with this code.The error is "parentNode is null or not and object"
The error is in this line: theParent.parentNode.removeChild(theParent);
Is there some other code I can use to replace this or jquery that
will work instead?
var path = location.pathname;
if( path == "/SearchResults.asp"
|| path == "/ProductDetails.asp"
|| path.indexOf("-s/") != -1
|| path.indexOf("_s/") != -1
|| path.indexOf("_p/") != -1
|| path.indexOf("-p/") != -1 ) {
var links = document.getElementById("content_area")
.getElementsByTagName("a");
var homeLink;
for (var i = 0; i < links.length; i++) {
if (links[i].innerHTML.match("Home")) {
homeLink = links[i];
break;
}
}
var theParent = homeLink.parentNode;
theParent.parentNode.removeChild(theParent);
}
It seems strange that you'd get "parentNode is null or not and object" with:
var theParent = homeLink.parentNode;
If anything, it would simply set theParent to null and continue on. Or, homeLink would need to be the cause of the error, which is not what IE is complaining about.
However, the next line...
theParent.parentNode.removeChild(theParent);
...I could see throwing the error mentioned if parentNode was null, since null cannot have methods, such as removeChild.
You can try revising the line to something like the following to get an idea of success rate:
if (theParent.parentNode == null) // == for null or undefined by coercion
theParent.parentNode.removeChild(theParent);
else
throw new Error('Node could not be removed as parentNode is unknown.');
Or, leave out the else and throw to let it fail silently.
Try
if (theParent) { theParent.parentNode.removeChild(theParent); }
Since, it looks like you may not be finding the innerHTML, "Home" or not creating theParent for some other reason.
The HTML would help, just to make sure Home exists and that it has a grand parent.
It seems your loop may not be finding a link with the text Home. Have you tried checking if homeLink is null?
Looks like either homeLink is null or the parentNode is null. Can you run it in firefox + firebug and set breakpoints?

CSS - js rendering links useless

Ok, well, thanks to people here, I figured out the portion of my js code that's rendering my links useless is what's pasted below... Still trying to figure out why, but if someone has any insight, that'd be great...
function initJumpMenus() {
// Turns all <select> elements with the 'jumpmenu' class into jump menus
var selectElements = document.getElementsByTagName("select");
for( i = 0; i < selectElements.length; i++ ) {
// Check for the class and make sure the element has an ID
if( selectElements[i].className == "jumpmenu" &&
document.getElementById(selectElements[i].id) != ""
) {
jumpmenu = document.getElementById(selectElements[i].id);
jumpmenu.onchange = function() {
if( this.options[this.selectedIndex].value != '' ) {
// Redirect
location.href=this.options[this.selectedIndex].value;
}
}
}
}
}
window.onload = function() {
initJumpMenus();
}
This:
document.getElementById(selectElements[i].id) != ""
is wrong. You want to check if the element has an id, so simply do:
selectElements[i].id != ""
I'd like to point out that you can improve your code here and there:
1 Don't write for loops that get the length property for each iteration,
instead do:
for( i = 0, num = selectElements.length; i < num; i++ ) {
...
}
Only if you expect selectElements to grow or shrink it would make sense to requery the property value, but in that case, you probably should not write a for loop anyway.
2: Don't write nodelist[index]
For nodelists, such as returned by getElementsByTagName() you should not write nodelist[index] (even though most browser support that). The standard DOM method is item, so write nodelist.item(index) instead.
3 fetch items from the list only once
If you need an item from the list more than once, store it in a local variable. your loop would become:
for( i = 0, selectElement; i < selectElements.length; i++ ) {
selectElement = selectElements.item(i);
...more code using selectElement...
}
Note the declaration of the selectElement variable in the for loop. since you don't use it outside the loop, declaring it there avoids clutter and ensures that if you move the loop, you move the declaration.
4. cheapest comparisons first
You wrote:
selectElement.className == "jumpmenu" &&
selectElement.id != ""
this could be slightly improved if you reverse the legs:
selectElement.id != "" &&
selectElement.className == "jumpmenu"
This will be faster, since it is less work to check if a string is empty, and for those cases where the string is empty, we won't even check the className
5 Don't use document.getElementById() if you already have the element
Inside the loop you have this:
jumpmenu = document.getElementById(selectElements[i].id);
You are basically getting the id from the selectElement and use that to query the document to find ....the element having and id equal to that of the current selectElement. Becuase id's are unique within the document (or should be), you are basically writing a completely unecessary sentence. jumpmenu and selectElement refer to one and the same object.
6. onchange handler improvements
inside the loop you assign an onchange handler. you do so by creating a new function for each loop iteration. This is the handler code:
function() {
if( this.options[this.selectedIndex].value != '' ) {
// Redirect
location.href=this.options[this.selectedIndex].value;
}
}
Three things are of note here: First, the onchange handler code contains this location.href = ... that should probably be document.location.href = ....
Second, you refer twice to this.options[this.selectedIndex].value. Again, put this in a local variable.
Third, the this refers to the element that experienced the onchange event by the time this function is executing. Other than this and properties of this, there are no variables in this handler that originate from the loop or the outer initJumpMenus function. You should simply create it once, outside the loop, and assign it every iteration:
var onchange_handler = function() {
if( this.options[this.selectedIndex].value != "" ) {
// Redirect
location.href=this.options[this.selectedIndex].value;
}
}
for (...) {
if (...) {
selectElement.onchange = onchange_handler;
}
}
7 Summary
Putting it all toghether, this is how I would write it:
function initJumpMenus() {
var handler = function() {
var value = this.options.item(this.selectedIndex).value;
if( value != "" ) {
// Redirect
document.location.href = value;
}
}
var selectElements = document.getElementsByTagName("select");
for(var i = 0, num = selectElements.length, selectElement; i < num; i++ ) {
selectElement = selectElements.item(i);
// Check for the class and make sure the element has an ID
if( selectElement.id != "" &&
selectElement.className == "jumpmenu"
) {
selectElement.onchange = handler;
}
}
}
Check the error console; any exception in the JS will stop the links form reacting to a click.

Internet Explorer 7 - Javascript 'undefined' not testing

I'm having trouble with some JS in IE7. I'm testing to see if a certain object has a className (its possibly an HTMLElement object from the DOM) assigned.
Now, testing the page in Firefox tells me that Yes, the variable is undefined (all my tests below do the Alert().
In IE, none of the tests pass, the variable gets assigned on the last IF statement, and during the last Alert() IE chucks an "className is null or not an object" error, based on the fn_note.className statement.
Here's the code:
var fn_note;
var kids = area.childNodes;
for (var l = 0; l < kids.length; l++){
//DEBUG check if the found var exists
if (kids[l].className == null){
//then the className var doens't exist
alert ('the classsname for the following var is null: --'+kids[l]+'--');
}
if (kids[l].className == undefined){
//then the className var doens't exist
alert ('the classsname for the following var is undefined: --'+kids[l]+'--');
}
if (kids[l].className == ''){
//then the className var doens't exist
alert ('the classsname for the following var is an empty string: --'+kids[l]+'--');
}
if (typeof kids[l].className === 'undefined'){
//then the className var doens't exist
alert ('the classsname for the following var is NEW TYPEOF TEST: --'+kids[l]+'--');
}
if (kids[l].className == 'fn-note') { /* (/fn-note$/).test(kids[l].className) IE doesn't really like regex. por supuesto */
//we have found the div we want to hide
fn_note = kids[l];
}
}
alert('the clicked on className is '+area.className+'name of the found div is '+fn_note.className);
Please let me know what I am doing wrong. I know its probably something basic but I just can't see it ATM.
Thanks in advance.
I think that what you get from the property is not a string, but an object of the type 'undefined'. Try this:
if (typeof(kids[l].className) == 'undefined') {
As far as I can see the only thing you really want to know is if there's a childNode with className 'fn-note' in the childNodes collection. So do a somewhat more rigourous test:
for (var l = 0; l < kids.length; l++){
if (kids[l]
&& kids[l].className
&& kids[l].className.match(/fn\-note$/i)) {
fn_note = kids[l];
}
}
This should be sufficient (do mind escaping the dash in the regexp).

Categories