I have a big problem writing a small piece of code using JS/jQuery (don't know which of these is causing the problem). Anyhow, here we go:
$('#themePicker').unbind().click(function() {
var t = $(this);
modalwindow2(t, function() {
console.log(1);
}, function(w) {
console.log(w);
});
return false;
});
and the function itself:
function modalwindow2(w, callbackOnSHow, callbackOnHide) {
if (typeof(callbackOnSHow) == 'function') {
callbackOnSHow.call();
}
// do some stuff //
$('form').submit(function() {
ajaxSubmit(function(data) {
if (typeof(callbackOnHide) == 'function') {
console.log('---------------');
console.log(data);
console.log('---------------');
callbackOnHide.call(data);
}
});
return false
});
}
The function is called modalwindow2 and I want to call a function when the modal is shown and another function when the modal will be hidden.
The first is not a problem.
The second… Well… Let's just say it's a problem. Why?
I want a parameter sent to the second function. The paramenter is an ajax response, similar to other jQuery stuff (ajax action, sortable, etc).
I hope I made myself clear enough.
Thanks!
Edit:
I'm using jQuery 1.1.2 (or 1.1.3) and upgrading or using jQuery UI is NOT a solution. I have some dependencies (interface is one of them) and i don't have enough time (nor motivation) to upgrade to 1.3 & UI 1.7.
I noticed that you have a typo on .submit:
$('form').submti(function(){
Was that just an entry error to SO?
EDIT:
Ok, so after looking at your code and doing a short test, I've come up with this (pardon the pun):
function modalwindow2(w, callbackOnShow, callbackOnHide) {
if(typeof callbackOnShow == 'function') {
callbackOnShow.call();
}
$('form').submit(function() {
if(typeof callbackOnHide == 'function') {
callbackOnHide.call(this, "second");
}
});
}
$(document).ready(function (){
$('#themePicker').click(function(){
var t=$(this);
modalwindow2(t, function() { alert("first"); }, function(x) { alert(x); });
return false;
});
});
It looks like you may have just been missing the "this" in your call() statement. Try using callbackOnHide.call(this, data);
Let me know if that works any better!
I understand what you are trying to do, but you will need to store the newly created window so that you can access it on the close callback function.
You might want to look at jQuery UI Dialog. It provides some really basic functionality for dialog windows (modal and otherwise) and handles some of the callback implementation.
Related
I use jquery-ujs for ajax requests (data-remote="true"). My problem is, that the first request is okay, and while the second is running, it breaks. Whenever I call in the events $('#modal').empty() or $('#modal').text('') or $('#modal').html(''), no more events are going to be called.
To be clear, here's the code:
$(document).on('ajax:beforeSend', function () {
console.log('beforeSend');
$('#modal').empty().modal('show');
});
$(document).on('ajax:send', function () {
console.log('send');
});
$(document).on('ajax:success', function (e, xhr) {
console.log('success');
$('#modal').html(xhr).drags({ handle: '.modal-header' }).modal('show');
if (typeof doWork === 'function') {
doWork();
}
});
$(document).on('ajax:complete', function () {
console.log('complete');
});
And the console output:
beforeSend
send
success
complete
beforeSend
If I move $('#modal').empty().modal('show'); to the send event, then it is going to be called, but the success method is never called anymore (neither error neither complete, nothing more).
This problem annoys me for more hours now... Thank you for your help.
How about to move empty() to the ajax:complete?
In this case, when your modal closes, it opens empty for the next use and is ready for reuse.
I suggest that you put this command in the last step so that it does not cause any problems. Like the following:
$(document).on('ajax:complete', function () { console.log('complete'); . . . . $('#modal').empty(); });
I believe that this is not the best solution and there are definitely other solutions. But I hope this solution will solve your problem.
$('#modal').on('hidden.bs.modal', function () {
$(this).empty()
})
My workaround was to avoid using jquery-ujs events and using global ajax events, so my final working code is:
$(document).ajaxSend(function () {
$('#modal').empty().modal('show');
});
$(document).ajaxSuccess(function (e, xhr) {
$('#modal').html(xhr.responseText).drags({ handle: '.modal-header' }).modal('show');
if (typeof doWork === 'function') {
doWork();
}
});
This question has little to do with jQueryUI's dialog, and more to do with JavaScript.
I pass some variables to ayb.dialogError(), and use them to create a dialog. Then I pass different values, but the first are still used.
The below script is condensed to highlight the issues, and the full script is located at https://jsbin.com/muhijodima.
Within the open callback, how do I access the variables passed to ayb.dialogError()?
$(function(){
ayb={};
ayb.dialogErrorElem=undefined;
ayb.dialogError=function(t,e) {
if (typeof ayb.dialogErrorElem === 'undefined') {
ayb.dialogErrorElem=$('<div/>').appendTo('body').dialog({
open: function(event, ui){
console.log('dialog.open',t,e);
//t=function(){return t;}
//e=function(){return e;}
},
});
console.log(ayb.dialogErrorElem);
};
ayb.dialogErrorElem.dialog('open');
}
$('#e1').click(function(){ayb.dialogError('Title1',['error1-1','error1-2'])});
$('#e2').click(function(){ayb.dialogError('Title2','error2-1')});
});
At if (typeof ayb.dialogErrorElem === 'undefined') {
ayb.dialogErrorElem is not undefined at click of two button
jsbin https://jsbin.com/rugarizedo/edit?html,output
I expect this is not the best way to do so, however, the passed parameters are available to the open callback.
Condensed script below to highlight concept, and full script at https://jsbin.com/segoxewape/edit?html,output.
If there is a better way to make the parameters available in the callback (which I am sure there is), please comment.
ayb.dialogError=function(t,e) {
getEm=function(){return {e:e,t:t};}
var v={e:e,t:t}; //Won't work
if (typeof this.dialog === 'undefined') {
this.dialog=$('<div/>', {})
.dialog({
open: function(event, ui){
console.log('Wrong values in dialog.open!',t,e,v.t,v.e);
var o=getEm();
console.log('Right values!',o);
}
});
};
this.dialog.dialog('open');
}
I seem to have problem with jQuery bind() and unbind() functions. They seem to not get executed at all. Here's the code I have so far:
$(function() {
var init = function() {
$.get('test.php', function(j) {
if(j.r && j.r == 'error') {
console.log("1");
$('#far').bind('click', function() {
console.log("2"); return false;
});
} else {
//getData();
}
})
}();
var getData = function() {
$('#far').unbind('click', false);
};
$('#far').click(function() { ... });
});
Console only shows me 1 and no errors. I have no idea what I'm doing wrong since there are no errors and jQuery docs and StackOverflow has given me the same answer. I'm using jQuery 1.4.4
What am I doing wrong?
By calling your getData() function at the end of the $.get() function you are unbinding the event as soon as you bind it. Try commenting out the getData() call in the $.get() function and see if that helps.
As I see you're binding event before it's created, so use live instead.
I'm creating a plugin that replaces alerts/confirms for a project and I was curious if there was a way to make it like a real confirm where you can do:
if(confirm('Yes or no?')){alert('You agreed!');}
Right now I could do with a call back using this syntax:
$.alert('yes or no',{type:'confirm'});
But i want to be able to do:
if($.alert('yes or no',{type:'confirm'})){/*some action on true*/}
Here is what I have so far and look for the all CAPS comments in the click event (remember, this is still in development, so the HTML and stuff is still a little icky):
(function($) {
$.alert = function(message,options) {
defaults = {
type:'alert',
callback:function(){}
}
options = $.extend({},defaults,options);
if(options.type == 'confirm'){
$('<div style="display:none" class="alerthiddenoverlay"></div><div style="display:none" class="customalertbox"><div><img src="http://cdn.iconfinder.net/data/icons/basicset/tick_48.png"><p>'+message+'</p><br class="clear"><span><a class="cancel" href="#cancel">Cancel</a><a class="ok" href="#ok">OK</a></span><br class="clear"></div></div>').prependTo('body');
}
else{
$('<div style="display:none" class="alerthiddenoverlay"></div><div style="display:none" class="customalertbox"><div><img src="http://cdn.iconfinder.net/data/icons/basicset/warning_48.png"><p>'+message+'</p><br class="clear"><span><a class="ok" href="#ok">OK</a></span><br class="clear"></div></div>').prependTo('body');
}
$alertboxclass=$('.customalertbox');
$alerthiddenoverlay=$('.alerthiddenoverlay');
$alertboxclass.find('a').click(function(event){
event.preventDefault();
var the_return = false;
if($(this).attr('href') == '#ok'){
var the_return = true;
}
$alertboxclass.fadeOut(250,function(){$alerthiddenoverlay.delay(250).fadeOut(250,function(){$(this).remove();options.callback.call(this,the_return);});$(this).remove()});
});
$alertboxclass.css({
top:$(window).height()/2-$alertboxclass.height()/2,
left:$(window).width()/2-$alertboxclass.width()/2
});
$alerthiddenoverlay.css({height:$(window).height()+'px',width:'100%',position:'fixed',zIndex:'9998'}).fadeIn(250,function(){$alertboxclass.delay(250).fadeIn()});
}
})(jQuery);
I think passing a callback method in as a parameter to the $.alert function is going to be the easiest option. If that's a deal-breaker though, I might look at the .queue() method for chaining the events.
http://api.jquery.com/queue/
I saw a nice confirm() overwrite to a modal window as an example of jqModal
Here is the code sample. I'm sure you can adapt it to your need...
/* Overriding Javascript's Confirm Dialog */
// NOTE; A callback must be passed. It is executed on "cotinue".
// This differs from the standard confirm() function, which returns
// only true or false!
// If the callback is a string, it will be considered a "URL", and
// followed.
// If the callback is a function, it will be executed.
function confirm(msg,callback) {
$('#confirm')
.jqmShow()
.find('p.jqmConfirmMsg')
.html(msg)
.end()
.find(':submit:visible')
.click(function(){
if(this.value == 'yes')
(typeof callback == 'string') ?
window.location.href = callback :
callback();
$('#confirm').jqmHide();
});
}
$().ready(function() {
$('#confirm').jqm({overlay: 88, modal: true, trigger: false});
// trigger a confirm whenever links of class alert are pressed.
$('a.confirm').click(function() {
confirm('About to visit: '+this.href+' !',this.href);
return false;
});
});
I have a form which is submitted remotely when the various elements change. On a search field in particular I'm using a keyup to detect when the text in the field changes. The problem with this is that when someone types "chicken" then the form is submitted seven times, with only the last one counting.
What would be better is something like this
keyup detected - start waiting (for one second)
another keyup detected - restart waiting time
waiting finishes - get value and submit form
before I go off and code my own version of this (I'm really a backend guy with only a little js, I use jQuery for everything), is there already an existing solution to this? It seems like it would be a common requirement. A jQuery plugin maybe? If not, what's the simplest and best way to code this?
UPDATE - current code added for Dan (below)
Dan - this may be relevant. One of the jQuery plugins I'm using on the page (tablesorter) requires this file - "tablesorter/jquery-latest.js", which, if included, leads to the same error with your code as before:
jQuery("input#search").data("timeout", null) is undefined
http://192.168.0.234/javascripts/main.js?1264084467
Line 11
Maybe there's some sort of conflict between different jQuery definitions? (or something)
$(document).ready(function() {
//initiate the shadowbox player
// Shadowbox.init({
// players: ['html', 'iframe']
// });
});
jQuery(function(){
jQuery('input#search')
.data('timeout', null)
.keyup(function(){
jQuery(this).data('timeout', setTimeout(function(){
var mytext = jQuery('input#search').val();
submitQuizForm();
jQuery('input#search').next().html(mytext);
}, 2000)
)
.keydown(function(){
clearTimeout(jQuery(this).data('timeout'));
});
});
});
function submitQuizForm(){
form = jQuery("#searchQuizzes");
jQuery.ajax({
async:true,
data:jQuery.param(form.serializeArray()),
dataType:'script',
type:'get',
url:'/millionaire/millionaire_quizzes',
success: function(msg){
// $("#chooseQuizMainTable").trigger("update");
}
});
return true;
}
Sorry i haven't tested this and it's a bit off the top of my head, but something along these lines should hopefully do the trick. Change the 2000 to however many milliseconds you need between server posts
<input type="text" id="mytextbox" style="border: 1px solid" />
<span></span>
<script language="javascript" type="text/javascript">
jQuery(function(){
jQuery('#mytextbox')
.data('timeout', null)
.keyup(function(){
clearTimeout(jQuery(this).data('timeout'));
jQuery(this).data('timeout', setTimeout(submitQuizForm, 2000));
});
});
</script>
Here's your fancy jquery extension:
(function($){
$.widget("ui.onDelayedKeyup", {
_init : function() {
var self = this;
$(this.element).keyup(function() {
if(typeof(window['inputTimeout']) != "undefined"){
window.clearTimeout(inputTimeout);
}
var handler = self.options.handler;
window['inputTimeout'] = window.setTimeout(function() {
handler.call(self.element) }, self.options.delay);
});
},
options: {
handler: $.noop(),
delay: 500
}
});
})(jQuery);
Use it like so:
$("input.filterField").onDelayedKeyup({
handler: function() {
if ($.trim($(this).val()).length > 0) {
//reload my data store using the filter string.
}
}
});
Does a half-second delay by default.
As an update, i ended up with this which seems to work well:
function afterDelayedKeyup(selector, action, delay){
jQuery(selector).keyup(function(){
if(typeof(window['inputTimeout']) != "undefined"){
clearTimeout(inputTimeout);
}
inputTimeout = setTimeout(action, delay);
});
}
I then call this from the page in question's document.ready block with
afterDelayedKeyup('input#search',"submitQuizForm()",500)
What would be nice would be to make a new jquery event which uses this logic, eg .delayedKeyup to go alongside .keyup, so i could just say something like this for an individual page's document.ready block.
jQuery('input#search').delayedKeyup(function(){
submitQuizForm();
});
But, i don't know how to customise jquery in this way. That's a nice homework task though.
Nice job, Max, that was very helpful to me! I've made a slight improvement to your function by making it more general:
function afterDelayedEvent(eventtype, selector, action, delay) {
$(selector).bind(eventtype, function() {
if (typeof(window['inputTimeout']) != "undefined") {
clearTimeout(inputTimeout);
}
inputTimeout = setTimeout(action, delay);
});
}
This way you can use it for any type of event, although keyup is probably the most useful here.
I know this is old, but it was one of the first results when I was searching for how to do something like this so I though I would share my solution. I used a combination of the provided answers to get what I needed out of it.
I wanted a custom event that worked just like the existing jQuery events, and it needed to work with keypress + delete, backspace and enter.
Here's my jQuery plugin:
$.fn.typePause = function (dataObject, eventFunc)
{
if(typeof dataObject === 'function')
{
eventFunc = dataObject;
dataObject = {};
}
if(typeof dataObject.milliseconds === 'undefined')
dataObject.milliseconds = 500;
$(this).data('timeout', null)
.keypress(dataObject, function(e)
{
clearTimeout($(this).data('timeout'));
$(this).data('timeout', setTimeout($.proxy(eventFunc, this, e), dataObject.milliseconds));
})
.keyup(dataObject, function(e)
{
var code = (e.keyCode ? e.keyCode : e.which);
if(code == 8 || code == 46 || code == 13)
$(this).triggerHandler('keypress',dataObject);
});
}
I used $.proxy() to preserve the context in the event, though there could be a better way to do this, performance-wise.
To use this plugin, just do:
$('#myElement').typePause(function(e){ /* do stuff */ });
or
$('#myElement').typePause({milliseconds: 500, [other data to pass to event]},function(e){ /* do stuff */ });