MooTools function return value - javascript

I am developing the MooTools confirm box function. In which I have two buttons which are OK and CANCEL.
So I want return TRUE on click of OK and return FALSE on click on CANCEL.
Here is my function code.
function confirm_box(title, text)
{
var className = 'msgAlert info';
var defaut_title ='Information';
// Placing the Overlay
var overlay = new Element('div', {'class':'msgAlert_overlay'});
$$('body').adopt(overlay);
// Placing the Main Div With class name
var main_box = new Element('div', {'class': className});
$$('body').adopt(main_box);
var content_div = new Element('div', {'class':'msgAlert_popup'});
//
if(title == '')
title=defaut_title;
content_div.set('html','<div class="msgAlert_header"><h4>'+title+'</h4></div><div class="msgAlert_content">'+text+'</div>');
main_box.adopt(content_div);
content_div.getChildren('a.msgAlert_close');
var footer_div = new Element('div',{'class':'msgAlert_footer'});
var ok_btn = new Element('button');
ok_btn.addEvent('click', function(){
main_box.fade(0);
//overlay.fade(0);
(function(){main_box.dispose(); overlay.dispose(); }).delay(350);
return true;
});
var cancel_btn = new Element('button');
cancel_btn.addEvent('click', function(){
main_box.fade(0);
//overlay.fade(0);
(function(){main_box.dispose(); overlay.dispose();}).delay(350);
return false;
});
ok_btn.set('html','Ok');
cancel_btn.set('html','Cancel');
footer_div.adopt(ok_btn);
footer_div.adopt(cancel_btn);
main_box.adopt(footer_div);
ok_btn.focus();
}
I have placed return TRUE and FALSE on click on respective buttons.
Can any suggest in which way I have to go so I can access my function just like the JS confirm box:
Just Like :
if(confirm_box(title, text))
{
alert('Yes');
}
else
{
alert('No');
}

this is not going to work. basically, you can use the native
if (confirm("are you sure")) { ... } else { ... }
which is fine, because it is blocking the UI thread...
when you want to replicate a confirm box, you need to work with an event callback method instead as your function will NOT have a return value.
in pseudo code, this will be:
var confirm_box = function(title, text, onConfim, onCancel) {
...
confirmEl.addEvent("click", onConfirm);
cancelEl.addEvent("click", onCancel);
};
confirm_box("Are you sure?", "Please confirm by clicking below", function() {
alert("yes");
}, function() {
alert("no");
});
in the context of mootools and Classes, you may want to do a confirm class which works with events instead. If you want an example, give me a shout.

Related

Making bootstrap-tags responsive, jquery events lost

I am trying to change this demo:
http://maxwells.github.io/bootstrap-tags.html
into a responsive version in which I can set it to readOnly and remove it from readOnly as I like. This code:
var alltags = ["new tag", "testtag", "tets", "wawa", "wtf", "wtf2"];
$(document).ready(function() {
var tagbox = $('#my-tag-list').tags({
suggestions: alltags
});
var tagenable = true;
$('#my-tag-list').focusout(function() {
if (tagenable) {
tagbox.readOnly = true;
$('#my-tag-list').empty();
tagbox.init();
tagenable = false;
}
});
$('#my-tag-list').click(function() {
if(!tagenable) {
tagbox.readOnly = false;
$('#my-tag-list').empty();
tagbox.init();
tagenable = true;
}
});
});
seems to work fairly well, it makes everything readonly after focusout and editable when I click it. However, the editing does not work since I cannot insert new tags nor delete them (seems to be like event handling was lost or something like that).
I am guessing that emptying the #my-tag-list div is causing this, but I cannot yet find a way to use for instance "detach" instead that removes everything inside (not the element itself) and putting it back in again.
I tried to make a JS Fiddle, but it isn't really working so well yet:
http://jsfiddle.net/tomzooi/cLxz0L06/
The thing that does work is a save of the entire website, which is here:
https://www.dropbox.com/sh/ldbfqjol3pppu2k/AABhuJA4A6j9XTxUKBEzoH6za?dl=0
this link has the unminimized JS of the bootstrap-tags stuff I am using:
https://github.com/maxwells/bootstrap-tags/blob/master/dist/js/bootstrap-tags.js
So far I managed to do this with some modifications of the bootstrap javascript code. I use two different tagbox which I hide and unhide with some click events.
var tagbox = $('#my-tag-list').tags({
suggestions: alltags,
tagData: tmp_tags,
afterAddingTag: function(tag) { tagboxro.addTag(tag); },
afterDeletingTag: function(tag) {tagboxro.removeTag(tag); }
});
var tagboxro = $('#my-tag-listro').tags({
suggestions: alltags,
tagData: tmp_tags,
readOnly: 'true',
tagSize: 'sm',
tagClass: 'btn-info pull-right'
});
$(document).mouseup(function (e) {
var container = $("#my-tag-list");
if (!container.is(e.target) // if the target of the click isn't the container...
&& container.has(e.target).length === 0) { // ... nor a descendant of the container
if (tagsave) {
$("#my-tag-listro").show();
$("#my-tag-list").hide();
var tags = tagbox.getTags();
$.post("%basedir%/save.php", {
editorID:"new_tags",
tags:tags
}, function(data,status){
//alert("Data: " + data + "\nStatus: " + status);
});
tagsave = false;
}
}
});
$('#my-tag-listro').click(function() {
tagsave = true;
//$(".tag-list").toggle();
$("#my-tag-list").show();
$("#my-tag-listro").hide();
});
I had to modify the code of bootstrap-tags.js to allow for this since it normally deletes all of the usefull functions when it is considered readonly in the init function:
if (this.readOnly) {
this.renderReadOnly();
this.removeTag = function(tag) {
if (_this.tagsArray.indexOf(tag) > -1) {
_this.tagsArray.splice(_this.tagsArray.indexOf(tag), 1);
_this.renderReadOnly();
}
return _this;
};
this.removeTagClicked = function() {};
this.removeLastTag = function() {};
this.addTag = function(tag) {
_this.tagsArray.push(tag);
_this.renderReadOnly();
return _this;
};
this.addTagWithContent = function() {};
this.renameTag = function() {};
return this.setPopover = function() {};
}
would be awesome if this feature was incorporated in a somewhat less hacky way though :)

How to achieve a queue of object instances of jQuery modals, assuring only one instance is on per time?

I've a task of building a modal prompt, that's been simple so far describing its methods like "show", "hide" when it comes down just to DOM manupulation.
Now comes the hardship for me... Imagine we have a page on which there are several immediate calls to construct and show several modals on one page
//on page load:
$("browser-deprecated-modal").modal();
$("change-your-city-modal").modal();
$("promotion-modal").modal();
By default my Modal (and other libraries i tried) construct all of these modals at once and show them overlapping each other in reverse order -
i.e $(promotion-modal) is on the top, while the
$("browser-deprecated-modal") will be below all of them. that's not what i want, let alone overlapping overlays.
I need each modal to show up only when the previous one (if there'are any) has been closed. So, first we should see "browser-deprecated-modal" (no other modals underneath), upon closing it there must pop up the second one and so on.
I've been trying to work it out with this:
$.fn.modal = function(options) {
return this.each(function() {
if (Modal.running) {
Modal.toInstantiateLater.push({this,options});
} else {
var md = new Modal(this, options);
}
});
}
destroy :function () {
....
if (Modal.toInstantiateLater.length)
new Modal (Modal.toInstantiateLater[0][0],Modal.toInstantiateLater[0][1]);
}
keeping a track of all calls to construct a Modal in a array and in the "destroy" method make a check of this array is not empty.
but it seems awkward and buggy me thinks.
i need a robust and clear solution. I've been thinking about $.Callbacks or $.Deferred,
kinda set up a Callback queue
if (Modal.running) { //if one Modal is already running
var cb = $.Callbacks();
cb.add(function(){
new Modal(this, options);
});
} else { //the road is clear
var md = new Modal(this, options);
}
and to trigger firing cb in the destroy method, but i'm new to this stuff and stuck and cannot progress, whether it's right or not, or other approach is more suitable.
Besides, I read that callbacks fire all the functions at once (if we had more than one extra modal in a queue), which is not right, because I need to fire Modal creation one by one and clear the Callback queue one by one.
Please help me in this mess.
My code jsfiddle
I got rid of the counter variable, as you can use toInstantiateLater to keep track of where you are, and only had to make a few changes. Give this a try...
Javscript
function Modal(el, opts){
this.el = $(el);
this.opts = opts;
this.overlay = $("<div class='overlay' id='overlay"+Modal.counter+"'></div>");
this.wrap = $("<div class='wrap' id='wrap"+Modal.counter+"'></div>");
this.replace = $("<div class='replace' id='replace"+Modal.counter+"'></div>");
this.close = $("<span class='close' id='close"+Modal.counter+"'></span>")
if (Modal.running) {
Modal.toInstantiateLater.push(this);
}
else {
Modal.running = true;
this.show();
}
}
Modal.destroyAll = function() {
Modal.prototype.destroyAll();
};
Modal.prototype = {
show: function() {
var s = this;
s.wrap.append(s.close);
s.el.before(s.replace).appendTo(s.wrap).show();
$('body').append(s.overlay).append(s.wrap);
s.bindEvents();
Modal.currentModal = s;
},
bindEvents: function() {
var s = this;
s.close.on("click.modal",function(e){
s.destroy.call(s,e);
});
},
destroy: function(e) {
var s = this;
s.replace.replaceWith(s.el.hide());
s.wrap.remove();
s.overlay.remove();
if (Modal.toInstantiateLater.length > 0) {
Modal.toInstantiateLater.shift().show();
}
else {
Modal.running = false;
}
},
destroyAll: function(e) {
Modal.toInstantiateLater = [];
Modal.currentModal.destroy();
}
}
Modal.running = false;
Modal.toInstantiateLater = [];
Modal.currentModal = {};
$.fn.modal = function(options) {
return this.each(function() {
var md = new Modal(this, options);
});
}
$("document").ready(function(){
$("#browser-deprecated-modal").modal();
$("#change-your-city-modal").modal();
$("#promotion-modal").modal();
$("#destroy-all").on("click", function() {
Modal.destroyAll();
});
});
jsfiddle example
http://jsfiddle.net/zz9ccbLn/4/

need to modify this jquery pop menu script to work with ajax

I am using this script from: http://pop.seaofclouds.com/
The problem is if you call the script multiple times it causes a cascading effect of a pop-out within a pop-out for as many times as you call the script.
I'm trying to figure out how to prevent it from executing when the popout has already been set. Here's the script:
//
// pop! for jQuery
// v0.2 requires jQuery v1.2 or later
//
// Licensed under the MIT:
// http://www.opensource.org/licenses/mit-license.php
//
// Copyright 2007,2008 SEAOFCLOUDS [http://seaofclouds.com]
//
(function($) {
$.pop = function(options){
// inject html wrapper
function initpops (){
$(".pop").each(function() {
var pop_classes = $(this).attr("class");
if ( $(this).find('.pop_menu').length) {
// do nothing
} else {
$(this).addClass("pop_menu");
$(this).wrap("<div class='"+pop_classes+"'></div>");
$(".pop_menu").attr("class", "pop_menu");
$(this).before(" \
<div class='pop_toggle'></div> \
");
}
});
}
initpops();
// assign reverse z-indexes to each pop
var totalpops = $(".pop").length + 100;
$(".pop").each(function(i) {
var popzindex = totalpops - i;
$(this).css({ zIndex: popzindex });
});
// close pops if user clicks outside of pop
activePop = null;
function closeInactivePop() {
$(".pop").each(function (i) {
if ($(this).hasClass('active') && i!=activePop) {
$(this).removeClass('active');
}
});
return false;
}
$(".pop").mouseover(function() { activePop = $(".pop").index(this); });
$(".pop").mouseout(function() { activePop = null; });
$("body").on("click", ".pop", function(){
closeInactivePop();
});
// toggle that pop
$("body").on("click", ".pop_toggle", function(){
$(this).parent(".pop").toggleClass("active");
});
}
})(jQuery);
now when i load this script on an ajax call the new pop-out menus work but the old ones do not react to the onclick event.
You shouldn't mess with the plugin. It works exactly like it should.
Better show us how you call this on elements that you already have.
Also I don't like this plugin. Better use something from JqueryUI
You can do such thing in much easier way.
[edit]
I tried your first code (the plugin) and it works correctly for me.
[edit]
OK. I get it. You call $.pop(); multiple times. You shouldn't! Calling $.pop(); will pin up the drop down menu to all elements that has class="pop". This is the reason why you have such funny stack.
Just use $.pop(); once.
Plugin doesn't give ability to connect NEW elements that was dynamically created on the page.
Removed pop from ajax call and just called this on success:
$(".pop").each(function() {
var pop_classes = $(this).attr("class");
if ( $(this).find('.pop_menu').length) {
// do nothing
} else {
$(this).addClass("pop_menu");
$(this).wrap("<div class='"+pop_classes+"'></div>");
$(".pop_menu").attr("class", "pop_menu");
$(this).before(" \
<div class='pop_toggle'></div> \
");
}
});
// assign reverse z-indexes to each pop
var totalpops = $(".pop").length + 100;
$(".pop").each(function(i) {
var popzindex = totalpops - i;
$(this).css({ zIndex: popzindex });
});
// close pops if user clicks outside of pop
activePop = null;
function closeInactivePop() {
$(".pop").each(function (i) {
if ($(this).hasClass('active') && i!=activePop) {
$(this).removeClass('active');
}
});
return false;
}
$(".pop").mouseover(function() { activePop = $(".pop").index(this); });
$(".pop").mouseout(function() { activePop = null; });

Javascript - Wait a function to finish

I need to implement a confirm box replacement by using jquery dialog. I have a calling function like this
function callingFunc() {
var a = confirmJquery("text", 300, 300, "ok", "cancel");
if (a == true) {
.....
}
else {
....
}
}
This is the confirmJquery function
function confirmJquery(msg, width, height, txtOk, txtCancel) {
var div = document.createElement('div');
div.className = "confirmJquery";
var span = document.createElement('span');
$(span).html(msg);
div.appendChild(span);
var buttonOk = document.createElement('button');
buttonOk.className = 'buttonStyleBigger';
$(buttonOk).html(txtOk);
var buttonCancel = document.createElement('button');
buttonCancel.className = 'buttonStyleBigger';
$(buttonCancel).html(txtCancel);
var divBottom = document.createElement('div');
divBottom.className = 'dialogAction';
divBottom.appendChild(buttonOk);
divBottom.appendChild(buttonCancel);
div.appendChild(divBottom);
var dialog = window.parent.$(div).appendTo(window.parent.document.body);
// open the dialog
dialog.dialog({
height: height,
width: width,
resizable: false,
// add a close listener to prevent adding multiple divs to the document
close: function(event, ui) {
// remove div with all data and events
dialog.remove();
},
modal: true
});
$(buttonOk).bind('click', function(){
return true;
});
$(buttonCancel).bind('click', function() {
return false;
});
}
The problem is, the confirmJquery function always finish before the button (Ok or Cancel) is pressed; hence, there is no value in the calling function. I need to make the confirmJquery waits until user press the button and then function finish and the rest of the calling function continues. How can i do that ?
I need to update more details: I already tried the call back function way. It works perfectly. But, life is not easy like that. This is a very big, old, messy system. Doing that requires me to re-write lot lot of functions, so i need to create a function that act exactly like the confirm function of javascript
Since your function is going to be asynchronous, you need to use a callback. Something like this:
function myCallback(result)
{
if (result) {
// OK
} else {
// Cancel
}
}
function confirmJquery(msg, width, height, txtOk, txtCancel, callback) {
...
$(buttonOk).bind('click', function(){
callback(true);
});
$(buttonCancel).bind('click', function() {
callback(false);
});
}
and
confirmJquery(msg, width, height, txtOk, txtCancel, myCallback);
Move the rest of the function inside another function, and execute that second function at the end of the confirmJquery function.
function firstfunction(){
// Do Some Stuff
secondfunction();
}
first, to avoid a long list of arguments on the receiving side, you can use an object of arguments instead. then send over a callback to confirmJquery
function callingFunc() {
var a = confirmJquery({
msg:"text",
width:300,
height:300,
txtOk:"ok",
txtCancel:"cancel"
},function(ok){
if(ok){
...
} else {
...
}
});
}
function confirmJquery(options,callback) {
//options.msg
//options.width
...
$(buttonOk).bind('click', function(){
callback(true);
});
$(buttonCancel).bind('click', function() {
callback(false);
});
}
yes, alexander is right, just reorganize code, one for dialog, one for function based on a flag/msg. just like mvc pattern.

Jquery confirmation box

I'm looking to create a generic confirmation box that can be used by multiple widgets easily, but I'm running into problems with scope and was hoping for a clearer way of doing what I'm trying to do.
Currently I have the following -
(function() {
var global = this;
global.confirmationBox = function() {
config = {
container: '<div>',
message:''
}
return {
config: config,
render: function(caller) {
var jqContainer = $(config.container);
jqContainer.append(config.message);
jqContainer.dialog({
buttons: {
'Confirm': caller.confirm_action,
Cancel: caller.cancel_action
}
});
}
}
} //end confirmationBox
global.testWidget = function() {
return {
create_message: function(msg) {
var msg = confirmationBox();
msg.message = msg;
msg.render(this);
},
confirm_action: function() {
//Do approved actions here and close the confirmation box
//Currently not sure how to get the confirmation box at
//this point
},
cancel_action: function() {
//Close the confirmation box and register that action was
//cancelled with the widget. Like above, not sure how to get
//the confirmation box back to close it
}
}
}//end testWidget
})();
//Create the widget and pop up a test message
var widget = testWidget();
widget.create_message('You need to confirm this action to continue');
Currently I'm just looking to do something as simple as close the box from the within the widget, but I think I've wrapped my own brain in circles in terms of what knows what.
Anyone want to help clear my befuddled brain?
Cheers,
Sam
The resulting code:
I thought it might be useful for people who find this thread in later days looking for a solution to a similar problem to see the code that resulted from the helpful answers I got here.
As it turns out it was pretty simple in the end (as most of the frustrating mind-tangles are).
/**
* Confirmation boxes are used to confirm a request by a user such as
* wanting to delete an item
*/
global.confirmationBox = function() {
self = this;
config = {
container: '<div>',
message: '',
}
return {
set_config:config,
render_message: function(caller) {
var jqContainer = $(config.container);
jqContainer.attr('id', 'confirmation-dialog');
jqContainer.append(config.message);
jqContainer.dialog({
buttons: {
'Confirm': function() {
caller.confirm_action(this);
},
Cancel: function() {
caller.cancel_action(this);
}
}
});
}
}
} // end confirmationBox
global.testWidget = function() {
return {
create_message: function(msg) {
var msg = confirmationBox();
msg.message = msg;
msg.render(this);
},
confirm_action: function(box) {
alert('Success');
$(box).dialog('close');
},
cancel_action: function(box) {
alert('Cancelled');
$(box).dialog('close');
}
}
}//end testWidget
You could pass jqContainer to the confirm/cancel functions.
Alternately, assign jqContainer as a property of caller. Since the confirm/cancel functions are called as methods of caller, they will have access to it via this. But that limits you to tracking one dialog per widget.
Try something like this:
(function() {
var global = this;
/*****************This is new****************/
var jqContainer;
global.confirmationBox = function() {
config = {
container: '<div>',
message:''
}
return {
config: config,
render: function(caller) {
// store the container in the outer objects scope instead!!!!
jqContainer = $(config.container);
jqContainer.append(config.message);
jqContainer.dialog({
buttons: {
'Confirm': caller.confirm_action,
Cancel: caller.cancel_action
}
});
}
}
} //end confirmationBox
global.testWidget = function() {
return {
create_message: function(msg) {
var msg = confirmationBox();
msg.message = msg;
msg.render(this);
},
confirm_action: function() {
//Do approved actions here and close the confirmation box
//Currently not sure how to get the confirmation box at this point
/*******Hopefully, you would have access to jqContainer here now *****/
},
cancel_action: function() {
//Close the confirmation box and register that action was
//cancelled with the widget. Like above, not sure how to get
//the confirmation box back to close it
}
}
}//end testWidget
})();
//Create the widget and pop up a test message
var widget = testWidget();
widget.create_message('You need to confirm this action to continue');
If that doesn't work, try defining your callbacks (confirm_action, cancel_action) as private members of your object. But they should be able to access the outer scope of your main object.

Categories