This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to create TRULY modal alerts/confirms in Javascript?
TL;DR: I've overridden the default alert() function with a custom HTML based one. I want the new dialogue to still block execution, and get the buttons within my dialogue to return true or false from the call to alert() to use in logic (and continue execution).
I'm trying to implement a custom alert box, which replaces the default browser alert with a nicely themed box with the same (or similar) functionality.
I've read this question, and I'm using the solution given in this answer (to the same question). What I want to do now is get my overridden alert to return a true or false value for use in if() statements, depending on whether OK or Cancel was clicked:
if(alert('Confirm?') {
// Do stuff
}
However, due to having custom HTML instead of a normal alert I can't do this for two reasons:
I can't return a value from the buttons in the replacement dialogue (click events bound with $.on()) because I have no idea how to.
I can't block program flow with this alert, as far as I know.
I've bound $.on() events to the Cancel and OK buttons in the replacement dialogue which hide the box. These work fine, but the problem I have now is returning a value when a button is clicked, so that execution will halt until an action is taken by the user.
HTML:
<div class="alert background"></div>
<div class="alert box">
<div class="message"></div>
<hr>
<div class="buttons">
<input type="button" name="cancel" value="Cancel">
<input type="button" name="confirm" value="OK">
</div>
</div>
Current JavaScript: (pretty much a carbon copy of the answer in my linked question)
(function () {
nalert = window.alert;
Type = {
native: 'native',
custom: 'custom'
};
})();
(function (proxy) {
proxy.alert = function () {
var message = (!arguments[0]) ? 'null' : arguments[0];
var type = (!arguments[1]) ? '' : arguments[1];
if (type && type == 'native') {
nalert(message);
} else {
// Custom alert box code
console.log(message);
}
};
})(this);
Ideally, I want to be able to put something like this in the // Custom alert box code part:
$('.alert.box input[name="confirm"]').on('click', function() {
// Hide dialogue box - I can do this already
// *** Return `true` or other truthy value from
// alert for use in `if()` statements
});
So that when the OK or Cancel button is clicked, it removes the custom alert box and returns a true or false value from the call to alert(). I can already remove the alert with $.fadeOut() and $.remove(), that's easy. What isn't is knowing how to get the button click events to get alert() (overridden) to return something.
I've tried to be as clear as I can, but I may have missed something out. Please let me know if I have.
The example below shows an approach to creating a custom alert and handling the outcome of the user selection
/*
message = String describing the alert
successCallBack = callback function for when the user selects yes
*/
function exampleAlert(message, successCallback)
{
/*Alert box object*/
var alertBox = document.createElement("div");
/*Alert message*/
var msg = document.createElement("div");
msg.innerHTML = message;
/*Yes and no buttons
The buttons in this example have been defined as div containers to accentuate the customisability expected by the thread starter*/
var btnYes = document.createElement("div");
btnYes.innerHTML= "Yes";
/*Both yes and no buttons should destroy the alert box by default, however the yes button will additionally call the successCallback function*/
btnYes.onclick = function(){ $(this.parentNode).remove();successCallback();}
var btnNo = document.createElement("div");
btnNo.innerHTML= "No"
btnNo.onclick = function(){ $(this.parentNode).remove();}
/*Append alert box to the current document body*/
$(alertBox).append(msg, btnYes, btnNo).appendTo("body");
}
function test()
{
alert("Example alert is working, don't use this test as a replacement test - horrible recursion!")
}
exampleAlert("shoe", test)
This is fairly basic and doesn't allow for additional data to be supplied to the callback function and for that reason is not ideal for production however jQuery's .bind() and similar methods allow for data to be associated with the callback method
It's worth commenting that while the above demonstrates a full implementation of the problem, there are in fact only two lines that actually matter.
btnYes.onclick...
btnNo.onclick...
Since we're achieving the desired result by binding onclick events for true and false respectively, everything else is there to paint the picture.
With that in mind it is possible to effectively turn any container object with at least one sibling into an alert box for eaxmple:
<!-- Example html -->
<div id='a'>
<ul>
<ul>
<li>Something</li>
<li>Something Else</li>
<li id='yesIdentifier'>Something not necessarily suggesting a trigger?</li>
</ul>
</ul>
</div>
As long as your yes / no (if no exists) options destroy the appropriate container a converting a container into an alert box can be handled in a couple of lines of code.
$('#yesIdentifier', '#a').click(
function(){ someCallback(); $(this).closest('#a').remove()});
Neither of the above are exemplary models for implementation but should provide some ideas on how to go about the task.
Finally... do you really need to replace the native alert method? That is, either you're writing the alert calls, in which case you'd know to use your custom method, or you're overwriting default behaviour that you can't guarantee the other developers will be aware of.
Overall recommendation:
I feel the best approach to this would be to create a jQuery plugin which creates the custom alerts on the fly and track callbacks, results and what not within the plugin.
SOliver.
Why don't you just use a confirm box like so.
var c = confirm('Confirm?');
if(c)
{
// Yes clicked
}
else
{
// No clicked
}
Or you could use jQuery UI's dialog confirmation box.
http://jqueryui.com/demos/dialog/#modal-confirmation
Related
I was thinking about how the native functions in JavaScript work today, and I can across alert() and I figured it must use createElement() or make an element and use innerHTML, but I can't figure out the complete code it would need to create a popup element, and make two buttons, then return true or false based on the one click.
jowes said:
usually JS is async; why is alert special? how and why does it create UI elements in a different way from my own scripts?
Here's the code I have figured out:
function confirm(message) {
message = message.replace(/"\n"/g, "<br />")
createElement();
//The create Element is very complicated to create the text box including message. . .
//These two functions are tied to the button's onclick's.
function clickOkay() {
valueToReturn = true
return true;
}
function clickCancel() {
valueToReturn = true
return false;
}
//here, the user hits the button, and sets valueToReturn
return valueToReturn;
}
But I don't understand how it stops the background script, if accessable, or how createElement() works, (but thats a question for another time)
alert, confirm, and prompt are all DOM APIs that are implemented by the browser. They do not create DOM elements to represent them, and their functionality cannot be exactly recreated with JavaScript because you cannot force the JavaScript engine to wait for the user to click one of your buttons. You can only come close by requiring a callback that will contain the result of the dialog that you create.
function customConfirm(message, callback) {
message = message.replace(/"\n"/g, "<br />")
createElement();
//The create Element is very complicated to create the text box including message. . .
function clickOkay() {
callback(true);
}
function clickCancel() {
callback(false);
}
}
customConfirm("Hello World!", function (result) {
console.log(result);
});
The confirm()-function is a native function brought to you by every browser.
It is not created by using javascript. However if you want to reproduce that behaviour you go a way similar to this:
function myConfirm(text, cb){
// We need this later
var body = document.getElementsByTagName('body')[0];
// First we create a div which holds the alert and give it a class to style it with css
var overlay = document.createElement('div');
overlay.className = 'myConfirm';
// The box holds the content
var box = document.createElement('div');
var p = document.createElement('p');
p.appendChild(document.createTextNode(text));
// We append the text to the div
box.appendChild(p);
// Create yes and no button
var yesButton = document.createElement('button');
var noButton = document.createElement('button');
// Add text and events to the buttons
yesButton.appendChild(document.createTextNode('Yes'));
yesButton.addEventListener('click', function(){ cb(true); body.removeChild(overlay); }, false);
noButton.appendChild(document.createTextNode('No'));
noButton.addEventListener('click', function(){ cb(false); body.removeChild(overlay); }, false);
// Append the buttons to the box
box.appendChild(yesButton);
box.appendChild(noButton);
// Append the box to the Overlay
overlay.appendChild(box)
// insert the Overlay with box into the dom
body.appendChild(overlay);
}
myConfirm('Hello there!', function(value){ console.log(value); });
.myConfirm{
position:fixed;
width:100%;
height:100%;
background:rgba(0,0,0,0.05);
}
.myConfirm>div{
width:200px;
margin:10% auto;
padding:10px 20px;
border:1px solid black;
background:#ccc;
}
.myConfirm div p{
text-align:center;
}
.myConfirm div button{
width:40%;
margin:0 5%;
}
This could be an implementation for a self-made alert-box.
Note that the native alert is a synchronous-function. That means the browser stops the JavasScript-engine until the alert-box is closed. You cant clone that behavior but at least you can give the function a callback which is called, when one of the buttons is clicked. In this case the callback just logs the value to the console.
Hope I could help here!
UPDATE to the updated question
Back in the days when JavaScript was new confirm was a valid way to ask the user for a specific value. confirm, prompt and alert are special functions from these days which behave completely different than normal functions since they break the JavaScript-"flow".
When you ask why: Well - maybe it was a nice to have-feature back in these days. Note that in earlier versions alert looked like a system-message (in IE it still does). At least in Firefox you can nowadays interact normally with your browser even if alert is called.
That's why it is merely used for debugging only today (and even here console.log is the better choice).
I am pretty sure that today (in FF) the alert is rendered with browser-intern html and CSS, too.
I am making a text adventure game, which would require user input in the form of a element in html, which would send the user input to JavaScript using the click function:
<!-- HTML CODE -->
<div class="game">
<div id="gamebox">
<a name="game"></a>
<!-- Javascript writes to here (if it works :( ) -->
</div>
<div id="inputbox">
<input type="text" id="userinput" placeholder="Input" value="" />
Go!
</div>
</div>
As you can see above, I have a element and a "Go!" button, which sends it to my JavaScript code. In JavaScript, first I define 3 variables where I would output my text.
//JavaScript Code
var txt_input = $("#userinput");
var btn_quest = $("#btn-quest");
I would than define 2 other functions, which allows me to write into the . I would than have other functions, which are for the storyline of the text adventure game. However, the root of the problem is that I can't seem to progress past the second event. Here are my events:
function wakeUp() {
displayGame("You wake up, at stackoverflow. West or east? [Choose 'west' or 'east']");
btn_quest.on({
"click": function() {
// Begin input preproccessing
var input = txt_input.val().toLowerCase();
// If/else block for choice here
if (input === "west") {
//Paste btn_quest here for new event
goWest();
} else if (input === "east") {
//Paste btn_quest here for new event
goEast();
} else {
//Error handler - do not modify
txt_input.val("Error - enter a valid choice");
}
//End of if else block body
}
});
The first event function would work perfectly, and write to my html, and accept the first user choice. However, at the next event, no matter what it is, (goEast() or goWest()), my program aways displays "Error - enter a valid choice"). Right now, my hypothesis is that the "switch" function isn't working correctly. However, I honestly don't know. What is the issue here, and how can I fix it? The other event functions (etc goEast) are exactly the same as the wakeUp function, except with different displayGame() strings and link to other event functions.
I have not included the full code, in order to keep my code short - but here is the full html/css/javascript if needed: http://plnkr.co/edit/55heHh4k5QEIVYdBrWGB?p=preview
Edit: I tried to implement the suggestion, like this: But It seems that JavaScript doesn't even get the userinput anymore. When I try to submit the user's response, nothing happens. What went wrong? I did the same thing here with all of my functions in the game:
function wakeUp() {
displayGame("You wake up at stackoverflow again, but it didn't work. Go West or east again?");
// btn_quest.off("click").on("click",function()){
btn_quest.off("click").on;
"click", function() {
// Begin input preproccessing
var input = txt_input.val().toLowerCase();
// If/else block for choice here
if (input === "walk") {
//Paste btn_quest here for new event
walkToWork();
} else if (input === "bus") {
//Paste btn_quest here for new event
busToWork();
} else {
//Error handler - do not modify
txt_input.val("Error - enter a valid choice");
}
//End of if else block body
};
//End of function. Copy until line under this comment V
}
What did I do wrong? Can you please show a example using this function?
You need to look at all the code to see the problem. The reason is because you keep binding to the element so multiple click events are being triggered. You need to remove the last click
btn_quest.off("click").on("click",function(){});
I found this question is already asked several times in different forms, but I still need some help on this, since can't get this as in the examples.
I have a JSF 2 page with PrimeFaces, and it contains the following hidden button, which I need to call on pageUnLoad from javascript.
The JSF has:
// Supposed to be hidden eventually
<h:commandButton id="doStuff" action="#{myBean.callMethod()}" />
The javascript has:
var stuff = new Object();
$(window).bind('beforeunload', function() {
stuff.doStuff();
});
stuff.doStuff = function() {
// var hidden = $("#doStuff"); // Incorrect
var hidden = document.getElementById("formId:doStuff"); // Correct
if (hidden === undefined) {
// Some logging
} else {
hidden.click();
}
}
And the managedBean has:
#ManagedBean(name = "myBean")
#RequestScoped
public class MyBean {
public void callMethod() {
// Do stuff
}
}
By debugging I can see that when manually clicking the button, it fires the event correctly.
I am also able to verify that the JavaScript is called correctly, it "seems" to find the element, and performs the '.click()' for it, but I do not catch any event on the server side.
I seem to be doing it as it has been instructed in other similar questions, but I lack the final result.
Any help would be appreciated, thanks.
Hidden button can be clicked by using JavaScript like
document.getElementById('doStuff').click();
However, you should be careful about naming containers. Hidden button must be enclosed by a <h:form> tag and prependid attribute of it should be set false. Otherwise you can access the button with the id formId:doStuff.
See also
Naming Container in JSF2/PrimeFaces
Cannot click hidden button by JavaScript
There is a much simpler way of calling server-side methods from javascript. Define a p:remoteCommand and Primefaces will create a JavaScript-function which you can call from inside your JavaScript-functions.
Use the following for defining the remoteCommand:
<p:remoteCommand name="doStuff" action="#{myBean.callMethod()}"/>
And then to call the bean-method on beforeunload just use:
$(window).bind('beforeunload', doStuff);
I want to make a custom made confirmation box in javascipt just like the built in confirm box. the built in confirm box does not allow the code to progress unless the user selects atleast one thing. Below is my code:
*****HTML start*****
<div class = "popUp confirm" style="z-index:40000;" id="confirmBlock">
<div id = "confirmLabel" >Confirm Message</div>
<div style ="border:0px solid red;height:44.56px;">
<input id="Confirm" type="button" value="Confirm" onclick = "confirmAction(1)" />
<input id = "CancelConfirm" type="button" value="Cancel" onclick = "confirmAction(0)" />
</div>
</div>
*****HTML end*****
*****Javascript start*****
var confirmresult = "-1";
function confirmationLoop()
{
alert("If this alert is preesnt it works, seems like the built in alert provides some sort of pause for other parts of code to continue to work");
if(confirmresult == "-1")
confirmationLoop();
return;
}
function confirmAction(val)
{
confirmresult = val;
}
function checkuuu()
{
confirmresult = "1";
}
function confirmMessage(message)
{
document.getElementById("confirmLabel").innerHTML= message;
//var check = setTimeout(function(){confirmAction(1)},5000);
confirmationLoop();
/*
while(1) //using while almost does not allow any other part to run at all hence tried recursion
{
if(confirmresult != "-1")
break;
}
*/
document.getElementById("confirmLabel").innerHTML= "Confirm Message";
var returnVal = confirmresult;
confirmresult = -1;
return returnVal;
}
*****Javascript end*****
*****Sample code start*****
So this i what i expect below:
function example
{
var check = confirmMessage(message);
//the next part of code should not execute untill i press confirm or cancel, using settimeout or settimeinterval is asynchronous and the code flow continues. i want the effect something like alert and confirm built in boxes
}
*****Sample code end*****
I used loop but it keeps the thread completely occupied and does not give me a chance to press any button, which was quite obvious
However recursion gives u the freedom to perform other activities. The problem even though the value of confirmResult will become 1 upon pressing confirm button, which i check through alert. the recursive loop i.e. confirmation loop does not seem read it as 1. it still continues as -1. If i put a alert in that confirmation loop the value wil be read as 1. Can anyone help me to achieve what i started out to??????
P.s.=> sorry for such a huge question!!!
You can't use any sort of loop - as you've found it'll just cause the browser to lock up.
What you need to do is to emulate a "modal" dialog box.
This is usually done by having your dialog box appear on top of another "overlay" element which importantly covers every other element, and prevents any user interaction with them.
It's also pretty hard to implement a confirm function that'll return a value - the window.confirm method can only do that because it's synchronous - it blocks all other JS processing while the dialog is displayed.
The easiest approach is to instead supply a callback function that'll get called once the user has selected the desired value.
how can i alert the user if there are any changes inside the object field
i''m trying to detect the changes on this div inside the object
if it's normal the code would be this:
<div id="HeaderNewMessageIcon" class="BrosixContactNewMessage" style="display:none;">
</div>
but if there are changes it will look like this:
<div id="HeaderNewMessageIcon" class="BrosixContactNewMessage" style="display: block; ">
</div>
i want to alert the user if there are changes inside the object, either via alert or using an image.
is there any way for me to achieve this?
and another thing, i have no access to the code inside the object, i can only view it but not edit it.
I believe there must be some JavaScript code which changing your html you can call your method from there. Other way you can use setInterval.
You can use jQuery plugin Mutation Events plugin for jQuery . see thread
var a = document.getElementsByClassName('HeaderNewMessageIcon')[0];
var oldTitle = a.title;
setInterval(function(){
if(a.title !== oldTitle){
alert("Title change");
oldTitle = a.title;
}
},100);
jsfiddle
You have to detect the changes when throught user interaction such as click, mouseover, mousedown, etc... then you can attach a function to see if its attributes or anything inside it changes.
//detect inputs change
$('#HeaderNewMessageIcon').find(':input').change(function(){ alert(...)});
//detect attributes change
$('#HeaderNewMessageIcon').click(function(){
detectChange(this);
});
As for detectChange to work, you must save the attributes when page just loaded
var attrs = $('#HeaderNewMessageIcon').get(0).attributes;
function detectChange(obj){
//pseudo-code, you need to find a function on the web to commpare 2 objetcs
if (obj.attributes === attrs){
alert(...);
}
//the same comparison for the children elements $(obj).children()
}