I'm building a javascript widget which updates a div with html from an external domain. It also intercepts any link clicks in this div and fetches fresh data, updating the div.
Issue I'm having is that when the link callback function runs after a click the JS script is re-run in it's entirety from init().
In trying to debug it, in handleClick() if I hard-code the url the script runs once as expected e.g. url: '/page-3/', but if I access the href from the clicked link e.g. url: jQuery.attr('href') the script re-runs. Is there any way of accessing this attribute without the script starting anew?
"use strict";
(function () {
var jQuery; //noconflict reference to jquery
var serverFQDN = 'http://127.0.0.1:8000';
var container = '#my-container';
function init() {
if (window.jQuery === undefined || window.jQuery.fn.jquery !== '3.4.1') {
...
}
function scriptLoadHandler() {
// Restore $ and window.jQuery to their previous values and store the
// new jQuery in our local jQuery variable
jQuery = window.jQuery.noConflict();
console.log('jQuery is now loaded');
main();
}
function main() {
jQuery(document).ready(function () {
jQuery('head').append('<link href="' + serverFQDN + '/static/css/cleanslate.css" rel="stylesheet" type="text/css">');
jQuery('head').append('<link href="' + serverFQDN + '/widget.css" rel="stylesheet" type="text/css">');
jQuery(container).addClass('cleanslate');
// build the initial widget
jQuery.ajax({
method: "GET",
cache: false,
url: "/page-1/",
success: function (response) {
jQuery(container).html(response);
// handle clicks
jQuery(container + ' a').click(handleClick);
}
});
});
}
function handleClick() {
console.log('Intercepted link click');
jQuery.ajax({
method: "GET",
cache: false,
url: jQuery.attr('href'),
success: function (response) {
console.log('succesfully loaded external html');
jQuery(container).html(response);
jQuery(container + ' a').click(handleClick);
}
});
// disable default click action
return false;
}
init();
})();
To access the href attribute you can use the event argument, provided by the Jquery click callback:
function handleClick(event) {
//you probably want this
event.preventDefault();
console.log('Intercepted link click');
jQuery.ajax({
method: "GET",
cache: false,
url: jQuery(event.target).attr('href'),
success: function (response) {
console.log('succesfully loaded external html');
jQuery(container).html(response);
jQuery(container + ' a').click(handleClick);
}
});
// disable default click action
return false;
}
Related
I am working on a random quote app. Quote is display when click a new quote button but I want quote already display when page loads. I invoked a function but it still does not work. Thank you!
Here is my code:
$(document).ready(function() {
function randomQuote() {
$('#get-quote').on('click', function(e){
e.preventDefault();
// Using jQuery
$.ajax( {
url: "http://quotes.stormconsultancy.co.uk/random.json",
dataType: "jsonp",
type: 'GET',
success: function(json) {
// do something with data
console.log(json);
data = json[0];
$('#quotation').html('"'+json.quote+'"');
$('#author').html('-- '+json.author+' --');
$('a.twitter-share-button').attr('data-text',json.quote);
},
});
});
$('#share-quote').on('click', function() {
var tweetQuote=$('#quotation').html();
var tweetAuthor=$('#author').html();
var url='https://twitter.com/intent/tweet?text=' + encodeURIComponent(tweetQuote+"\n"+tweetAuthor);
window.open(url)
});
}
randomQuote();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Try removing click listener. inside randomeQuote() remove click listener.
keep your click listener out side of document.ready
$(document).ready(function() {
randomQuote(); // call initially and get random quote
});
function randomQuote() {
$.ajax( {
url: "https://quotes.stormconsultancy.co.uk/random.json",
dataType: "jsonp",
type: 'GET',
success: function(json) {
// do something with data
data = json[0];
$('#quotation').html('"'+json.quote+'"');
$('#author').html('-- '+json.author+' --');
$('a.twitter-share-button').attr('data-text',json.quote);
},
});
$('#share-quote').on('click', function() {
var tweetQuote=$('#quotation').html();
var tweetAuthor=$('#author').html();
var url='https://twitter.com/intent/tweet?text=' + encodeURIComponent(tweetQuote+"\n"+tweetAuthor);
window.open(url)
});
}
$('#get-quote').on('click', function(e){
e.preventDefault();
randomQuote();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="get-quote">get quote</button>
<div id="quotation"></div>
Remove the onClick listeners so that when you call the function it will update directly.
function randomQuote() {
$.ajax( {
...
success: function(json) {
... //do updates
},
});
}
When using $.getScrtip it does not cache your dynamically loaded js, so i have this custom one.
jQuery.loadScript = function (url, callback) {
var load = true;
//check all existing script tags in the page for the url
jQuery('script[type="text/javascript"]')
.each(function () {
return load = (url != $(this).attr('src'));
});
console.log('load is ' + load);
if (load) {
//didn't find it in the page, so load it
jQuery.ajax({
type: 'GET',
url: url,
dataType: 'script',
cache: true,
ifModified: true,
success: callback
});
} else {
//already loaded so just call the callback
if (jQuery.isFunction(callback)) {
callback.call(this);
};
};
};
it works on caching part, however it does not work when i am refreshing the page using f5 and 304 is received on next attempt to dynamically load js. i get function undefined for a function defined inside the loaded js. here is how i call this (this same code perfectly with $.getScript if replaced $.loadScript)
function getvm() {
return $.getScript("Scripts/ViewModel/cachedvm-1.0.0.js")
}
function functionthatinvokesjsload() {
$.when($.get(myUrl), getvm())
.done(function(a1, a2) {
initializeVm();
});
}
Error i am getting is initializeVm() is not defined when i get 304 on js load. it works the first time. but if i later manually do it in browser debug window it does find that function. it seems to be i am trying to invoke the js before its loaded to DOM but not sure why that is happening.
i had to use
jQuery.loadScriptNoCallBack = function (url) {
return $.ajax({
type: 'GET',
url: url,
dataType: 'script',
cache: true,
ifModified: true
});
};
Simple ajax query, but being triggered for every item of a class using the .click() event. When it gets to the .done() I cannot figure out how to look up the element which was clicked so I can properly remove the m_action class.
Below is the code. I'm sure I'm missing something simple, but I've been searching with Chrome and Firefox web tools without luck, and can't find a duplicate question here on Stack.
In short: using the code below, how do I properly remove the m_action class of the clicked element on a successful jQuery ajax return?
<script type="text/javascript">
jQuery("div#normal .m_action").click(function() {
jQuery.ajax({
url: "./action.php",
type: "POST",
data: { action: this.id }
}).done(function(result) {
jQuery(this).removeClass("m_action");
jQuery(this).html(result);
}).fail(function(result) {
alert("There was an error.")
});
})
</script>
You can just store a reference to it so that it is available anywhere in that scope:
jQuery("div#normal .m_action").click(function() {
var elem = this; // <-- right here
jQuery.ajax({
url: "./action.php",
type: "POST",
data: { action: this.id }
}).done(function(result) {
jQuery(elem).removeClass("m_action"); // <-- elem is still available
jQuery(elem).html(result); // <--
}).fail(function(result) {
alert("There was an error.")
});
});
Just a note for the future, your problem doesn't have to do with jQuery. This is just a simple use of variables within a scope. The this pointer changes within the done function, so you just needed to cache the reference.
This code should work:
$(document).ready(function()
{
jQuery(".m_action").click(function() {
var self = $(this);
jQuery.ajax({
url: "./action.php",
type: "POST",
data: { action: this.id }
}).done(function(result) {
self.removeClass("m_action");
self.html(result);
}).fail(function(result) {
alert("There was an error.")
});
})
});
</script>
I have an ajax function that creates a link that triggers another ajax function. For some reason the second ajax function refuses to go through POST event if I've set type: "POST"
The two functionas are below:
function HandleActivateLink(source) {
var url = source.attr('href');
window.alert(url)
$.ajax({
type: "POST",
url: url,
success: function (server_response) {
window.alert("well done")
}
});
return false;
}
function HandleDeleteLink() {
$('a.delete-link').click(function () {
var url = $(this).attr('href');
var the_link = $(this)
$.ajax({
type: "POST", // GET or POST
url: url, // the file to call
success: function (server_response) {
if (server_response.object_deleted) {
FlashMessage('#form-success', 'Link Deleted <a class="activate-link" href="' + url.replace('delete', 'activate') + '">Undo</a>');
$('a.activate-link').click(function(){
HandleActivateLink($(this));
});
the_link.parent().hide();
} else {
var form_errors = server_response.errors;
alert(form_errors)
}
}
});
return false;
});
}
You'll notice HandleDeleteLink creates a new link on success, and generates a new click event for the created link. It all works butHandleActivateLink sends the request to the server as GET. I've tried using $.post instead with no luck.
Any pointers, much appreciated.
In the second event you do not inform the client to prevent the default behaviour.
One way to do this would be to change:
$('a.activate-link').click(function(){
HandleActivateLink($(this));
});
to:
$('a.activate-link').click(function(){
return HandleActivateLink($(this));
});
(This works because HandleActiveLink already returns false.)
A nicer way to do this is to pass in the event argument to the click function and tell it to preventDefault
$('a.activate-link').click(function(e){
e.preventDefault();
HandleActivateLink($(this));
});
what is your url?
btw You can't send a cross-domain post via javascript.
im trying to turn this jquery script into a toggle event type, thier is my script, with illustrations, to show what i want to happen. i cnt seem to intrgate it so here goes:
//myElement.toggle(vote(), unvote()); // this is the toggle event
$(document).ready(function() {
$('.statuses').delegate('.vote_up', 'click', function(e) {
//stop event
e.preventDefault();
//get the id
var the_id = $(this).closest('.message').attr('id').split('_').pop();
//function vote () // this should be the vote up function
//the main ajax request
$.ajax({
context: this,
type: "POST",
// Make sure "this" in the callback refers to the element clicked
data: "action=vote_up&id=" + the_id,
url: "ajax/votes.php",
success: function (msg) {
$(this).siblings("span.vote_count").html(msg).fadeIn();
// get the child <img> and set its src
$(this).children("img").attr("src", "img/uparrowActive.png");
}
});
//function unvote() thier should be another function here to unvote toggle
$.ajax({
context: this,
type: "POST",
// Make sure "this" in the callback refers to the element clicked
data: "action=vote_down&id=" + the_id,
url: "ajax/votes.php",
success: function (msg) {
$(this).siblings("span.vote_count").html(msg).fadeIn();
// get the child <img> and set its src
$(this).children("img").attr("src", "img/uparrow.png");
}
});
});
i just dont know how to integrate this toggle event into this jquery snippet, someone please help me ive been trying for years :)) thanks
Doing so:
$('.statuses').delegate('.vote_up, .vote_down', 'click', function(e) {
if($(this).hasClass('.vote_up') {
src = "img/uparrowActive.png";
action = "vote_up";
}
else {
src = "img/uparrow.png";
action = "vote_down";
}
$.ajax({
context: this,
type: "POST",
// Make sure "this" in the callback refers to the element clicked
data: "action=" + action + "&id=" + the_id,
url: "ajax/votes.php",
success: function (msg) {
$(this).siblings("span.vote_count").html(msg).fadeIn();
// get the child <img> and set its src
$(this).children("img").attr("src", src);
}
});
});
$('.statuses').delegate('.vote_up, .vote_down', 'click', function(e) {
var parent = $(this).closest('.statuses'),
vote = (($(this).hasClass("vote_up")) ? "up" : "down");
if(parent.data("vote") == vote) {
return true; // If already voted up, do nothing, if already voted down, do nothing...
}
if(vote == "down") { // Vote down
src = "img/uparrow.png";
action = "vote_down";
}
else if(vote == "up") { // Vote up
src = "img/uparrowActive.png";
action = "vote_up";
}
// Setting current vote (up or down)
// So next time you toggle, we have the trace of the previous vote (up/down)
// And authorise only do the opposite
parent.data("vote", vote);
$.ajax({
context: this,
type: "POST",
// Make sure "this" in the callback refers to the element clicked
data: "action=" + action + "&id=" + the_id,
url: "ajax/votes.php",
success: function (msg) {
$(this).siblings("span.vote_count").html(msg).fadeIn();
// get the child <img> and set its src
$(this).children("img").attr("src", src);
}
});
});