I have an a element containing an href attribute. Clicking on it would delete data so I want the user to confirm that action. The href attribute refers to a php file with an id of the data that will be deleted in the GET parameter. I've added an onclick attribute, that should execute the following piece of JS (it shows a Semantic UI modal that asks for confirmation):
confirmmodal = function () {
beforeunload = function () {
$('.ui.basic.modal')
.modal({
closable: false,
onDeny: function () {
return false;
},
onApprove: function () {
return true;
}
})
.modal('show')
;
}
}
But when I run this it still goes to the page that would delete the data (although I haven't built it yet, so nothing is deleted). Would there be an option that gives the onclick attribute priority over the href attribute somehow?
You need to add event.preventDefault() at the end of your code.
Eg:
Delete
function showDialog(e) {
// custom code to show dialog here
e.preventDefault();
}
Okay, I got there with a few tweaks on the script, taking gavgrif's comment into account as well.
I made the <a> element a little different, so it won't contain an href attribute anymore:
<a title="Delete post" onclick="confirmmodal(this)" data-postid="'. $row['postnr'] .'"><i class="large delete middle aligned icon"></i></a>
Now, if the icon is clicked, the postid is available for the JS as well, so we can just refer to that in the GET parameter when the confirm button is clicked:
confirmmodal = function (a) {
$('.ui.basic.modal')
.modal({
closable: false,
onDeny: function () {
return true;
},
onApprove: function () {
window.location.href = "deletepost.php?id=" + a.dataset.postid
return true;
}
})
.modal('show')
;
}
Which is a semi-ugly fix, but it's not that many more lines, and I don't know s*** about JQuery :)
Thanks for all the help, I almost got there with preventDefault() but I couldn't continue if the action was confirmed, so this is an easier solution.
Related
I am trying to develop some code to allow the user show/hide a block level element by clicking a button.
The HTML structure is like below
<div class="chat_container"><a class="crm" href="https://google.com" target="_blank">Chat?</a><button id="close_chat"><</button></div>
I have written a click() function for #close_chat which amongst other things changes the ID of the button to #open_chat. I then use the on() method on #open_chat to modify some classes and ids on various elements. In isolation both these methods work, however when combined they don't work. I have noticed that when I click #close_chat even though the ID changes to #open_chat the original event is still attached to the button. After doing some search I suspected the issue might have been related to events bubbling up, but now I am not so sure, still I added event.stopPopagation() to my click function and I can see it appears to be called correctly. I have also tried using the one() method, this appeared to get closer to the behavior I was expecting at the DOM level but still didn't working
My expected behavior is the click() function is called when the user clicks #close_chat, the event is then unbound allowing the .on() event to be called on #open_chat. Id than of course have to reset the original functionality. My code looks like this
$(document).ready(function () {
var close = "<button id='close_chat'><</div>";
var container = $("<div />");
container.addClass("chat_container");
var crmChat = $("<a />");
crmChat.addClass("crm");
crmChat.attr("href", "https://google.com");
crmChat.attr("target", "_blank");
crmChat.text("Chat?");
console.log(crmChat);
console.log(container);
$(container).insertAfter("#heading");
$(container).prepend(crmChat);
$(close).insertAfter(crmChat);
$("#close_chat").click(function (event) {
$("#close_chat").removeAttr("id").attr("id", "open_chat");
event.stopPropagation();
alert(event.isPropagationStopped());
//return false;
});
$(".chat_container").on("#open_chat", "button", function () {
//$(".crm_chat_container").addClass("animate-open").removeClass("animate-close");
$("#open_chat").html(">").removeAttr("id").attr("id", "reopen");
//event.stopPropagation();
});
});
any help is greatly appreciated
Sam
edit, I have now updated my code to look like so
//onclick function for our close button
$("#close_chat").click(function (event) {
attachClosedChatListner();
});
function attachOpendChatListener() {
$(".chat_container").on("click","#open_chat", function () {
$("#open_chat").removeAttr("id").attr("id", "close_chat");
$("#close_chat").html("<")
$(".crm_chat_container").removeClass("animate-close").addClass("animate-open");
});
//attachClosedChatListner();
}
function attachClosedChatListner() {
$("#close_chat").off('click');
$("#close_chat").removeAttr("id").attr("id", "open_chat");
$("#open_chat").html(">")
$(".chat_container").removeClass("animate-open").addClass("animate-close");
//attachOpendChatListener();
}
What about re-attaching the event?
$("#close_chat").click(function (event) {
$("#close_chat").removeAttr("id").attr("id", "open_chat");
attachOpenChatListener();
event.stopPropagation();
alert(event.isPropagationStopped());
//return false;
});
function attachOpenChatListener() {
$("#close_chat").off('click');
$(".chat_container").on("#open_chat", "button", function () {
//$(".crm_chat_container").addClass("animate-open").removeClass("animate-close");
$("#open_chat").html(">").removeAttr("id").attr("id", "reopen");
//event.stopPropagation();
});
}
I managed to work this out, the click function was causing the problem
//onclick function for our close button
$("#close_chat").click(function (event) {
attachClosedChatListner();
});
I've replaced it with .on and it works now
$(".crm_chat_container").on("click", "#close_chat", function (event) {
$("#close_chat").off('click');
$("#close_chat").removeAttr("id").attr("id", "open_chat");
$("#open_chat").html(">");
$(".crm_chat_container").removeClass("primo-animate-open").addClass("animate- close");
attachCloseChatListener();
event.stopImmediatePropagation();
});
function attachCloseChatListener() {
$(".crm_chat_container").on("click", "#open_chat", function (event) {
$("#open_chat").off('click');
$(".crm_chat_container").removeClass("primo-animate-close").addClass("primo-animate-open");
$("#open_chat").removeAttr("id").attr("id", "close_chat");
$("#close_chat").html("<");
event.stopImmediatePropagation();
});
}
on thing is my click events appears to be firing multiple times, that is after clicking my buttons a few times I see several click events in dev tools.
Anyway, thanks for putting me on the right path
I'm trying to figure out how to change behaviour of a button using AJAX.
When the button is clicked, it means that user confirmed order recently created. AJAX calls /confirm-order/<id> and if the order has been confirmed, I want to change the button to redirect to /my-orders/ after next click on it. The problem is that it calls again the same JQuery function. I've tried already to remove class="confirm-button" attribute to avoid JQuery again but it does not work. What should I do?
It would be enough, if the button has been removed and replaced by text "Confirmed", but this.html() changes only inner html which is a text of the button.
$(document).ready(function () {
$(".confirm-button").click(function (b) {
b.preventDefault();
var $this = $(this);
var id = this.value;
var url = '/confirm-order/'+id;
$.ajax({
type: 'get',
url: url,
success: function (data) {
$this.empty();
$this.attr('href','/my-orders/');
$this.parent().attr("action", "/my-orders/");
$this.html('Confirmed');
}
})
});
});
The event handler will be still attached to the button, so this will run again:
b.preventDefault();
which will prevent the default, which is opening the href. You need to remove the event handler on success. You use the jQuery #off() method:
$(".confirm-button").off('click');
or more shortly:
$this.off('click');
You can add to your success function something like: $this.data('isConfirmed', true);
And then in your click handler start by checking for it. If it's true, redirect the user to the next page.
$(".confirm-button").click(function (b) {
b.preventDefault();
var $this = $(this);
if ($this.data('isConfirmed')) {
... redirect code ...
}
else {
... your regular code ...
}
}
You need to use .on() rather than .click() to catch events after the document is ready, because the "new" button appears later.
See http://api.jquery.com/on/
$(document).ready(function() {
$('.js-confirm').click(function(){
alert('Confirmed!');
$(this).off('click').removeClass('js-confirm').addClass('js-redirect').html('Redirect');
});
$(document).on('click', '.js-redirect', function(){
alert('Redirecting');
});
});
<button class="js-confirm">Confirm</button>
What's the best way to prevent a double-click on a link with jQuery?
I have a link that triggers an ajax call and when that ajax call returns it shows a message.
The problem is if I double-click, or click it twice before the ajax call returns, I wind up with two messages on the page when I really want just one.
I need like a disabled attribute on a button. But that doesn't work on links.
$('a').on('click', function(e){
e.preventDefault();
//do ajax call
});
You can use data- attributes, something like this:
$('a').on('click', function () {
var $this = $(this);
var alreadyClicked = $this.data('clicked');
if (alreadyClicked) {
return false;
}
$this.data('clicked', true);
$.ajax({
//some options
success: function (data) { //or complete
//stuff
$this.data('clicked', false);
}
})
});
I came with next simple jquery plugin:
(function($) {
$.fn.oneclick = function() {
$(this).one('click', function() {
$(this).click(function() { return false; });
});
};
// auto discover one-click elements
$(function() { $('[data-oneclick]').oneclick(); });
}(jQuery || Zepto));
// Then apply to selected elements
$('a.oneclick').oneclick();
Or just add custom data atribute in html:
<a data-oneclick href="/">One click</a>
You need async:false
By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false.
$.ajax({
async: false,
success: function (data) {
//your message here
}
})
you can use a dummy class for this.
$('a#anchorID').bind('click',function(){
if($(this).hasClass('alreadyClicked')){
return false;
}else{
$(this).addClass('alreadyClicked);
$/ajax({
success: function(){$('a#anchorID').removeClass('alreadyClicked');},
error: function(){$('a#anchorID').removeClass('alreadyClicked');}
});
}});
Check this example. You can disable the button via CSS attribute after the first click (and remove this attribute after an ajax request or with a setTimeout) or use the jQuery.one() function to remove the trigger after the first click (without disabling the button)
var normal_button = $('#normal'),
one_button = $('#one'),
disabled_button = $('#disabled'),
result = $('#result');
normal_button.on('click', function () {
result.removeClass('hide').append(normal_button.html()+'<br/>');
});
one_button.one('click', function () {
result.removeClass('hide').append(one_button.html()+'<br/>');
});
disabled_button.on('click', function () {
disabled_button.attr('disabled', true);
setTimeout(function () {
result.removeClass('hide').append(disabled_button.html()+'<br/>');
}, 2000);
});
Although there are some good solutions offered, the method I ended up using was to just use a <button class="link"> that I can set the disabled attribute on.
Sometimes simplest solution is best.
You can disable click event on that link second time by using Jquery
$(this).unbind('click');
See this jsfiddle for reference
Demo
You can disable your links (for instance, href="#" ), and use a click event instead, binded to the link using the jQuery one() function.
Bind all the links with class "button" and try this:
$("a.button").click(function() { $(this).attr("disabled", "disabled"); });
$(document).click(function(evt) {
if ($(evt.target).is("a[disabled]"))
return false;
});
I am trying to use a Twitter Bootstrap button group with data-toggle="buttons-radio" in my site. Bootstrap markup as follows.
<div class="btn-group program-status" data-toggle="buttons-radio">
<button class="btn">All</button>
<button class="btn">Active</button>
<button class="btn">Planning</button>
<button class="btn">End of Life</button>
<button class="btn">Cancelled</button>
</div>
I need to redirect to the same page with query depending on the pressed button. I tried to use following jQuery code to achieve this.
<script>
var sParamStr = '';
function addToParamStr(str) {
sParamStr += str;
}
function redirectToUpdatedLocation() {
$('.program-status > .btn.active').each(function () {
addToParamStr( '?status=' + $(this).text());
});
console.log(sParamStr);
window.location.href = "program" + sParamStr;
}
$document.ready(function () {
$('.program-status > .btn').on('click', function (e) {
redirectToUpdatedLocation();
});
});
</script>
But the browser always redirects to {site}/program without the query string. By commenting out window.location.href = "program" + sParamStr; line, I managed to observe that second click onwards, sParamStr getting appended properly.
It seems that, my code tries to read the text of the pressed button before, .button('toggle') method form bootstrap.js finished. Code worked as intended when I changed function as follows.
$document.ready(function () {
$( '.program-status > .btn').on('click', function (e) {
$(this).addClass('active');
redirectToUpdatedLocation();
});
});
While this method works for me right now, I would like to know the proper way to achieve this. i.e How to execute my code after previous click binding finishes?
UPDATE:
I found this link in the Twitter Bootstrap forum. Seems it is a known issue.
https://github.com/twitter/bootstrap/issues/2380
I'm not sure what Bootstrap's .toggle is doing exactly, but it seems like it does some sort of animation that completes with the setting of the active class. You can try enqueing your code instead:
$( '.program-status > .btn').on('click', function (e){
$(this).queue(function (next) {
redirectToUpdatedLocation();
next();
});
});
For example, click the div as it is being toggled: http://jsfiddle.net/9HwYy/
It also seems a bit silly to me to update every href instead of just the one you clicked on since you are changing the window location anyway.
try
$('.program-status > .btn.active').each(function(i,v){
v = $(v);
addToParamStr( '?status=' + v.text());
});
since im not sure "this" is working in your case.
I tried to use focus for first input field on the form. but
it doesn't work. When I call attr("id") for that input it worked. When I call focus for the same input, I didn't see any
result. I also tried to use native Javascript. Does anyone know how to
fix that?
You are all misunderstanding the question. When Colorbox opens you can't focus an input field?
...unless you add your focus to the Colobox onComplete key e.g.
$('#mydiv a').colorbox({ onComplete:function(){ $('form input:first').focus(); }});
You could also bind the focus to an event hook:
$('#mydiv a').bind('cbox_complete', function(){
$('form input:first').focus();
});
That should be enough to get started.
use
$(document).ready(function() {
// focus on the first text input field in the first field on the page
$("input[type='text']:first", document.forms[0]).focus();
});
It may be happening that when your colorbox is opened its focus goes onto the highest element i.e. body of page. use document.activeElement to find that focus went to which element. Then find iframe or id of your colorbox and then set focus on it
Try the first selector,
$("form input:first").focus();
http://jsfiddle.net/erick/mMuFc/
I've just stumbled on this problem.
I think it's best to have a single $.colorbox opener like this:
function showActionForColorBox(
_url,
_forFocus
) {
$.colorbox(
{
scrolling: false,
href: _url,
onComplete: function () {
idColorboxAjaxIndect1.appendTo($('#cboxOverlay'));
idColorboxAjaxIndect2.appendTo($('#cboxOverlay'));
idColorboxAjaxIndect3.appendTo($('#cboxOverlay'));
idColorboxAjaxIndect4.appendTo($('#cboxOverlay'));
// --> Possible element's ID for focus
if (_forFocus) {
$('#' + _forFocus).focus();
}
return;
},
onCleanup: function () {
// TODO: ?
return;
},
onClosed: function () {
if (shouldReloadPageAfterColorBoxAction) {
// --> Should we reload whole page?
shouldReloadPageAfterColorBoxAction = false; // NOTE: To be sure: Reset.
window.location.reload(false);
}
else if (cbEBillsActionReloadPopup) {
// --> Should we reload colorbox
cbEBillsActionReloadPopup = false;
showActionForColorBox(_url);
}
else if (cbShouldLoadAnotherContentAfterClosed) {
// --> Should we reload colorbox with custom content?
cbShouldLoadAnotherContentAfterClosed = false;
$.colorbox({ html: setupContentForcbShouldLoadAnotherContentAfterClosed });
setupContentForcbShouldLoadAnotherContentAfterClosed = '';
}
return;
}
}
);
return;
}
You can also use
$.colorbox({
...,
trapFocus: false
});
to disable focus inside colorbox