jQuery.find() doesn't work inside html variable - javascript

I have a very simple problem and keep finding answers to similar questions with more complexity. I am trying to replace image links in loaded html and decided that the best is to read the html into a string variable loadedHTML using .get(), like this:
$.get(loadURL, function(loadedHTML) {
myFunction(loadedHTML);
}, 'html');
In myFunction, I want to make some changes to the loaded html and eventually return it. I can't get .find() to work. Here is what that code looks like:
function myFunction( html ) {
var $html = $("<div>" + html + "</div>");
console.log( "$html.html() = " + $html.html()); // works!
$html.find("img", function() {
console.log("found an image"); // doesn't work :(
});
}
I am killing myself with something that is probably really simply. Let me know how I am dumb please...

I'm almost sure that you cannot use find in the way that you have.
Try something like:
var $foundImages = $html.find("img");
console.log($foundImages.length);
Which would, in theory, output the number of images that were found.

The find method doesn't have a second parameter:
http://api.jquery.com/find/
You should try this:
function myFunction( html ) {
var $html = $("<div>" + html + "</div>");
console.log( "$html.html() = " + $html.html()); // works!
console.log($html.find("img"));
}

Simply assign id to your div tag .
like below,
var $html = $("<div id='placeholder'>" + html + "</div>");
and find img with it like below,
$("#placeholder").find("img", function() {
console.log("found an image"); // doesn't work :(
});
your resultant code,
function myFunction( html ) {
var $html = $("<div id='placeholder'>" + html + "</div>");
console.log( "$html.html() = " + $html.html()); // works!
$("#placeholder").find("img", function() {
console.log("found an image"); // doesn't work :(
});
}

.find() didn't have callback function in jquery. it have parameter for selectors,elements,jqueryObject only.you have to check with length or condition like this
if($html.find("img").length > 0){
// do stuff here
}
or
if($html.has("img")){
// do stuff here
}

You can use this .filter():
var found = $html.find("img").filter(function() {
return this;
});
console.log(found);
or make an array out of it with .map():
var found = $html.find("img").map(function() {
return this;
}).get(); // use get() method here to get the values in array
console.log(found.length); // would give you the length of array created.

jQuery.find() doesn't have a callback but you can extend jQuery to do what you want:
jQuery.fn.extend({
findEach: function (selector, callback) {
var found = this.find(selector);
if (typeof callback == 'function' && found.length > 0) {
found.each(callback);
}
return found;
}
});
Then use like you expect:
$html.findEach("img", function(key, value) {//will run for each image
console.log(key);
console.log(value);
console.log(this);
});

Related

Accesing function within function JavaScript

I got this piece of code below which is not DRY. What i want to do is to cut it,so everything below var = text would be used only once not twice.
My concept is,to close these two functions in bigger function (e.g. guess()) and keep trimmed correctGuess() and incorrectGuess() within it.
Now here's the question,how can I call such nested function as describe above from outside scope. I was thinking about smth like: guess().correctGuess() which is obviously wrong but I wanted to share a concept.
Additionally, when e.g. correctGuess() would be called, is rest of the commands within our main guess() function would be executed?
function correctGuess(i) {
totalScore++;
questionNumber++;
var text = "Correct!";
var updatePage = ['<div id="answerDiv">' +
'<h1>' + text + '<h1>' +
'<h2>Total Score: ' + totalScore + '</h2></div>'
];
mainContent[html](updatePage);
$('#answerDiv')[fadeIn]("slow");
$('#answerDiv').append('<button id="nextButton">Next Question</button>');
$('#nextButton').on('click', function() {
if (questionNumber == allQuestions.length && totalScore <= 4) {
results()
} else {
question(questionNumber)
}
})
};
var incorrectGuess = function(i) {
totalScore--;
questionNumber++;
var text = "Wrong!";
var updatePage = ['<div id="answerDiv">' +
'<h1>' + text + '<h1>' +
'<h2>Total Score: ' + totalScore + '</h2></div>'
];
mainContent[html](updatePage);
$('#answerDiv')[fadeIn]("slow");
$('#answerDiv').append('<button id="nextButton">Next Question</button>');
$('#nextButton').on('click', function() {
if (questionNumber == allQuestions.length && totalScore <= 4) {
results();
} else {
question(questionNumber);
}
});
};
http://www.w3schools.com/js/js_objects.asp
From your question it seems like you aren't very familiar with object notation. Read up on the above link and then try to create a js "guess" object with 2 member functions. Correct and Incorrect guess.
You need to use the this keyword.
function guess(){
/* do stuff here for guess() */
this.correct = function(){
/* Do stuff for correct */
}
this.wrong = function(){
/* Do stuff for wrong */
}
return this;
}
Because you returned this you can now access the correct() and wrong() functions using:
guess().correct();
// AND
guess().wrong();
Note that whatever code you write inside guess() and outside the two nested functions will also be called every time you call guess().correct() or guess().wrong()
If you do not want any particular code to execute every time they "guess" regardless of right or wrong then I would suggest just storing the correct() and wrong() functions in an object literal.
var guess = {
correct: function(){
// Code for "correct" here
},
wrong: function(){
// Code for "wrong" here
}
}
And then you can access them using
guess.correct();
// AND
guess.wrong();

jquery this pointer scope when call a function in ajax

I want to call a external function from $.ajax when getting through a xml file, but I am confused by the scope of this pointer in this case.
so in my ajax function
function getCustomerInfo (customerID) {
$.ajax ({
type: "GET",
url: "./content/customer_list.xml",
dataType:"xml",
success: function (xml) {
$(xml).find("customer[value=" + customerID + "]").each(function(){
//I want to create a function and call here to achieve the following commented code
//the commented code works fine. I just want to change it to a function because
//otherwise I have to hard code many similar lines...
// so here is the current function I call:
addCustomerDetails("timeAdded", "time_added");
// the following code works fine:
// var timeAdded = $(this).children('time_added').text();
// var lastUpdate = $(this).children('last_update').text();
// $("#time_added").html("<p>" + timeAdded + "</p>");
// $("#last_update").html("<p>" + lastUpdate + "</p>");
});
}
});
}
So the current addCustomerDetails function:
function addCustomerDetails (varName, tagName) {
window[varName] = $(this).children("time_added");
$("#"+tagName).html("<p>"+window[varName]+"</p>");
}
So I need a variable name as the argument, so I used window[varName]. Maybe this is also a problem, but I think the $(this) in addCustomerDetails() also doesn't seem work.
I hope I have explained it clearly. Please post any questions if this isn't clear enough and realllly appreciate your help!!
function addCustomerDetails (tagName) {
var tag = $(this).children(tagName).text();
$("#" + tagName).html("<p>" + tag + "</p>");
}
and call it like this:
addCustomerDetails.call(this, "time_added");
addCustomerDetails.call(this, "last_update");
Or following this path you can invent something even more convenient to use:
$(xml).find("customer[value=" + customerID + "]").each(appendTag('time_added', 'last_update'));
where appendTag will look like:
function appendTag() {
var tags = [].slice.call(arguments);
return function() {
for (var i = 0; i < tags.length; i++) {
var tag = $(this).children(tags[i]).text();
$("#" + tags[i]).html("<p>" + tag + "</p>");
}
};
}
When you call getCustomerInfo, assuming the caller has access to addCustomerDetails, you can save a reference to it before you make your ajax call and then use that reference to call addCustomerDetails or pass it as the caller if assigned 'self' doesn't have access, like:
var self = this;
$.ajax(
....
self.addCustomerDetails(...);
);
If addCustomerDetails isn't in the context of self, the other option is:
addCustomerDetails.apply(self, ...)
For differences between call and apply, you can check this SO thread:
What is the difference between call and apply?

Is there a way to access jQuery object from previous chain?

Not sure how I could search for these type of question/answer...
This is what I am trying to do...
(function($){
$.fn.helloworld = {
want: function () {
alert("I want" + this + "!");
}
};
})(jQuery);
Now when I call the function this way, and try to retrieve this, it will only give me the helloworld "object".
$("#test").helloworld.want();
Is there a way to access the caller element, #test, from within?
There's no "nice" way. You could do this:
var $test = $('#test');
$test.helloworld.want.call($test);
The problem is that by setting up the structure you've got you're essentially forcing the behavior you say you don't want.
What you could do instead is this:
$.fn.helloworld = function( action ) {
var actions = {
test: function() {
alert("Hi!");
},
// ...
};
if (actions[action])
return actions[action].apply(this, [].slice.call(arguments, 1));
return this;
};
Now you can call it:
$('#this').helloworld("test");

Pass html object through string into function

What I have is kinda unusual I guess. I have this function deleteItem which is triggered onclick and has the following parameters
function dItem(type,id,element,confirmed){
if(confirmed){
handle delete function
}else{
var c = ',';
popup('Are you sure you want to delete this item?',
{
"Yes":"dItem('"+type+"'"+c+id+c+element+c+true+")",
"Cancel":"popupClose()"
}
)
}
}
.. onclick='dItem("comment",15,this,false)' ..
In popup()'s second parameter are passed the buttons that are to be displayed in the popup and the functions they call respectively. The problem is that element is a HTMLDIV element and I cannot figure out a neat way to pass that through a string. The only solution I could come to think of is to have a global variable holding the element in question and not passing it at all, although I don't really want to do that since it's more of a hack rather than a solution. Does anybody have any idea how I can pass that element through a string? Thanks in advance!
EDIT:
This is how the buttons object b is being processed and turned into HTML. Do you see how I can supply it with an actual function instead of just a name in the form of string?
var _b = '';
for(var i in b){
_b+="<div onclick='"+b[i]+"'>"+i+"</div>";
}
It's more common to handle this situation with callbacks. You will need to alter your popup function for that to work.
Example:
popup('Are you sure you want to delete this item?', {
"Yes": function () {
dItem(type, id, element, confirmed);
},
"Cancel": function () {
popupClose();
}
});
As a workaround you could simply generate an unique ID for the element and use that to identify the element later on. Because your function is recursive you need to deal with the fact that element can be either a ELEMENT_NODE or a string.
for(var i in b){
var generatedId = i /* TODO: not sure this generates an unique id */;
_b += "<div id='" + generatedId + "' onclick='" + b[i] + "'>" + i + "</div>";
}
function dItem (type, id, element, confirmed) {
if (confirmed) {
// handle delete function
}else{
var elementId;
// find the elementId
if (element && element.nodeType && element.nodeType == 1) {
elementId = element.id;
}else if (typeof element == 'string') {
elementId = element
}else{
throw Error('Argument [element] is not a ELEMENT_NODE or string');
}
var args = [type, id, elementId, true];
popup('Are you sure you want to delete this item?', {
"Yes": "dItem(" + args.join(', ') + ")",
"Cancel": "popupClose()"
});
}
}

javascript api simplified

Was using fourquare api to get venue, had previously had a clickable list written out from api but cut it down to just one venue name written to screen. Then decided it'd be best to just send it over to php. So when I did what I thought was logical cutting of the code, it stopped working completely.
My program has this, working:
$(document).ready(function doEverything(element) {
$.getJSON("https://api.foursquare.com/v2/venues/search?ll=" + lat + "," + lng + "&client_id=L2VWBKPOW45D5X3FJ3P4MJB5TGVJ4ST2J005RIVAFIWG44ND%20&client_secret=ZKDAOLHASCA31VUOGMBTAS3RFYUOMXL4IFFYPRURIDQA3QMA%20&v=20111107", function(data) {
one = data.response.venues[0].name;
var list = [];
list[0] = [one];
function Make() {
for (var i = 0; i < 1; i++) {
var div = document.createElement("div");
div.style.margin = "-435px 100px 0px 110px";
div.innerHTML = list[i];
!
function() {
var index = 0;
div.onclick = function() {
doSomething(this);
};
}();
document.body.appendChild(div);
}
}
function doSomething(element) {
var value = element.innerHTML;
switch (value) {
case one:
break;
}
}
Make();
});
});
Then I decided I wanted to pass a variable over to php using this:
theVar = 10; //just to make things simple.
urlString = "cookiestesttwo.php?var=" +theVar;
window.location = urlString;
So I tried to simplify my api code to this, and it stopped working:
$(document).ready() {
$.getJSON("https://api.foursquare.com/v2/venues/search?ll=" + lat + "," + lng + "&client_id=L2VWBKPOW45D5X3FJ3P4MJB5TGVJ4ST2J005RIVAFIWG44ND%20&client_secret=ZKDAOLHASCA31VUOGMBTAS3RFYUOMXL4IFFYPRURIDQA3QMA%20&v=20111107", function(data) {
one = data.response.venues[0].name;
document.write(one)
theVar = one
urlString = "cookiestesttwo.php?var=" + theVar;
window.location = urlString;)
};
};​
$(document).ready() { is not proper syntax and does throw errors.
Furthermore there was another syntax error at the end of the function. you reversed } and )
$(document).ready(function() {
$.getJSON("https://api.foursquare.com/v2/venues/search?ll=" + lat + "," + lng + "&client_id=L2VWBKPOW45D5X3FJ3P4MJB5TGVJ4ST2J005RIVAFIWG44ND%20&client_secret=ZKDAOLHASCA31VUOGMBTAS3RFYUOMXL4IFFYPRURIDQA3QMA%20&v=20111107", function(data) {
one = data.response.venues[0].name; // if one is local to this function then use VAR otherwise you'll leak it globally.
document.write(one);
theVar = one; // same here for the VAR keyword.
urlString = "cookiestesttwo.php?var=" + theVar; // and here as well. NO GLOBAL LEAKS!
window.location = urlString;
});
});
I threw a few more hints in the comments.
Your problem might be that you use document.write() when the DOM is already complete. You are not supposed to do that. Create an element document.createElement( "div" ) and set the innerText() and then append it to the dom. Much like you did before the refactor.
EDIT
I understand that it wasn't the document.write() but just do clarify what I was talking about I wrote a little refactor. I also threw out the theVar = one since that is redundant. Also make sure to declare your variables in the right scope. Therefore I added a var in front of the one.
$(document).ready(function() {
$.getJSON("https://api.foursquare.com/v2/venues/search?ll="+lat+","+lng+"&client_id=L2VWBKPOW45D5X3FJ3P4MJB5TGVJ4ST2J005RIVAFIWG44ND%20&client_secret=ZKDAOLHASCA31VUOGMBTAS3RFYUOMXL4IFFYPRURIDQA3QMA%20&v=20111107",
function(data){
var one = data.response.venues[0].name;
var div = document.createElement( "div" );
div.innerText( one );
document.appendChild( div );
window.location = "cookiestesttwo.php?var=" + one;
});
});
But if you change the location of the window. There is no point to document.write() or appending a new div since you leave the site anyways.

Categories