Why is this jQuery submit event not triggering correctly? - javascript

I am trying to create a function that takes a user's input and uses it to search Wikipedia. Then, at least for now, show the first result by appending it to the element call "#list".
I have tested the API, the JSON syntax, the appendTo syntax all independently and confirmed that they are working fine. But the event does not execute.
$('form').submit(function(event)
{
var $input = $(event.target).find('input');
var search = $input.val();
$.getJSON("https://en.wikipedia.org/w/api.php?action=query&format=json&list=search&titles=Main+Page&srsearch="+search+"&srprop=wordcount%7Ctimestamp%7Csnippet%7Ctitlesnippet",
function(data)
{
var item = data.query.pages.search[0].titlesnippet;
var itemDesc = data.query.pages.search[0].snippet;
var html = $('<li>').html(item+"<br/>"+itemDesc);
html.prependTo('#list');
});
});

Related

Jquery .change() event fires only once

So I'm fairly novice with jquery and js, so I apologise if this is a stupid error but after researching I can't figure it out.
So I have a list of data loaded initially in a template, one part of which is a dropdown box that lets you filter the data. My issue is that the filtering only works once? As in, the .change function inside $(document).ready() only fires the once.
There are two ways to reload the data, either click the logo and reload it all, or use the search bar. Doing either of these at any time also means the .change function never fires again. Not until you refresh the page.
var list_template, article_template, modal_template;
var current_article = list.heroes[0];
function showTemplate(template, data)
{
var html = template(data);
$("#content").html(html);
}
$(document).ready(function()
{
var source = $("#list-template").html();
list_template = Handlebars.compile(source);
source = $("#article-template").html();
article_template = Handlebars.compile(source);
source = $("#modal-template").html();
modal_template = Handlebars.compile(source);
showTemplate(list_template,list);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = list.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
$("#classFilter").change(function()
{
console.log("WOW!");
var classToFilter = this.value;
var filteredData =
{
heroes: list.heroes.filter(function(d)
{
if (d.heroClass.search(classToFilter) > -1)
{
return true;
}
return false;
})
};
console.log(filteredData);
showTemplate(list_template,filteredData);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = filteredData.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
});
$("#searchbox").keypress(function (e)
{
if(e.which == 13)
{
var rawSearchText = $('#searchbox').val();
var search_text = rawSearchText.toLowerCase();
var filteredData =
{
heroes: list.heroes.filter(function(d)
{
if (d.name.search(search_text) > -1)
{
return true;
}
return false;
})
};
console.log(filteredData);
showTemplate(list_template,filteredData);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = filteredData.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
}
});
$("#logo").click(function()
{
showTemplate(list_template,list);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = list.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
});
//$("#logo").click();
});
function displayModal(event)
{
var imageNumber = $(this).data("id");
console.log(imageNumber);
var html = modal_template(current_article.article[0].vicPose[imageNumber]);
$('#modal-container').html(html);
$("#imageModal").modal('show');
}
I should note two things: first, that the search bar works perfectly, and the anonymous function inside both of them is nearly identical, and like I said, the filtering works perfectly if you try it after the initial load. The second is that the same problem occurs replacing .change(anonymous function) with .on("change",anonymous function)
Any help or advice would be greatly appreciated. Thanks.
I agree with Fernando Urban's answer, but it doesn't actually explain what's going on.
You've created a handler attached to an HTML element (id="classFilter") which causes part of the HTML to be rewritten. I suspect that the handler overwrites the HTML which contains the element with the handler on it. So after this the user is clicking on a new HTML element, which looks like the old one but doesn't have a handler.
There are two ways round this. You could add code inside the handler which adds the handler to the new element which has just been created. In this case, that would mean making the handler a named function which refers to itself. Or (the easier way) you could do what Fernando did. If you do this, the event handler is attached to the body, but it only responds to clicks on the #classFilter element inside the body. In other words, when the user clicks anywhere on the body, jQuery checks whether the click happened on a body #classFilter element. This way, it doesn't matter whether the #classFilter existed when the handler was set. See "Direct and delegated events" in jQuery docs for .on method.
Try to use some reference like 'body' in the event listeners inside your DOM like:
$('body').on('click','.articleButton', function() {
//Do your stuff...
})
$('body').on('click','#classFilter', function() {
//Do your stuff...
})
$('body').on('keypress','#searchbox', function() {
//Do your stuff...
})
$('body').on('click','#logo', function() {
//Do your stuff...
})
This will work that you can fire it more than once.

Unexpected jQuery syntax error by chaining a plug-in after .find()

I've baked a plug-in to handle runtime searches on input fields I'm using all over a big site.The plug-in works perfect in every situation but this http://jsfiddle.net/tonino/v8d2A/
$(document).ready(function () {
var callback_methods = { /* methods here */ };
var input_html = '<div class="search"><input name="search-field" value="Search..."></div>';
$(document).on('click', 'div.add', function (event) {
if (!$('li div.add + div').hasClass('search')) {
var input = $(this).after(input_html).parent().find('input');
input.focus();
input.hunter({url:'<?php echo $this->request->base; ?>/searches', callback:callback_methods, var_name:'data[Search][term]'});
// other code after
}
});
});​
If I comment the hunter plug-in everything works fine.
I'm sure is some concept on how it must be structured, here is the code: jquery.hunter.1.3.js
Why my plug-in make this error in this situation, where I'm wrong on writing it?
the problem is this part of your code:
var selector = this.selector;
var def_css = {backgroundPosition:'-16px center', paddingLeft:$(selector).css('padding-left')}
if (settings.loader) { setStyle(def_css); }
var selector = this.selector;
and later:
$(this.selector).blur(function () {
first of all your code wont work when the if-condition is fulfilled, because you are trying to redeclare the variable 'selector' inside the if block. just leave the var-statement out there:
if (settings.loader) { setStyle(def_css); }
selector = this.selector;
but YOUR MAIN-problem is that 'this.selector' contains '.parent() input' which i doubt is a valid jQuery selector.
why are you doing that? why dont you just use $(this) save it into a variable and use this???
eg:
// first line in your plugin
$this = $(this)
// later you could use the $this var
$this.blur(function () {
To get rid of the error change this line:
var input = $(this).after(input_html).parent().find('input');
To the following:
var input = $(input_html).insertAfter($(this));
The core problem though is that the jquery.hunter plugin is using the this.selector variable for some reason - you don't need this - the plugin should use $(this) instead of $(this.selector)

jQuery updating elements added on the fly?

My code is not working, i think because elements are added on the fly:
var tooltip = $('<div/>').insertAfter('.trigger').addClass('tooltip');
var tname = $('<span/>').addClass('tname').text('(...)');
tooltip.html(tname.html()):
// Ajax call
success: function() {
tname.html('success'); // not working
$('.tooltip').find('.tname').html('success'); // not working
$('.tname').html('success'); // not working
}
This won't work because you are not inserting the tname element into the DOM. See this fix below:
var tooltip = $('<div/>').insertAfter('.trigger').addClass('tooltip');
var tname = $('<span/>').addClass('tname').text('(...)');
tooltip.html("");
tooltip.append(tname);
// Ajax call
success: function() {
tname.html('success'); // should work
$('.tooltip').find('.tname').html('success'); // should work
$('.tname').html('success'); // should work
}
You're not inserting the span into the DOM.
// append to some element
var tname = $('<span/>').addClass('tname').text('(...)').appendTo(tooltip);
Only then you can use selectors to find the element and do something with it.

Using jquery form submission was working fine until I added other JS libraries

I was using jquery for form submission it was working fine but when I included it in with other javascript libraries the .ready works but other events don't.
$(document).ready(jQueryCodeOfReady);
function jQueryCodeOfReady()
{
// arrays of target tags ..... w.r.t id
var hashtable = new Array();
hashtable['frm'] = 'result';
hashtable['newaccount'] = 'content';
/********************** AJAX related Section Started ******************************/
function _(url , data ,dataType,type ,thetag)
{
/***Animation Code***/
$(thetag).html("<span style=\"font-family:sans-serif; color:#274d87; background:url('loader.gif') no-repeat; padding-left:80px; width:164px; height:32px; \">wait ... </span>");
/***Animation Code ended***/
$.ajax({
type: type ,
url: url ,
data: data,
dataType: dataType,
success: function(data)
{
// show content etc in this tag
$(thetag).html(data);
} // ajax call back function
});
return false;
}
/*************************************************** AJAX related Section endeed *****************************************************************/
alert('sendf');
/*************************************************** Events Section Started *****************************************************************/
// Form submission using ajax ... when event happens then specific code called
$("form").submit(function (e)
{
// don't perform default html event behaviour
e.preventDefault();
// get form attribute and the taag in which the result should be shown
var formid="#"+$(this).attr('id'); // identify the form
var formaction=$(this).attr('action'); // the path where to move ahead after this event occurs
var targettag="#"+hashtable[$(this).attr('id')]; // hashtable array declared upthere
// get form data
var formdata = $(formid).serialize();
// give serverCall
_(formaction,formdata ,"text/html","POST",targettag );
});
$("a.searchlink2").click(function (e){
var path=$(this).attr('href');
var formdata='';
e.preventDefault();
// give serverCall
_(path,formdata ,"text/html","POST",'#result');
});
}
You may take a look at the using jQuery with other libraries section of the documentation.

How can I pass args to event handler?

How can I pass args to the event handler function? This runs the function on page load which is not the desired effect. I need this routine validateText to run against several different textbox, dropdown combinations. Can I reuse validateText instead of creating one per text/dropdown combination??
//add blur event handler to the textbox with jQuery when the page is finished loading
$(document).ready(function() {
$("#myTextbox").blur(validateText($("#myTextbox"), $("#Select1")));
})
function validateText(textbox, dropdown) {
var message = $("#message");
var isValid = false;
//get the value the user type in
var textboxValue = $(textbox).val();
//get the options from the lookup
var options = $("option", dropdown);
//loop through the options and compare it to "value"
options.each(function() {
var optValue = $(this).val();
if (optValue === textboxValue) {
isValid = true;
}
});
if (!isValid)
message.text(textboxValue + " is not a valid value from the list.");
else
message.text(textboxValue + " is perfectly valid.");
}
Use binding to pass extra parameters to an event listener:
http://docs.jquery.com/Events/bind
$(document).ready(function() {
$("#myTextbox").bind("blur", [ $("#myTextBox"), $("#Select1")], validateText);
})
Then access the data from event.data:
function validateText(event) {
textBox = event.data[0];
dropdown = event.data[1];
}
The reason it calls at load is because handing over a function name with arguments actively calls it. You can effectively mimic what you're looking for by wrapping the call to validateText in an anonymous function like so.
$(document).ready(function() {
$("#myTextbox").blur(function(){
// Since in your original example you used $("#myTextbox") as an arg, this mimics it
validateText($(this), $("#Select1"));
});
});
The anonymous function, since it's using the 'this' keyword, should scale a little better with your initial selector if you change it from #myTextbox to textarea or whatever. =)

Categories

Resources