I'm having a problem with my code, lemme first paste my code, most of it isn't important, just the context of it.
$("#navbar > a").click(function(event) {
$('#controls').show();
var currentNum = parseInt($(this).attr('class'), 10);
document.getElementById('pNum').innerHTML = "pg. " + (currentNum + 1);
event.preventDefault();
var t2 = ($(this).attr('id')).split("#");
var $tr = $(zip.file(localStorage.selected + "/" + t2[0]).asText());
document.getElementById('main').innerHTML = "";
$('#main').append($tr);
document.getElementById(t2[1]).scrollIntoView()
current = ($(this).attr('class'));
$(function() {
$("#main img").each(function() {
var imgPath = localStorage.selected + "/" + $(this).attr('src');
var imageData = zip.file(imgPath).asBinary();
$(this).attr('src', 'data:image/jpeg;base64,' + btoa(imageData));
});
});
$("#main a").click(function(event){
event.preventDefault();
var elems = ($(this).attr('href')).split("#");
var $path = $(zip.file(localStorage.selected + "/" + elems[0]).asText());
document.getElementById('main').innerHTML = "";
$('#main').append($path);
});
});
Now the click event at the bottom only works if I place it inside the code that creates the content, which shouldn't be the case and secondly it only works once, after I call it for the first time it refuses to work, any suggestions ?
It sounds like you want to use event delegation instead. For example:
$(document).on('click', '#main a', function(event){
event.preventDefault();
var elems = ($(this).attr('href')).split("#");
var $path = $(zip.file(localStorage.selected + "/" + elems[0]).asText());
document.getElementById('main').innerHTML = "";
$('#main').append($path);
});
The problem is that the $('#main a').click(...) approach requires that the #main a elements already be present on the page at the time that the click handler is bound.
Event delegation allows you to listen for a click event on the document (or any other element that will always be present), and see if that event originated from a #main a element. This allows you to add/remove elements on the fly without worrying about which ones have or haven't already had click handlers bound.
I've had this problem before, have you tried using this?:
$("<element id>").on( 'click', this, function ()
{
// Your code here
}
reference: http://api.jquery.com/on/
edit* Sorry did not see an answer before ( better explanation in answer above ) - but I'll keep mine for reference.
Related
I have a page in php, and I'm trying to add an ?id=variable_value extension to it's url when I click on a div, but when I click it gives me an undefined url error with the extension
Here is the script:
<script language="javascript" type="text/javascript">
var Pokemon_ID = 1;
function changeUrl() {
location.href=this.href+'?id='+Pokemon_ID;return false;
}
document.getElementById( 'right-btn' ).onclick = function() {
changeUrl();
};
</script>
And the div :
<div id="right-btn" href="pokedex.php" onclick="changeUrl()">
Don't use two separate ways of attaching handlers when you only need one. Inline event handlers are essentially eval inside HTML markup - they're bad practice and result in poorly factored, hard-to-manage code. Seriously consider attaching your events with JavaScript, instead.
The problem is that when assigning the handler via onclick, the this in changeUrl is undefined, because the calling context is global. Feel free to avoid using this when it can cause confusion.
Just use addEventListener alone. Also, you'll have to use getAttribute('href') instead of .href because divs are not supposed to have href properties.
const Pokemon_ID = '5';
document.getElementById('right-btn').addEventListener('click', function(e) {
// location.href = e.target.getAttribute('href') + '?id=' + Pokemon_ID;
console.log('changing URL to ' + e.target.getAttribute('href') + '?id=' + Pokemon_ID);
});
<div id="right-btn" href="pokedex.php">text</div>
Try this instead:
location.href += '?id=' + Pokemon_ID;
Because you call changeUrl() within the onclick method you loose the context of this. This in changeUrl is not your div. Maybe you have to pass this into the method with changeUrl(this) or you just pass the href with changeUrl(this.href).
Than use:
function changeUrl(target){
location.href=target.href+'?id='+Pokemon_ID;
}
As mentioned by CertainPerformance above, you are not passing the right arguments to you function to work correctly; Using you code as a reference, you can either pass the original event to you changeUrl() function, then use the e.target to get to your 'right-btn' element.
Javascript:
var Pokemon_ID = 1;
function changeUrl(e) {
var href = e.target.getAttribute('href');
console.log(href +'?id=' + Pokemon_ID);
return false;
}
document.getElementById( 'right-btn' ).onclick = function(e) {
changeUrl(e);
};
HTML:
<div id="right-btn" href="pokedex.php">Click Me 4</div>
However, if you realy want to use this in your function to refer to the 'right-btn' element, then you can change the code to;
Javascript:
var Pokemon_ID = 1;
function changeUrl() {
var href = this.getAttribute('href');
console.log(href +'?id=' + Pokemon_ID);
return false;
}
document.getElementById( 'right-btn' ).onclick = function(e) {
changeUrl.call(e.target);
};
The changes being the call in the event handler:
changeUrl.call(e.target);, which calls you function in the 'context' of the e.target, making the this in your changeUrl() function to the element. Then you can use the this as in var href = this.getAttribute('href');
I'm cloning input fields and then when I edit the cloned input field I'm trying to put the new values into an outside div as a text string. Thanks for your help in advance!
function cloneClue(target){
clueCount++;
var myClueField = $(target).prev().find('#textClue');
var myClone = myClueField.clone().attr('id','textClue' + clueCount);
var clueName = myClone.find('.clueName');
var clueContent = myClone.find('.clueContent');
var clueRemove = myClone.find('.clueRemove');
var clueNamePreview = myClone.find('.clueNamePreview');
var clueContentPreview = myClone.find('.clueContentPreview');
clueName.attr('name', "clueName" + clueCount);
clueName.attr('id', "clueName" + clueCount);
clueContent.attr('name', "clueContent" + clueCount);
clueContent.attr('id', "clueContent" + clueCount);
clueRemove.attr('id', "clueRemove" + clueCount)
clueNamePreview.attr('id', "clueNamePreview" + clueCount);
clueContentPreview.attr('id', "clueContentPreview" + clueCount);
clueRemove.click(function() {
$(this).parent().remove();
});
$('#clueField').append(myClone);
myClone.show();
}
var clueCount = 0;
$(document).ready(function() {
$("#addTextClue").click(function(){
cloneClue(this)
});
$('.clueName').keyup(function(){
var nameVal = $(this).val();
$(this).parent().find('.clueNamePreview').html(nameVal);
});
$('.clueContent').keyup(function(){
var contentVal = $(this).val();
$(this).parent().find('.clueContentPreview').html(contentVal);
});
});
Here's the jsfiddle
You need to use the .on for any element that is dynamically added to the DOM.
Change your jQuery to:
$(document).on("keyup", ".clueName", function() {
....
}
etc...
Your problem is that you define you keyup listeners in your document.ready function. at this point your cloned elements aren't in your DOM, so there aren't any Listeners attached to your clones. Just move this part of code right after you appended your input clone like this:
http://jsfiddle.net/8yv5x7dg/2/
I am calling some jQuery plugins that attaches themselves to element on DOM ready. These plugins manipulate the DOM when certain events has occurred (click, change etc,)
$("body").find("input[type='checkbox']").checkbox();
Above works fine on DOM ready. However, if I'm loading some HTML from an AJAX call I have to use .on() to guarantee events gets bound consistently.
The question is which event I should bind the plugin to? I have tried below and it doesn't seem to respond.
$("body").on("load", "input[type='checkbox']", function(){
$(this).checkbox();
});
Here's the checkbox() plugin I'm referring to above. If that's any help. :)
'use strict';
define(['jquery'], function($){
return function(){
$.fn.checkbox = function (options) {
options = options || {};
var defaults = {
'className': 'jquery-checkbox',
'checkedClass': 'jquery-checkbox-on'
};
var settings = jQuery.extend(defaults, options);
return this.each(function () {
var self = jQuery(this);
var replacement = jQuery(
'<span class="' + settings.className + '-wrapper">' +
'<a class="' + settings.className + '" href="#" name="' + self.attr('id') + '"></a>' +
'</span>');
var element = jQuery('a', replacement);
if (self.prop('checked')) {
element.addClass(settings.checkedClass);
}
element.on('click', function (event) {
event.preventDefault();
event.stopPropagation();
var input = jQuery('input#' + jQuery(this).attr('name'), replacement.parent());
if (input.prop('checked')) {
input.removeAttr('checked');
} else {
input.prop('checked', true);
}
input.trigger('change');
return false;
});
element.on('focusin', function (event) {
$(this).addClass('checkbox-focus');
});
element.on('focusout', function (event) {
$(this).removeClass('checkbox-focus');
});
element.on("keypress", function(e){
if ( e.which === 32 ){ self.prop('checked', !self.prop('checked')).change(); }
});
self.on('change', function (event) {
var input = jQuery(this);
if (input.prop('checked')) {
jQuery('a[name=' + input.attr('id') + ']', replacement.parent()).addClass(settings.checkedClass);
} else {
jQuery('a[name=' + input.attr('id') + ']', replacement.parent()).removeClass(settings.checkedClass);
}
return true;
});
self.css({
'position': 'absolute',
'top': '-200px',
'left': '-10000px'
}).before(replacement);
});
}
};
});
You appear to want to apply add-ins to elements that have been loaded dynamically. That is not what 'on' is for.
Delegated events listen for specific events (like "click") at a parent/ancestor element then filter the possible recipients, then executes the supplied function against any matching elements that caused the event.
You actually need to apply the add-in code after your Ajax load completes.
Example:
In the success part of your ajax load, apply the addin:
$("input[type='checkbox']").checkbox();
If you loaded a specific part of the screen (likely), then target the selector at that element:
e.g.
$("#myloadcontainer input[type='checkbox']").checkbox();
Not sure how to formulate this but here it goes.
I am checking if a var exists (content), if it doesnt i set it.
Problem is next click, it still behaves as if there is no var content. But why??
Here my code:
$("#nav a").click(function(event) {
event.preventDefault();
var href = $(this).attr("href");
var load = href + " .content";
if (!content)
{
var content = $('<div>').load(load);
$(".content").append(content);
}
else
{
var position = content.offset();
$(document).scrollTop(position);
}
});
It never results to else, so always a click is made the whole load and append function repeats.
Basically how can I record that content for this particular link has been loaded once, so the else function should be performed next time?
Also, what is wrong with my if(!content) statement? Is it because of scope?
In Javascript functions determine the scope of an object. You need to place content in the global scope. Currently it is created within the anonymous function assigned to the click event handler, so when the function is executed again content is out of scope causing it to return false.
var content;
$("#nav a").click(function(event) {
event.preventDefault();
var href = $(this).attr("href");
var load = href + " .content";
if (!content)
{
content = $('<div>').load(load);
$(".content").append(content);
}
else
{
var position = content.offset();
$(document).scrollTop(position);
}
});
Try to make the var content as a global variable rather than a local one, like you are doing right now. That's why the if (!content) result as true always, like:
var content;
$("#nav a").click(function (event) {
event.preventDefault();
var href = $(this).attr("href");
var load = href + " .content";
if (!content) {
content = $('<div>').load(load);
$(".content").append(content);
} else {
$(document).scrollTop(content.offset());
}
});
Just to show what happens, when value of content is not set at first and then set again:
var content;
console.log(content); // undefined
console.log(!content); // true
content = 'text';
console.log(content); // text
console.log(!content); // false
Thanks to everyone for answering the first question about the checking if var exists.
I ended up ditching this whole concept it turned out the
one()
function is what I needed all along. In order to only execute a function once and another function on all following clicks.
Here it is:
$(document).ready(function() {
//Ajaxify Navi
$("#nav a").one("click", function(event) {
event.preventDefault();
var href = $(this).attr("href");
var load = href + " .content";
var content = $('<div>').load(load);
$(".content").append(content);
$(this).click(function(event) {
event.preventDefault();
var position = content.offset().top;
$(document).scrollTop(position);
$("body").append(position);
});
});
});
What this is is the following:
1st click on a button loads content via ajax and appends it, second click on the same button only scrolls to said content.
I have a modal box in jQuery which I have created to display some embed code. I want the script to take the id of the link that is clicked but I can't seem to get this working.
Does anyone know how I can do that or why this may be happening?
My jQuery code is:
function generateCode() {
var answerid = $('.openembed').attr('id');
if($('#embed input[name="comments"]:checked').length > 0 == true) {
var comments = "&comments=1";
} else {
var comments = "";
}
$("#embedcode").html('<code><iframe src="embed.php?answerid=' + answerid + comments + '" width="550" height="' + $('#embed input[name="size"]').val() + '" frameborder="0"></iframe></code>');
}
$(document).ready(function () {
$('.openembed').click(function () {
generateCode();
var answerid = $('.openembed').attr('id');
$('#box').show();
return false;
});
$('#embed').click(function (e) {
e.stopPropagation()
});
$(document).click(function () {
$('#box').hide()
});
});
My mark-up is:
Embed
Embed
Your problem is here:
$('.openembed')
returns an array of matched elements. Your should instead select only the clicked element.
$('.openembed') works correctly if you assing a click event to all elements that have this class. But on the other hand, you're unable do know which is clicked.
But fortunately in the body of handler function click you could call $(this).
$(this) will return the current (and clicked element).
// var answerid = $('.openembed').attr('id'); // Wrong
var answerid = $(this).attr('id'); // Correct
// Now you can call generateCode
generateCode(answerid);
Another error is the body of generateCode function. Here you should pass the id of selected element. This is the correct implementation.
function generateCode(answerid) {
if($('#embed input[name="comments"]:checked').length > 0 == true) {
var comments = "&comments=1";
} else {
var comments = "";
}
$("#embedcode").html('<iframe src="embed.php?answerid=' + answerid + comments + '" width="550" height="' + $('#embed input[name="size"]').val() + '"frameborder="0"></iframe>');
}
Here I have implemented your code with the correct behavior: http://jsfiddle.net/pSZZF/2/
Instead of referencing the class, which will grab all members of that class, you need to reference $(this) so you can get that unique link when it is clicked.
var answerid = $(this).prop('id');
$('.openembed').click(function () {
generateCode();
var answerid = $(this).attr('id');
$('#box').show();
return false;
});
Use $(this). $('.openembed') refers to multiple links.
var answerid = $('.openembed').attr('id');
needs to be
var answerid = $(this).prop('id');
The other answers are trying to fix the click() function, but your issue is actually with the generateCode function.
You need to pass the clicked element to the generateCode function:
$('.openembed').click(function () {
generateCode(this);
And modify generateCode:
function generateCode(element) {
var answerid = element.id;
Of course var answerid = $('.openembed').attr('id'); within the click code isn't correct either, but it doesn't seem to do anything anyway.
Get the id when the correct anchor is clicked and pass it into your generateCode function
$('.openembed').click(function () {
var answerid = $(this).attr('id');
generateCode(answerid)
$('#box').show();
return false;
});
Change your function
function generateCode(answerid) {
// dont need this line anymore
// var answerid = $('.openembed').attr('id');