Why is wrap ignoring the last wrap? - javascript

I'm trying to turn more into a hyperlink, but it's like it totally ignores the last wrap.
$j('#sub > div[id^="post-"]').each(function() {
var sid=this.id.match(/^post-([0-9]+)$/);
var sfimg = $j(this).find("img");
var sfhh = $j(this).find("h2");
var sfpt = $j(this).find("p:not(:has(img)):eq(0)");
var more = 'more';
$j(this).html(sfimg);
$j(sfimg).wrap($j('<a>').attr('href', '/blog/?p='+sid[1]));
$j(this).append(sfhh).append(sfpt);
$j(sfpt).wrap($j('<div>').attr('class', 'sfentry'));
$j(this).append('<div class="morelink">'+more+'</div>');
$j(more).wrap($j('<a>').attr('href', '/blog/?p='+sid[1]));
});

You over-using the jquery function ($j(), in your case) and your doing things in the wrong order. Also, there may be cases (possibly) that $(this).find('img'), for instance, might return more than one element... Not sure of your scenario, though.
Try this (may not be perfect, but it should lean you in the right direction):
$j('#sub > div[id^="post-"]').each(function() {
var sid = this.id.match(/^post-([0-9]+)$/);
var sfimg = $j(this).find("img");
var sfhh = $j(this).find("h2");
var sfpt = $j(this).find("p:not(:has(img)):eq(0)");
var more = 'more';
sfimg.wrap($j('<a>').attr('href', '/blog/?p='+sid[1]));
$j(this).html(sfimg);
sfpt.wrap($j('<div>').attr('class', 'sfentry'));
// You do realize what you have will append the paragraph to your h2 tag, right?
// I think you want:
/*
$j(this).append(sfhh).end().append(sfpt);
*/
$j(this).append(sfhh).append(sfpt);
$j(this).append('<div class="morelink">'+more+'</div>');
$j('.morelink',this).wrap($j('<a>').attr('href', '/blog/?p='+sid[1]));
});
There were all sorts of crazy things going on in that code. Remember that you need to modify the objects before appending them to another object (unless you have some unique way of identifying them after the fact, i.e. IDs).
Good luck.

Why do you expect $j(more) to match anything?

Related

How can I define 2 classes in one var?

I have a problem with define a second class in one Var
Here is the Code: http://jsfiddle.net/2DuQc/
How can I make work this fine?
It's written in JQuery!
var animateEye = $('.rightEye, .leftEye');
doesnt work!
Actually your code won't work because you are overwriting your variabile with only one selector .leftEye so the .rightEye will not have nothing attached to it.
You can use a multiple selector than loop through the result using jQuery each and apply yuor current code.
Use the same class as inner element and find it as a children of the current element.
Code:
$('.rightEye, .leftEye').each(function () {
var animateEye = $(this);
var eyes = animateEye.find(".Eye");
Demo: http://jsfiddle.net/IrvinDominin/rU9E2/
var animateEye = $('.rightEye, .leftEye');
This will give you an array of items, so when you call, say, animateEye.offset(), which one is it supposed to choose? It'll bomb out.
Your current code:
var animateEye = $('.rightEye');
var eyes = $(".Eye");
var animateEye = $('.leftEye');
This will obviously always use .leftEye.
My suggestion? Loop through rightEye and leftEye like so:
var eyes = $('.rightEye, .leftEye');
for(var i = 0; i < eyes.length; i++) {
var animateEye = eyes[i];
}

adding line breaks to array values javascript

Here is my javascript array:
var quizArray = [
'When the weather is agreeable what do you prefer to do the most?~Something outside...Obviously!~I tend to enjoy things that aren\'t dependent on weather.~Read, possibly outside if I can find my sunscreen.~Do what I always do, which is whatever I want.~Try something new, like Planking.~~~','It\'s a weeknight and friend invites you to an orchestra. You would?~Kindly refuse. It\'s just not my thing.~Go, unquestionably. I love all art forms.~Ask who the composer is, then read all about them before going.~Confuse Orchestra with Opera and begin singing in Latin.~Go if the tickets are free, otherwise no.~~~',]
When I load my html it won't display line breaks after each answer. I've tried adding a .join(<\br>) after split, but that breaks up every single word, here is the code I have:
function displayQuiz(ent, qnum) {
perPage++;
var qna = quizArray[qnum].split('~');
var od = []; for (var i = 1; qna[i] != null && qna[i] != ''; i++) od.push(i); od.sort( randOrd ); od.sort( randOrd );
var newF = document.createElement("form");
var newDq = document.createElement("div");
newDq.className = 'question';
newDq.appendChild(document.createTextNode(Number(qnum+1)+ ': ' +qna[0]));
newF.appendChild(newDq);
newDq = document.createElement("div");
newDq.className = 'answers';
for (var i = 1; qna[i] != null && qna[i] != ''; i++) {var newDa = document.createElement("label"); newDa.htmlFor = 'a'+qnum+i; /*#cc_on #if (#_jscript) var newR = document.createElement("<input name='a"+qnum+"'>"); #else */
var newR = document.createElement("input");
newR.name = 'a'+qnum; /* #end #*/
newR.type = 'radio';
newR.id = 'a'+qnum+i;
newR.value = od[i-1];
newDa.appendChild(newR);
newDa.appendChild(document.createTextNode(' '+qna[od[i-1]]+' '));
newDq.appendChild(newDa);}
newF.appendChild(newDq);
document.getElementById('quiz'+perPage).appendChild(newF);
}
I'll try my best to post additional info if needed. I did use this as a snippet and am very novice on Javascript. Not opposed to learning on my own but I've poured over the interwebs and cannot find my answer.
to make an array of Strings its better if you put your complete string in a var and after make a split(), and for add you can use a join() or a for()
It's better put this way the code
var quizArray = 'When the weather is agreeable what do you prefer to do the most?~Something outside...Obviously!~I tend to enjoy things that aren\'t dependent on weather.~Read, possibly outside if I can find my sunscreen.~Do what I always do, which is whatever I want.~Try something new, like Planking.~~~';
function displayQuiz(ent, qnum) {
perPage++;
var qna = quizArray.split('~');
var res = qna.join(" <br> ");
return res;
}
Here is the approach that I took, using .join to add the br element. I think you weren't specifying what to split on originally, if it added br after every word.
var string = 'When the weather is agreeable what do you prefer to do the most?~Something
outside...Obviously!~I tend to enjoy things that aren\'t dependent on weather.~Read, possibly outside if I can find my sunscreen.~Do what I always do, which is whatever I want.~Try something new, like Planking.~~~';
var quizArray = string.split('~');
var finalString = quizArray.join('<br/>');
document.getElementById('yourIdHere').innerHTML = finalString;
Here's a fiddle: http://jsfiddle.net/brettwlutz/Q35J2/1/
i thought arrays were made as so:
var arr = [val1, val2, val3];
you can use arr.push to append more values or arr.unshift to add values to the beginning of the array
http://jsfiddle.net/h_awk/K3kEv/
<script>
var arr = [1, 2, 3, 4], i;
for( i=0; i<arr.length; i++ )
{
document.write(arr[i] + '<br />');
}
</script>
First, to answer your question. The above code should work and make the variable qna contain the new, split array. Your solution of adding .join("") should then turn that new array into a single string with html newlines. That is, unless you want t JS newline, in which case you should instead use .join("\n").
My question for you is, why are you starting with an array with only one element? A string can be split into an array and joined back into a string the same way. Also, it may be easier to, instead of using the tilde ~ to seperate the statements you want to split, just use a form of proper array syntax, then get rid of the "split" and just use the joining:
var quizArray = ["When the weather is agreeable what do you prefer to do the most?", "Something outside...Obviously!, I tend to enjoy things that aren\'t dependent on weather.", "Read, possibly outside if I can find my sunscreen.", "Do what I always do, which is whatever I want.", "Try something new, like Planking."];
My only possible understanding is that you are still learning JS and this is just an example for learning how to split arrays, but this is not really a real-life application, which is why this post seems questionable to Stack Overflow users.

Pass array to Javascript onClick function while adding links into a string?

I know the question sounds strange, but it's really very simple. I have the following function which isn't working:
function start40Counter(counter40_set){console.log(counter40_set);
var gid = counter40_set[0];
var seat = counter40_set[1];
var suits = counter40_set[2];
var cont = "";
$.each(suits, function (num, suit) {
cont += "<a class='suitpick' onClick='pickSuit(counter40_set);'><img src='"+base+"images/someimg.png' title='Odaberi' /></a>";
});
$('#game40_picks').html(cont);
}
counter40_set is [10, 3, ["H", "S"]]. The part of the function that fails is the part this:
onClick='pickSuit(counter40_set);'
It says that counter40_set is not defined. I understand that. This wouldn't even work if counter40_set was a simple string instead of an array. If I try onClick='pickSuit("+counter40_set+");' I get a different error, saying H is not defined. I get this too, the array is rendered and JS doesn't know what H and S are.
I also tried passing the array elements (counter40_set[0] etc) individually but it still fails with the last element (["H", "S"]).
So, how do I pass this data to the onClick function in this case? There must be a more elegant way than concatenating the whole thing into a string and passing that to the function?
Btw, this is a simplified version. What I should really be passing in every iteration is [suit, counter40_set] so that each link chooses a different suit. I'm asking the simplified question because that will be enough to send me down the right path.
It cannot work,because the context is lost and thus "counter40_set" is not set.
To fix it simply use jquery for the onlick as well:
$('#game40_picks').empty(); // get rid of everything
$.each(suits, function (num, suit) {
var line = $("<a class='suitpick'><img src='"+base+"images/"+cardsuits[suit].img+"' title='Odaberi "+cardsuits[suit].name+"' /></a>");
line.click(function(ev){
ev.preventDefault(); // prevent default click handler on "a"
pickSuit(counter40_set);
});
$('#game40_picks').append(line);
});
this way the "counter40_set" is available for the click function.
You shouldn't use the onClick HTML attribute. Also, using DOM functions to build nodes saves the time it takes jQuery to parse strings, but basically the method below is to create the element and attach a click event listener and then append it to the specified element.
function start40Counter(event){console.log(event.data.counter40_set);
var counter40_set = event.data.counter40_set;
var gid = counter40_set[0];
var seat = counter40_set[1];
var suits = counter40_set[2];
var cont = "";
$.each(suits, function (num, suit) {
var link = document.createElement('a');
link.className = 'suitpick';
$(link).on('click', {counter40_set: counter40_set}, start40Counter);
var img = document.createElement('img');
img.src= base + "images/" + cardsuits[suit].img;
img.title = 'Odaberi ' + cardsuits[suit].name;
link.appendChild(img);
$('#game40_picks').append(link);
});
}
Not tested but it might work out of the box.

Alternative to using eval()

I've heard a lot of rumblings about how "evil" or even "misunderstood" the eval function is, so I've decided to remove it from my code. The problem is I don't know what to replace it with.
Here's a quick rundown of my current code. I have a series of arrays (just 2 for the example below) declared at the beginning, and then based on a button click one of them gets loaded into a variable that is passed into a function.
Here's some basic HTML
<div class="button" data-name="button1">Button1</div>
<div class="button" data-name="button2">Button2</div>
and the JS (with jQuery)
var butName = null;
var eArray = null;
var button1Logo = ["..path/to/pic1.png","..path/to/pic2.png"];
var button2Logo = ["..path/to/pic3.png","..path/to/pic4.png"];
$(".button").mouseup(function(){
/*give a butName*/
butName = $(this).attr("data-name");
/*give the array from the button*/
eArray = eval(butName + "Logo");
});
Doing it this way assigns the array to the variable and not just a string that says "butnameLogo" which is why I used eval. But I'm looking to get away from that.
I know I can add a new attribute to the html and just retrieve that for the variable but I don't want to add more html when I can possibly do it with JS.
I've also tried making an object with strings loaded into it as seen in this answer: https://stackoverflow.com/a/16038097/1621380 but that resulted in just a string again, and not assigning a variable.
Wondering if you smart people have any better suggestions!
Replace
var button1Logo = ["..path/to/pic1.png","..path/to/pic2.png"];
var button2Logo = ["..path/to/pic3.png","..path/to/pic4.png"];
with an object, where the keys are your button names:
var buttonLogos = {
button1: ["..path/to/pic1.png","..path/to/pic2.png"],
button2: ["..path/to/pic3.png","..path/to/pic4.png"]
};
Then instead of the eval you can simply do
eArray = buttonLogos[butName]
(or buttonLogos[butName + "Logo"] if you want to call the keys button1Logo and button2Logo, but I can't really see the point now that they are nicely contained within a buttonLogos object)
Use an object:
var butName = null;
var buttonsLogos = {
button1: ["..path/to/pic1.png", "..path/to/pic2.png"],
button2: ["..path/to/pic3.png", "..path/to/pic4.png"]
};
$(".button").mouseup(function(){
/*give a butName*/
butName = $(this).attr("data-name");
/*give the array from the button*/
eArray = buttonsLogos[butName];
});
Consider making the data available as properties of an object, then you can control access to the object through scope and only need one (global?) variable for all such data.
If global scope is needed, then:
var dataObj = {
button1Logo: ["..path/to/pic1.png","..path/to/pic2.png"],
button2Logo: ["..path/to/pic3.png","..path/to/pic4.png"]
}
and later:
var eArray = dataObj[this.data-name + 'Logo'];
You may want to call the data object something more meaningful than dataObj though.
The best option is to define an object which holds all our button paths:
var buttons = {
"1": ["..path/to/pic1.png", "..path/to/pic2.png"],
"2": ["..path/to/pic3.png", "..path/to/pic4.png"]
};
$(".button").mouseup(function(){
/* give a butName */
var butName = $(this).attr("data-name");
/* give the array from the button */
var eArray = buttons[butName];
});
If your variables reside in the global scope, you could use the bracket notation to access them:
eArray = window[butName + "Logo"];
Note that this solution is not recommended. The first code sample is much cleaner and more maintainable.
Imagine a situation where you would have to move all the code into a 'deeper' context (!= global context). Nothing would work anymore.
You can do this very nicely with arrays and array indexes. You needn't find and use variable names at all. Even your data- attributes are unnecessary.
var eArray;
var buttonLogos = [
["..path/to/pic1.png","..path/to/pic2.png"],
["..path/to/pic3.png","..path/to/pic4.png"]
];
var buttons = $(".button").mouseup(function(){
var idx = buttons.index(this);
eArray = buttonLogos[idx];
});
The key line in this is buttons.index(this). This method call gets the position of the current element among all the elements matched by $(".button"). We then use this index to select the relevant element from the buttonLogos array.
You're taking a very circuitous route by using eval here.
You'd be much better off doing something like this:
var paths = {
button1: ["..path/to/pic1.png","..path/to/pic2.png"],
button2: ["..path/to/pic3.png","..path/to/pic4.png"]
};
$(".button").mouseup(function(){
/*give the array from the button*/
eArray = paths[$(this).attr("data-name")];
});
eval should only be used if you need to execute code (usually from a 3rd party source), and even that is rare. If you ever find yourself saying "i should use eval here", there's almost definitely a better alternative, and you should try and find it.

How to get the next element of an array with Jquery onclick

Hi all i am trying to change the html of an object from an array of htmls. But i am having problem iterating properly. I managed to make it work once
EDIT
After a few complains about the clarity of my question I will rephrase it. I have a div panel called .trpanel and a button called #trigger2 (it is a next button). Then I have a series of divs with texts that contain translations. I want when I press the button (called next) to cycle through the translations one by one on the trpanel.
var ltranslation = [];
ltranslation[0] = $("#translation-en-1").html();
ltranslation[1] = $("#translation-ur-en").html();
ltranslation[2] = $("#translation-fr-en").html();
ltranslation[3] = $("#translation-it-en").html();
ltranslation[4] = $("#translation-sp-en").html();
ltranslation[5] = $("#translation-po-en").html();
ltranslation[6] = $("#translation-fr-en").html();
ltranslation[7] = $("#translation-de-en").html();
var l= ltranslation;
$("#trigger2").off('click').on('click',function(){
for (var i = 0; i <= ltranslation.length; i++){
if (i==7){i=0;}
$(".trpanel").html.ltranslation[i]; or ???//replace().ltranslation[]+i??? the code throws errors
}
});
I am quite new to Javascript and i am getting a bit confused with the types of objects and arrays and loops. I managed once to add the htmls but without replacing them ... so they all came one after the other. The i tried to change the code and it hasn't worked since. Any help will be greatly appreciated.
A lot of guessing, but seems like you are trying to do this :
var trans = $('[id^="translation-"]'),
idx = 0;
$("#trigger2").on('click',function(){
$(".trpanel").html( trans.eq(idx).html() );
idx = idx > 6 ? 0 : idx+1;
});
FIDDLE
I think you are trying to do this:
if (i == 7) {
i = 0; // I don't really know why you are doing this, but it will reset the loop
}
$(".trpanel").html(ltranslation[i]); //I'm passing ltranslation[i] to the html method. Instead of .html.ltranslation[i].
}
Also, without seeing any html, I'm not sure but I think you may want to iterate over .trpanel ?
Something like:
$(".trpanel").eq(i).html(ltranslation[i]);
Another thing (so you can make your code clearer I think). You can abstract the array population in a function, like this:
var ltranslation = [];
var languages = ["en-1", "ur-en", "fr-en", "it-en", "sp-en", "po-en", "fr-en", "de-en"];
$.each(languages, function(index) {
ltranslation[index] = $("#translation-" + this).html();
});
// Then you can use ltranslation
If you want to flip through several translations I would implement it that way:
var translations=["hej","hello", "hallo","hoy"];
var showTranslation=function(){
var current=0;
var len=translations.length;
return function(){
var direction=1;
if (current>=len) current=0;
$("#text").text(translations[current]);
current+=direction;
}
}();
$("#butt").on("click", showTranslation);
Fiddle: http://jsfiddle.net/Xr9fz/
Further: You should give your translations a class, so you could easily grab all of them with a single line:
$(".translation).each(function(index,value){ ltranslation.push(value); })
From the question : I managed once to add the htmls but without replacing them -
I think you want to add all of these items into $(".trpanel"). First, dont take the HTML of each element, clone the element itself :
//method ripped from Nico's answer.
var ltranslation = [];
var languages = ["en-1", "ur-en", "fr-en", "it-en", "sp-en", "po-en", "fr-en", "de-en"];
$.each(languages, function(index) {
ltranslation[index] = $("#translation-" + this).clone();
});
Then you could append everything into the container, so add the htmls but without replacing them. append takes in an array without replacing the previous html.
$("#trigger2").off('click').on('click',function() {
$(".trpanel").append(ltranslation);
});
I don't know what exactly you're tring to do, but I've put comments in your code to help you better understand what your code is doing. The net effect of your code is this (which I doubt you want) :
$("#trigger2").off('click').on('click',function(){
$(".trpanel").html(ltranslation[7]);
});
This is your code with some comments and minor changes
var ltranslation = [];
ltranslation[0] = $("#translation-en-1").html();
ltranslation[1] = $("#translation-ur-en").html();
ltranslation[2] = $("#translation-fr-en").html();
ltranslation[3] = $("#translation-it-en").html();
ltranslation[4] = $("#translation-sp-en").html();
ltranslation[5] = $("#translation-po-en").html();
ltranslation[6] = $("#translation-fr-en").html();
ltranslation[7] = $("#translation-de-en").html();
var l= ltranslation;
$("#trigger2").off('click').on('click',function(){
for (var i = 0; i < ltranslation.length; i++){
//if (i==7){i=0;} <-- This will cause an infinite loop won't it? are you trying to reset i? i will reset next time loop is called,
$(".trpanel").html(ltranslation[i]); //<-- this will overwrite elements with class .trpanel ltranslation.length times...
///you'll see only the value of translation[7] in the end
}
});
EDIT
To do what you want to do based on your comments, try this:
var ltranslation = [];
ltranslation[0] = $("#translation-en-1").html();
ltranslation[1] = $("#translation-ur-en").html();
ltranslation[2] = $("#translation-fr-en").html();
ltranslation[3] = $("#translation-it-en").html();
ltranslation[4] = $("#translation-sp-en").html();
ltranslation[5] = $("#translation-po-en").html();
ltranslation[6] = $("#translation-fr-en").html();
ltranslation[7] = $("#translation-de-en").html();
var counter = 0;//a global counter variable
$("#trigger2").click(function(){ //eeverytime button is clicked do this
$(".trpanel").html(ltranslation[counter]); //set the html to an element of array
counter++; //increment counter
if(counter==ltranslation.length) //reset the counter if its bigger than array len
counter=0;
});

Categories