javascript looping problem - javascript

<script type="text/javascript">
function addbutton() {
var o = document.getElementsByTagName('li');
for(var i=0;i<o.length;i++)
{
var keyword= o[i].innerHTML;
var regobj = /<a (.*)>(.*)<(.)a>/g;
keyword = keyword.replace(new RegExp("<br>", "g")," ");
keyword = keyword.replace(regobj,"$2");
keyword = keyword.substring(0,100);
var str = "<br>"+ "<a class='but' target='blank' ";
str += "href=\"http://www.google.com.tr/search?q=";
str += decodeURIComponent(keyword);
str += "\">ara</a>";
o[i].innerHTML = o[i].innerHTML + str;
}
}
</script>
addbutton() adds a search button to end of the li tags, but when i run, it's looping for only 43 times. so it's adding the search button for the first 43 li tags. what is your thoughts, why is looping broken?
edit:
more information,
-i tried function on a page that contains 131 li tags. and function is working for the first 43 li tag,
-i tried for both of google chrome and firefox, results are same.
i tried to alert(o.length). there is no problem, it return true number, "131".

Well, there's certainly a bug on this line:
str += decodeURIComponent(keyword);
That should be
str += encodeURIComponent(keyword);
That may be the problem, decodeURIComponent may be blowing up on some input text because you're using it on strings that aren't URL-encoded.
Barring that:
You'll need to look at the actual text in the li elements as they're being processed. It's clearly not just a numbers thing, the code works just fine in Chrome.
I recommend using Chrome's Dev tools (Shift+Ctrl+I) to set a breakpoint in the function and walk through it with your actual test data. Or use the Firebug add-on for Firefox to do the same.

Related

JQuery get 'id' attribute

So I have the following code that generates a table and applies a click function to each td within the table. It also applies an incremental id starting with 1. When the user clicks on a td element I'm trying to retrieve the id of the <td> they clicked on. However the value of selector is [object Window]. I'm sure it is something simple but I none of the similar questions on here have helped, and I'm not seeing it.
$("#CMGame").click(function() {
$("#TTTContent").hide();
$("#CMContent").show();
var board = $("#CMBoard");
var htmlString = "";
var count = 0;
for (var i = 0; i < 20; i++) {
htmlString += "<tr>";
for (var i2 = 0; i2 < 20; i2++) {
count++;
htmlString += "<td id='" + toString(count) + "'></td>";
}
htmlString += "</tr>";
}
board.html(htmlString);
$("#CMBoard td").click(function() {
var piece = $(this);
var selector = piece.attr('id');
alert(selector);
/*
if (CMBArray[selector] != 1 OR CMBArray[selector] != 2) {
CMBArray[selector] = 1;
piece.addClass('selected');
}
*/
});
});
There are 2 errors in your code, the td id you create can't be just a number, it has to start with a letter and then you can either remove toString(count) and use only count or change it to count.toString(), which is the correct way.
Here is the specs. for a DOM id:
https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id
And here for toString():
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString
The toString is wrong in the code. Change
toString(count)
to
count.toLocaleString()
toString(count) is effectively like saying this.toString() which, in your case basically means window.toString(), which results in [object Window].
Instead, use count.toString().
Here's a quick test:
var count = 0;
console.log('second toString: ' + toString(count) );
console.log('second toString: ' + count.toString );
Bear in mind that, whenever you concatonate strings in Javascript, the toString method is called on all objects by default. For example, these two expressions yield the same output:
var number = 5;
console.log( 'The number is ' + number.toString() );
console.log( 'The number is ' + number );
The toString method you are calling is actually window.toString.
By not specifying a parent object for toString, you are invoking the method on the global window object. That is why you see "[object Window]", it is returning a string representation of the invoking object.
You don't need the toString at all. Javascript cast numberics to a string when you add it to a string.
this.id will return the id of the a jQuery element. E.g.:
$("td").click(function(){
alert(this.id);
});
Your problem is in the event $("#CMGame").click(function()
when try to convert to string with toString(count) javascript and jquery don't understand that they do understand count.toString() here is the source javaScript toString function.
Suggestion about some code you have:
first this one var board = $("#CMBoard"); you pass the html element to a javascript variable for you can do this board.html(htmlString); i think you do that so your function can be more faster than using other method to manipulate the DOM but in this case it look that we are not looking for best performances so other option is keep it simple with this $("#CMBoard").append(htmlString)
The id you set to each element is a number that is not a good practice at all and also there is a suggestion for compatibility for HTML5 to HTML4 look;
Note: Using characters except ASCII letters and digits, '_', '-' and '.' may cause compatibility problems, as they weren't allowed in HTML 4. Though this restriction has been lifted in HTML 5, an ID should start with a letter for compatibility. you can find this in global attribute id so is better to set a real id name you can do something like this in your code htmlString += "<td id='item_" + count.toString() + "'></td>";
so the id will come out like id="item_1"

String concat, test, add extra code or add anyway and remove at the end?

Sorry for the odd title, I'm sure someone has asked something similar before. My question is, I'm building a string with html tags enclosed, my question is is it better to test and add extra tags, in this case a <br />, or to add the tag anyway and have a 'remove' line at the end, which is faster?:
So at the moment we have
bFirst = true;
label = '';
if(...)
{
if (!bFirst)
label += '<br/>';
label+= 'some more text'
}
if(...)
{
if (!bFirst)
label += '<br/>';
label+= 'some more text'
}
and so on...
or
if()
{
label+= 'some more text <br />'
}
and then just remove the last <br /> using the string.substring() method.
Which is faster, better, more correct? I don't need code it is really a performance question, I could test it but I'm sure someone has done this before.
Thanks.
You can define which way is the fastest with this procedure :
Requirements :
You will need an addon like firebug or pagespeed
You'll have to execute those two pages :
Add all extra text and then trim some :
<div id ="concat"></div>
<script type="text/javascript">
var someText = ""
// adds "foo" 10k times
for (i = 0; i < 10000; i++) {
someText += "foo"
}
// crops the 3 last characters off the string 5k times
for (i = 0; i < 5000; i++) {
someText.substr(someText.length - 3, someText.length);
}
// append the final string
$('#concat').append(someText);
</script>
On my browser, it takes between 0.19 sec and 0.30 sec.
Add extra text when it is needed
<div id ="if"></div>
<script type="text/javascript">
var someText = ""
var append = true;
for (i = 0; i < 15000; i++) {
//adds "foo" the first 10k times
if(append == true){
someText += "foo";
}
if(i == 10000){
append = false;
}
}
$('#if').append(someText);
</script>
This code iterates 15k times and only adds "foo" the first 10k times.
The execution of such code can take between 0.10 and 0.12 sec
Conclusion
Adding content to your string only when it is needed seems a better option in terms of performance.
Also, in terms of code readabilty, the second option should be used.
Quick and simple analysis:
First option makes a comparison and a memory reallocation.
Second option (supposing you'd be doing label = label.substring(...)) counts characters, if you want the first N characters, String.prototype.substring() will probably count N times while reading N bytes of characters. Finally, you allocate/reallocate memory.
Now which strategy appears more efficient?
If you're still in doubt try both methods under a timer.

Carriage Returns replacement in IE9

I'm trying to display some data in a <div> and IE9 is not keeping more than one carriage return. This works fine in Chrome, but not IE9 (it only adds the <br/>) Here's the code:
$.get(url,function(xml){
$("record",xml).each(function(){
var profile= $("profile",this).text().replace(/\r\n|\r|\n/g,'~').replace(/~~/g,'<\/p> <p>').replace(/~/g,'<br/>');
profileRpt += profile
});
});
Thought process on this was to normalize, then add <p> for double carriage returns and <br> for the single returns.
I've also tried the simple replacement,
var points= $("points",this).text().replace(/\n\r?/g, '<br />');
and again this worked fine in Chrome, but not in IE9.
Does anyone know of a way I can get this to work in IE9? Thanks!!
UPDATE
So it seems that jQuery is the culprit when used in IE, as it collapses the line breaks prior to any replace function.
Can anyone help with using an alternate (non-jQuery) method of retrieving the data from the xml response as I've done above? One that would preserve the line breaks?
Thanks for your help!
Try this:
function unifyLineFeeds = function(str) {
return str.replace("\r\n", "\n").replace("\r", "\n");
}
You can then use this function to output text as HTML following way:
// `text` var contains text with line ununified line feed characters.
text = unifyLineFeeds(text);
var lines = text.split("\n"),
count = lines.length,
lastIndex = count - 1;
var container = document.getElementById('someContainerToShowFormattedText');
for (var i = 0; i < count; i++) {
container.appendChild(document.createTextNode(lines[i]));
if (i < lastIndex) {
container.appendChild(document.createElement('br'));
}
}
var points = $("points", this).text().replace(/\r+/g, '').replace(/\n/g, '<br>');

jQuery: Getting syntax error after split() or text()?

What I need to do is grab the first <p> tag within an element, loop through all of the words, and wrap them in <span> tags. I wrote a script for this, which I thought worked, but it appears to break when some characters are in the <p> tag. I don't know which character(s) that causes it to break though.
Here is my current code:
$(document).ready(function(){
// Transform is set on html tag by modernizr
// Apply this on all .quote boxes, even if there are multiple (most likely aren't)
$('.csstransforms .quote').each(function() {
// Get data
var elem = $(this).find('p:first'),
html = elem.text(),
words = html.split(" "),
charCount = html.length
$(this).append('<p class="fixed"></p>');
// Add new words
var tmpWord = '';
for(i=0; i< words.length ; i++) {
tmpWord = $.trim(words[i]);
if(tmpWord && tmpWord != "") {
// Maybe replace with $(elem).next('.fixed') or something?
$('.csstransforms .quote .fixed').append('<span>'+ tmpWord +' </span>');
}
}
// Check word count, make size smaller if needed
if(charCount > 150) {
// Add class to .quote box
$(this).addClass('smaller');
}
// Hide original <p>
$(elem).hide();
});
});
The error i'm getting is as follows, and what you see in the text is the actual quote:
Uncaught Error: Syntax error, unrecognized expression: "In the decade or so, science has discovered a tremendous amount about the role emotions play in our lives. Researchers have found that even more than IQ, your emotional awareness and abilities to handle feelings, will determine your success and happiness in all walks of life, including family relationships". – John Gottman, Ph. D.
Any ideas as to what is causing this, and how to fix it? Been chewing on it on a while without success.
Update: Jsfiddle showing same error: http://jsfiddle.net/Uugbc/
Just for clarification. Your fiddle has
charCount = $(html).text().length;
but your variable html is not a jQuery object.
This will work better
var elem = $(this).find('p:first'),
html = elem.text(),
words = html.split(" "),
charCount = html.length; // here you had $(html).text().length;

How can I get IE to recognize NBSP as NBSP instead of a space?

For the following JavaScript:
function EscapedString(str) {
var obj = document.createElement("span");
obj.innerHTML = str;
return "&#" + (obj.textContent || obj.innerText).charCodeAt(0) + ";";
}
alert(EscapedString(" "));
alert(EscapedString(" "));
alert(EscapedString("\xA0"));
IE returns for each value instead of   like every other browser correctly does. Is .innerText the wrong property for IE?
Here's it running on jsbin.
Ah, I can access the value of the text node created by the innerHTML and that returns the correct value:
function EscapedString(str) {
var obj = document.createElement("div");
obj.innerHTML = str;
return "&#" + (obj.firstChild.nodeValue || obj.textContent).charCodeAt(0) + ";";
}
Here's the latest script running on jsbin
...and here's the gist of the final code I ended up using
Try this out. Split up the '&' character from 'nbsp'
alert('&' + 'nbsp');
That worked for me. are you able to do that?
if not, perhaps you can convert to ascii???
edited
alert(String.fromCharCode(EscapedString(" ")))

Categories

Resources