A short while back I asked a question here about how I could calculate when a heading was longer than one line within a given container, and subsequently wrap each of these lines in a <span>:
Use Javascript/jQuery to determine where a heading breaks to the next line?
I chose an answer which worked great for me, at least until I checked in IE7 and IE6, in which all the headings handled by this script rendered as
"undefinedundefinedundefinedundefinedundefinedundefined[...]"
on the page. As I'm not really a JavaScript person (that's why I asked such a question in the first place), it's really tough for me to figure out where the problem is. I assumed an undefined variable or something, but I just can't seem to grasp it.
Can anyone help?
I'll repeat the code here, but please refer to the link above for context:
$(function(){
$h = $('.fixed').find('h3');
$h.each(function(i,e){
var txt = $(e).text();
$th = $('<h3 />').prependTo($(e).parent());
var lh = $(e).text('X').height();
$(e).text('');
while (txt.length > 0) {
$th.text($th.text() + txt[0]);
txt = txt.slice(1);
if (($th.height() > lh) || (txt.length <= 0)) {
var shc = $th.text().split(' ');
var ph = shc.slice(0,-1).join(' ')+' ';
if (txt.length <= 0) { ph += shc.pop(); }
$('<span />').text(ph).appendTo($(e));
$th.text(shc.pop());
}
}
$th.remove();
})
});
You need to change
$th.text($th.text() + txt[0]);
to be
$th.text($th.text() + txt.charAt(0));
IE<8 doesn't accept string positions through array indexes ;)
The styling doesn't work, but that'll be a CSS issue which I couldn't fix before leaving. But everything is wrapped in spans :)
Nothing jumps out at me. But, since you mentioned in your comment to your question that you see "undefined" in Firebug, I would start there. Even though those browsers are failing gracefully, the fact that you see undefined there is your first hint to finding the problem for the harder-to-diagnose IE6/7. I would use Firebug and either breakpoint in the function, or use some console.log() calls to document what the values that you are working with are each step of the way. Once you start seeing undefined... you have likely found your problem.
Related
I've just been trying to make some code to test out tampermonkey stuff on simple maths questions when I came across this error. it would work for the first question, get the question, solve it, enter the answer. The element then changes to a new question however when I use .innerHTML or .textContent it always gives the original question.
Here is my code which shows this:
console.log(document.getElementById('currgamename'))
console.log(document.getElementById('currgamename').textContent)
I get this output:
<span id="currgamename">12-7</span>
6-3 //The first question that appears
Full code:
var delayInMilliseconds = 1000; //1 second
var x = 0
setTimeout(function() {
var handler = setInterval(function() {
document.getElementById('playPadding').childNodes[1].click()
var equation = document.getElementById('currgamename').textContent
var actual = equation.split('-')
var answer = (parseInt(actual[0]) - parseInt(actual[1])).toString()
document.getElementById('currgamename').innerHTML = 'hello'
console.log(document.getElementById('currgamename'))
console.log(document.getElementById('currgamename').textContent)
document.getElementById('gameinput').value = answer
document.getElementById('nextButton').click()
x++;
if (x >= 5) {
clearInterval(handler);
}
}, 1000);
}, delayInMilliseconds);
I have absolutely no clue why it gives the updated element but not the updated text so I could really use some clarification here thanks!
In the console:
>document.querySelector("#currgamename")
<-<span id="currgamename">12-7</span>
>document.querySelector("#currgamename").textContent = "hello"
<-"hello"
------And the HTML on the screen changed to show the "hello" instead of "12-7"------
>document.querySelector("#currgamename").innerHTML = "bye"
<-"bye"
>document.querySelector("#currgamename").innerText
<"bye"
So it works as long as your querySelector is aimed at the correct element it should work
I genuinely cannot believe my stupidity, I've been at this for 4 hours now and the error was that I had document.getElementById('playPadding').childNodes[1].click() inside the setinterval. It was pressing the start button everytime i wanted to answer a new question so it was just replacing it with the old one FML.
Well, there was me thinking my JS wordgame was functioning beautifully ( with a little help from Ryan J - thanks!). I was about to begin adding styling when I realised that I hadn't tested in Firefox at all - my bad, I got the dreaded script timeout error. So, after hours of testing and playing around I still can't understand what's wrong. I'm being told by the error that it's the following function that's causing the problem:
function guessLetter( letter, shown, answer ) {
var checkIndex = 0;
checkIndex = answer.indexOf(letter);
while (checkIndex >= 0) {
shown = alterAt(checkIndex, letter, shown);
checkIndex = answer.indexOf(letter, checkIndex + 1);
}
return shown;
}
alterAt is previously defined, totally puzzled - any tips most welcomed.
Thanks
Terry
EDT: Oops! Here's a link - completely unstyled but you get the idea.
http://theelectricunderground.net/eltel/currentaffairs/wordpress/?p=449
I have confirmed it... this is because letter is an empty string. You should add something like this to your code (in the keypress event):
if (tempChar === "") return;
before the line
tempString = guessLetter(tempChar, gameShownAnswer, gameAnswer );
This is because sometimes the keyup event occurs but there is nothing in the input box.
For example, what happens when you press the control key?
The index of an empty string never be -1, so the loop will never break.
For example, "petrol".indexOf("", 100) returns 6.
I've got the following JavaScript statement, that executes on Page Load:
The variable u1 is populated with one of the following values:
BBSLoan|Accept|PPI+No|60Months
BBSLoan|Refer|PPI+No|60Months
HSBSLoan|Accept|PPI+No|48Months
HSBSLoan|Refer|PPI+No|48Months
I have been informed that the conditions in the conditional statements will never be met - is this true? From what I can see, going on each of the variables, the index that will be returned by indexOf is 0? Unless I am mistaken?
EDIT: Just to clarify, the variable 'u1' will be populated dynamically with any of the 4 strings listed above. The %pu1=!; is actually a macro that will populate this value.
<script language="JavaScript" type="text/javascript">
var u1 = '%pu1=!;';
if (u1.indexOf('BBSLoan|Accept') > -1) {
var pvnPixel = '<img src="http://www.url1.com"/>';
document.writeln(pvnPixel);
}
if (u1.indexOf('BBSLoan|Refer') > -1) {
var pvnPixel2 = '<img src="https://www.url2.com;"/>';
document.writeln(pvnPixel2);
}
if (u1.indexOf('HSBSLoan|Accept') > -1) {
var pvnPixel3 = '<img src="https://www.url3.com;"/>';
document.writeln(pvnPixel3);
}
</script>
Thanks in advance!
EDIT: Just to clarify, the variable 'u1' will be populated dynamically with any of the 4 strings listed above. The %pu1=!; is actually a macro that will populate this value.
This answer is not correct. It will be deleted later, but is being left to prevent this answer from popping up again.
var u1 = '%pu1=!;';
The value of u1 is always '%pu1=!;', since you declare it as that.
Ok I finally got this to work using search instead of indexOf!
Would it make more sense to use a switch statement with a default case, or at a minimum provide an "else" with a default?
Have you tried to put a debugger statement in after var u1 is set, and step through using the client (firefox, chrome, IE, safari all have built in "developer tools" with the ability to step through js code) debugger to see what the value of u1 is?
Ok guys/girls.
Below is some jQuery that runs in Firefox but no IE. I have no idea why it craps out in one and not the other.
Anyone??
function SwapTextAssetforPOS() {
$("*").each(function () {
if ($(this).children().length == 0) {
$(this).text($(this).text().replace('Assets', 'POS'));
$(this).text($(this).text().replace('Asset', 'POS'));
$(this).text($(this).text().replace('assets', 'POS'));
$(this).text($(this).text().replace('asset', 'POS'));
}
});
}
Sorry folks - the error that I get is:-
SCRIPT65535: Unexpected call to method or property access.
jquery-1.6.min.js, line 16 character 60352
EDIT:------------------------------------------------------------------------------------
Ok so an update - I removed the * selector and IE no longer blows up, my issue now is that I cant figure how to get it to do the replace on the element. I have the following code to ping up all the text elements in the object:
function SwapTextAssetforPOS() {
var containerElementByID = $("#assetDetailContents");
containerElementByID.children().children().each(function () {
var $this = $(this);
alert($this.text());
});
This chucks me up an alert for every bit of text, however some is contained within a table, some is within a span, and some is just there. I have no control over a majority of this stuff so my new question is how do I get the previous replace to work using this type of selector. -- I can believe how painful this is..
Cheers again
I see the problem in my IE browser. When you do the $("*").each... it takes every single element in the page (including title, script, etc). When you do .text(), looks like it fails for some elements in IE for which .text() doesn't make sense. Replace "*" for "div" and it should work for the divs for example.Maybe you could do something like if ($(this).text()) {$(this).text($(this).text().replace('Assets', 'POS'));} to make sure the text() is defined for that element.
Still, going through the whole DOM is overkill. Can you add a class to the elements that can have the text?, like class="replaceable" so you could just do a $(".replaceable").text(...
Ok folks - so firstly thanks for the help.
I have resolved the issue by cobbling a number of suggestions together and by doing a little bit of investigative work.
In a nutshell IE was crapping out when it ran up against an tag. I no not why but this is where it fell over every time.
function SwapTextAssetforPOS() {
var overlaycon = $("#jq-selectionHelper").find("*:not(img)"); //This line simply looks at the div surrounding the template and returns (to an array I believe) every element therein except for img tag
//as this breaks in IE when tying to do the replace text stuff below.
overlaycon.each(function () {
var $this = $(this);
if ($this.children().length == 0) {
$this.text($(this).text().replace('Assets', 'POS'));
$this.text($(this).text().replace('Asset', 'POS'));
$this.text($(this).text().replace('assets', 'POS'));
$this.text($(this).text().replace('asset', 'POS'));
}
});
}
This code runs and I believe is a lot more efficient than my original offering. Any further suggestions for performance re-factoring are welcome but thank the lord this is now working.
Thanks again for all the help.
Regards
This code has no problem as seen here . I tested in IE and FF both works fine
http://jsfiddle.net/wKWRC/
You should use F12 developer tool for IE and see what error you are getting that way others can know what exact problem is . You can debug script and see where you are getting error . IE is sensitive to javascript errors and its possible there is some error before you are calling this function .
http://msdn.microsoft.com/en-us/library/gg699336%28v=vs.85%29.aspx
Just a hunch but you might be running out of memory in IE.
First, using $('*') is never advisable, its better that you narrow it down with a selector like $('p').
Also, every time you call $(this) you create a new jQuery object, so if there are a lot of elements on your page you're making 9 objects every time.
The convention is to set $this = $(this) at the begining of the function so you only use one object.
function SwapTextAssetforPOS() {
$("*").each(function () {
var $this = $(this);
if ($this.children().length == 0) {
$this.text($this.text().replace('Assets', 'POS'));
$this.text($this.text().replace('Asset', 'POS'));
$this.text($this.text().replace('assets', 'POS'));
$this.text($this.text().replace('asset', 'POS'));
}
});
}
try it like this
for (var i = 0, replacements = ['Assets','assets','asset','Asset']; i < 4; i++)
$("*:contains('" + replacements[i] +"')").map(function() { this.innerHTML = this.innerHTML.replace(/asset(s){0,1}/igm, 'POS'); })
r = r.replace(/<TR><TD><\/TD><\/TR>/gi, rider_html);
...does not work in IE but works in all other browsers.
Any ideas or alternatives?
I've come to the conclusion that the variable r must not have the value in it you expect because the regex replacement should work fine if there is actually a match. You can see in this jsFiddle that the replace works fine if "r" actually has a match in it.
This is the code from fiddle and it shows the proper replacement in IE.
var r = "aa<TR><TD></TD></TR>bb";
var rider_html = " foo ";
r = r.replace(/<TR><TD><\/TD><\/TR>/gi, rider_html);
alert(r);
So, we can't really go further to diagnose without knowing what the value of "r" is and where it came from or knowing something more specific about the version of IE that you're running in (in which case you can just try the fiddle in that version yourself).
If r came from the HTML of the document, then string matching on it is a bad thing because IE does not keep the original HTML around. Instead it reconstitutes it when needed from the parsed page and it puts some things in different order (like attributes), different or no quotes around attributes, different capitalization, different spacing, etc...
You could do something like this:
var rows = document.getElementsByTagName('tr');
for (var i = 0; i < rows.length; i++) {
var children = rows[i].children;
if (children.length === 1 && children[0].nodeName.toLowerCase() === 'td') {
children[0].innerHTML = someHTMLdata
}
}
Note that this sets the value of the table cell, rather than replacing the whole row. If you want to do something other than this, you'll have to use DOM methods rather than innerHTML and specify exactly what you actually want.