I have the following code that I use with Yii framework to delete one register.
This code is automatic generated and I'd like to capture if it was submited when the dialog open. If the ajax is complete I'll save in my user log.
jQuery(function($) {
jQuery('body').on('click','#yt0', function(){
if (confirm('Want to delete it?')) {
jQuery.yii.submitForm(this,'/yiiProject/index.php?r=project/delete&id=168',{});
return false;
}
else
return false;
});
jQuery('body').tooltip({'selector':'a[rel=tooltip]'});
jQuery('body').popover({'selector':'a[rel=popover]'});
});
Most you can do as far as I can see is override the confirm method and handle the case when user click OK:
var originalConfirm = window.confirm;
window.confirm = function(msg) {
if (originalConfirm(msg)) {
//log...
return true;
}
return false;
};
You can also override Yii auto generated code completely by sumbitting the AJAX yourself then always returning false:
if (originalConfirm(msg)) {
$.post("/yiiProject/index.php?r=project/delete&id=168", function() {
//success, write to log...
});
return false;
}
Try to use the global ajax events:
http://api.jquery.com/ajaxSuccess/
$( document ).ajaxSuccess(function( event, xhr, settings ) {
if ( settings.url == "ajax/test.html" ) {
$( ".log" ).text( "Triggered ajaxSuccess handler. The ajax response was: " +
xhr.responseText );
}
});
Related
I have a js file (using jQuery) that am making ajax request. The thing is that i want to redirect to 'login' whenever the error.status == 401 (Unauthorized), but i dont want to do this everywhere there is an ajax call.
error: function(e){
if(e.status == 401){
notice(e.responseText+' Please Login.', 'error');
}
}
Define a new function that does what you want and call it inside the error callback:
var errorFunction = function(responsetext) {
notice(responsetext +' Please Login.', 'error');
}
then:
error: function(e){
if(e.status == 401){
errorFunction(e.responseText);
}
}
You can use global ajaxError() and define conditions within it based on settings like url or special properties you can assign to any xhr object within specific requests in beforeSend callback
Example modified from ajaxerror() docs
$( document ).ajaxError(function( event, jqxhr, settings, thrownError ) {
if ( settings.url == "ajax/missing.html" ) {
$( "div.log" ).text( "Triggered ajaxError handler." );
// do a redirect
window.location = '/path/to/login';
}
});
I'm working on a magento site which uses ajax layered navigation. When the user clicks on a color link in the layered nav it loads a list of the relevent products. I want to fire a click event after the ajax has completed.
I thought I could use the jQuery when() function for this but I can't get it working.
jQuery( "a#red-hoi-swatch" ).click(function() {
jQuery.when( jQuery.ajax() ).then(function() {
jQuery("a[name*='chili-ireye']").click();
});
});
Basically, I want to run jQuery("a[name*='chili-ireye']").click(); after the ajax has finished when a user clicks the a#red-hoi-swatch.
UPDATE
I found the ajax responsible for this, it's from the Magento Blacknwhite theme we bought
/*DONOT EDIT THIS CODE*/
function sliderAjax(url) {
if (!active) {
active = true;
jQuery(function($) {
oldUrl = url;
$('#resultLoading .bg').height('100%');
$('#resultLoading').fadeIn(300);
try {
$('body').css('cursor', 'wait');
$.ajax({
url: url,
dataType: 'json',
type: 'post',
data: data,
success: function(data) {
callback();
if (data.viewpanel) {
if ($('.block-layered-nav')) {
$('.block-layered-nav').after('<div class="ajax-replace" />').remove();
$('.ajax-replace').after(data.viewpanel).remove();
}
}
if (data.productlist) {
$('.category-products').after('<div class="ajax-category-replace" />').remove();
$('.ajax-category-replace').after(data.productlist).remove();
}
var hist = url.split('?');
if(window.history && window.history.pushState){
window.history.pushState('GET', data.title, url);
}
$('body').find('.toolbar select').removeAttr('onchange');
$('#resultLoading .bg').height('100%');
$('#resultLoading').fadeOut(300);
$('body').css('cursor', 'default');
ajaxtoolbar.onReady();
jQuery('.block-layered-nav a').off('click.vs');
try{
ConfigurableSwatchesList.init();
}catch(err){}
}
})
} catch (e) {}
});
active = false
}
return false
}
function callback(){
}
I was able to achieve this with the ajaxComplete() function:
jQuery( "a#red-hoi-swatch" ).click(function() {
jQuery(document).ajaxComplete(function(){
jQuery("a[name*='chili-ireye']").click();
});
});
Not done jQuery for a while but do you really need the .when()?
Can you not just do
jQuery( "a#red-hoi-swatch" ).click(function() {
var url = 'http://my/api/url';
jQuery.ajax(url).then(function() {
jQuery("a[name*='chili-ireye']").click();
});
});
You can make any of the following 3
calling your click event on the success of your ajax call
you can make the asynch property of your ajax call to false;
callback the click event on success of your ajax call.
You can use handlers just after ajax queries or you can define a success callback for the ajax query.
From the jQuery API:
// Assign handlers immediately after making the request,
// and remember the jqXHR object for this request
var jqxhr = $.ajax( "example.php" )
.done(function() {
alert( "success" );
})
.fail(function() {
alert( "error" );
})
.always(function() {
alert( "complete" );
});
// Perform other work here ...
// Set another completion function for the request above
jqxhr.always(function() {
alert( "second complete" );
});
I'm having issues figuring out how to handle error on my page using .load() function, i already used the call back function for transitioning and i don't know how or to place the error code and make it work correctly....
i av this code.....
$('.menuLink:eq(0)').click(function(event) {
event.preventDefault();
setTimeout($('#navigation ul li').removeClass('expand', 'normal'), 1000);
$('section').hide().load('index.html section', function() {
$(this).fadeIn('slow');
});
});
I'll like to load any error that may occur in the section tag...
If you are using load() you can do the error checking in the same callback function. For example, as given in the JQuery documentation:
Display a notice if the Ajax request encounters an error.
<script>
$( "#success" ).load( "/not-here.php", function( response, status, xhr ) {
if ( status == "error" ) {
var msg = "Sorry but there was an error: ";
$( "#error" ).html( msg + xhr.status + " " + xhr.statusText );
}
});
</script>
In that callback function, first check for errors. Then, if there are no errors, do the fadeIn.
$('.menuLink:eq(0)').click(function(event) {
event.preventDefault();
setTimeout($('#navigation ul li').removeClass('expand', 'normal'), 1000);
$('section').hide().load('index.html section', function() {
// Check for errors here
$(this).fadeIn('slow');
});
});
I want to try to override window.confirm function with modal dialog.
<a href="http://example.com" onClick="return confirm('you want to go?')">
<script>
window.confirm = function(message){
$("#confirm-dialog").modal('show');
$("#confirm-dialog .modal-body p").html(message);
$("#confirmYes").on("click", function () {
return true;
});
}
</script>
When I click in modal window on the #confirmYes element it returns true, but the redirect by href link will not work...Why?
Can somebody tell me how I can do this thing without changing my link?
Thanks
UPD
Yii framework generates that code for CGridView widget and i want to override it. I can't change this code, because its in framework. Instead this confirm standard i want to use my modal window
$(document).on('click','#product-grid a.delete',function() {
if(!confirm('Are you sure you want to delete this item?')) return false;
var th=this;
var afterDelete=function(){};
$.fn.yiiGridView.update('product-grid', {
type:'POST',
url:$(this).attr('href'),
success:function(data) {
$.fn.yiiGridView.update('product-grid');
afterDelete(th,true,data);
},
error:function(XHR) {
return afterDelete(th,false,XHR);
}
});
return false;
});
Here is a practice that we used in my company in a UI conversion project.
It is ugly though, but it works just fine.
var clickState={};
var justClicked=null;
window.confirm = function(message) {
var e = window.event || window.confirm.caller.arguments[0];
var el = e.target || e.srcElement; // the element's click that triggers confirm dialog
if(justClicked && clickState[justClicked]===true){
clickState[justClicked]=false;
return true;
}else{
// your async style confirmation dialog (e.g. jQuery's dialog)
showConfirmBox(message, function() {
justClicked=el;
clickState[el]=true;
$(justClicked).click(); // in the call back function , click the target again.
});
}
return false;
};
Js default confirm dialog work synchronously, it means that code will wait for the user to make his choice to continue. When you override confirm dialog this way what happens is that your new stylish confirm dialog is shown but method end immediately and returns undefined.
You can work with callbacks;
<a href="http://example.com" onClick="confirm('you want to go?', function(result){
if(result)
//code to redirect, like window.location(this.href);
}); return false;">
then:
<script>
window.confirm = function(message, cb){
$("#confirm-dialog").modal('show');
$("#confirm-dialog .modal-body p").html(message);
$("#confirmYes").on("click", function (userChoice) {
cb(userChoice); //true or false - your jquery plugin will supply this value
});
}
</script>
EDIT: Its important to keep the link url on href (instead of just leaving "/#") for SEO reasons - for the link not be triggered you should also return false after calling your new confirm dialog.
If you need Overriding the window.alert() dialog box you can find it here
after that I have create my own Overriding the window.confirm() dialog box you can find it here
Overriding the window.confirm() dialog box.
It is pretty simple just like:
window.confirm = function(message, title, doYes) {
$(document.createElement('div'))
.attr({title: title, class: 'confirm'})
.html(message)
.dialog({
buttons: {
"Confirm": function() {
$(this).dialog("close");
if (doYes && (typeof doYes === "function")) {
doYes();
}
},
"Cancel": function() {
$(this).dialog("close");
}
}
,
close: function() {
$(this).remove();
},
draggable: true,
modal: true,
resizable: false,
width: 'auto'
});
};
// New confirm
//confirm('This is a <strong>new</strong> alert!','Confirm', function(){alert('Yes')},function(){alert('No')});
I know it is an old post but I want to share my solution, I know this changes the yii default behaviour but I replaced their function for one custom working the same way, I am gonna ask yii gurus about a better way or if in the future this can be done easily.
In framework/yii/zii/widgets/grid/CButtonColumn.php modify the initDefaultButtons:
/**
* Initializes the default buttons (view, update and delete).
*/
protected function initDefaultButtons()
{
if($this->viewButtonLabel===null)
$this->viewButtonLabel=Yii::t('zii','View');
if($this->updateButtonLabel===null)
$this->updateButtonLabel=Yii::t('zii','Update');
if($this->deleteButtonLabel===null)
$this->deleteButtonLabel=Yii::t('zii','Delete');
if($this->viewButtonImageUrl===null)
$this->viewButtonImageUrl=$this->grid->baseScriptUrl.'/view.png';
if($this->updateButtonImageUrl===null)
$this->updateButtonImageUrl=$this->grid->baseScriptUrl.'/update.png';
if($this->deleteButtonImageUrl===null)
$this->deleteButtonImageUrl=$this->grid->baseScriptUrl.'/delete.png';
if($this->deleteConfirmation===null)
$this->deleteConfirmation=Yii::t('zii','Are you sure you want to delete this item?');
foreach(array('view','update','delete') as $id)
{
$button=array(
'label'=>$this->{$id.'ButtonLabel'},
'url'=>$this->{$id.'ButtonUrl'},
'imageUrl'=>$this->{$id.'ButtonImageUrl'},
'options'=>$this->{$id.'ButtonOptions'},
);
if(isset($this->buttons[$id]))
$this->buttons[$id]=array_merge($button,$this->buttons[$id]);
else
$this->buttons[$id]=$button;
}
if(!isset($this->buttons['delete']['click']))
{
if(is_string($this->deleteConfirmation))
$confirmation="if(!confirm(".CJavaScript::encode($this->deleteConfirmation).")) return false;";
else
$confirmation='';
if(Yii::app()->request->enableCsrfValidation)
{
$csrfTokenName = Yii::app()->request->csrfTokenName;
$csrfToken = Yii::app()->request->csrfToken;
$csrf = "\n\t\tdata:{ '$csrfTokenName':'$csrfToken' },";
}
else
$csrf = '';
if($this->afterDelete===null)
$this->afterDelete='function(){}';
$withConfirmation = strlen($confirmation) == 0 ? 0 : 1;
$confirmationMessage = CJavaScript::encode($this->deleteConfirmation);
$this->buttons['delete']['click']=<<<EOD
`function(event) {
event.preventDefault();
if ($withConfirmation){
var th=this;
var afterDelete=$this->afterDelete;
var deleteUrl=$(this).attr('href');
console.log(deleteUrl);
$(document.createElement('div')).attr({
title:'AtenciĆ³n',
'class': 'dialog'
}).html($confirmationMessage).dialog({
buttons: {
"OK": function () {
$(this).dialog('close');
$.fn.yiiGridView.update('{$this->grid->id}', {
type:'POST',
url:deleteUrl,$csrf
success:function(data) {
$.fn.yiiGridView.update('{$this->grid->id}');
afterDelete(th,true,data);
},
error:function(XHR) {
return afterDelete(th,false,XHR);
}
});
return true;
},
"Cancel": function () {
$(this).dialog('close');
return false;
}
},
close: function () {
$(this).remove();
},
draggable: false,
modal: true,
resizable: false,
width: 'auto'
}).position({
my: "center",
at: "center",
of: window
});
}
}
EOD;
}
}
`
EDIT:
I also learned how to do it without modify core yii:
In you widget grid you a file for the buttons like this:
array
(
'class'=>'CButtonColumn',
'deleteConfirmation'=>'Atencion',
'buttons'=>array
(
'update'=>array
(
'imageUrl'=>FALSE,
'label'=>'update',
'options'=>array('title'=>'update'),
'visible'=>'$row > 0'
),
'delete'=>array
(
'imageUrl'=>FALSE,
'label'=>'delete',
'options'=>array('title'=>'delete'),
'click'=>'function(){$("#mydialog").dialog("open"); return false;}',
),
),
'template'=>'{update} | {delete}'
),
Try adding a return to the onclick:
a href="http://example.com" onclick="return confirm("you want to go?")">
Goal:
Disable links before ajax:success is received. (then i'll tell my app server thing to enable the links. I'm writing a simple board game, and don't want to be recieving multiple ajax requests before the first one is responded to, because it messes with the game logic.
<script type="text/javascript">
var disableLinks = false;
$("a").click(function(e){
if (disableLinks){
e.preventDefault();
}
});
$("a").ajaxStart(function(){
disableLinks = true;
});
$("a").ajaxStop(function(){
disableLinks = false;
});
</script>
And here are what the links look like:
<a href="/board/take_turn?id=313&x=1&y=2" data-remote="true">
<div class="ttt_square">
</div>
</a>
This is because your AJAX start and finish events never fire. Why? Because simply clicking a link isn't an AJAX request, and doesn't trigger the global AJAX events. To use the global AJAX events, you need to use an AJAX function such as .get( ), .load( ), or $.ajax( )
The code below, is mostly yours... I've just added 2 lines (which could even be reduced to 1, but I think it looks better this way)
var disableLinks = true;
$('a').click( function( e )
{
if( disableLinks )
{
e.preventDefault( );
}
var self = $(this);
$.ajax( { "url": self.attr( 'href' ) } );
} );
$('a').ajaxStart( function( )
{
disableLinks = true;
} );
$('a').ajaxStop( function( )
{
disableLinks = false;
} );
You've got a typo. e.prevenDefault(); should be e.preventDefault();
And this should be enough for disabling the default action. So you can rid of your onclick.
$("a").click(function(e){
e.preventDefault();
});
Edit:
Maybe this: jQuery - How can I temporarily disable the onclick event listener after the event has been fired?
or this: jQuery - How can I temporarily disable the onclick event listener after the event has been fired?
should solve your problem (if understand you correctly)
try this:
$('a').click(function(){
if (!this.hasClass('disabled')) {
this.addClass('disabled');
var self = this;
$.ajax({url: this.attr('href'),
complete: function(jqXHR, textStatus)
self.removeClass('disabled');
}
});
}
return false;
});