How to make function like confirm - javascript

I want to make custom confirm function.
so, I make a code like :
function confirm(msg){
var obj = document.createElement("div");
var body = document.createElement("div");
body.innerHTML = msg;
var foot = document.createElement("div");
var ok = document.createElement("div");
ok.innerHTML = "OK";
var cancel = document.createElement("div");
cancel.innerHTML = "Cancel";
foot.appendChild(ok);
foot.appendChild(cancel);
obj.appendChild(body);
obj.appendChild(foot);
document.getElementsByTagName("body")[0].appendChild(obj);
ok.onclick = function(){
return true;
}
cancel.onclick = function(){
return false;
}
}
or
returnValue = -1;
ok.onclick = function(){
returnValue = true;
}
canacel.onclick = function(){
returnValue = false;
}
while(true){
if(returnValue !== -1) break;
}
return returnValue;
If this custom confirm function must get 1 parameter like original confirm function.
How can make the custom confirm function?

Personally, I would use a third-party dialog already written for this, write a jQuery plugin, or at least take a more object-oriented approach. As it stands, you are putting a confirm function in the global namespace (where a confirm function already exists).
Also note that you can't halt execution of the page and wait for a response like window.confirm can. See: How can I reproduce the "wait" functionality provided by JavaScript's confirm() function? (where the accepted answer is "you can't").
The available way of performing such a task is to use a callback:
function customConfirm(message, resultCallback){
ok.onclick = function(){
// note that you can pass whatever you want to the callback
// you are not limited to one parameter.
resultCallback(true);
}
cancel.onclick = function(){
resultCallback(false);
}
}
In the above example, resultCallback is a function defined to perform an action(s) in response to events in your confirmation box.
You could pass an object with both the message and the callback to achieve the single parameter goal, but I suspect the real goal is to replace window.confirm which (as stated) behaves differently.
{ message: "foo", callback: function bar(status){ alert(status); } }

You can't have your confirm function halt until a value is found, otherwise the whole page would freeze. What you need in this case is to provide a callback to execute once either of the buttons is clicked (if you can not pass it as argument for any reason, you'd have to use a global var, or maybe a queue):
var queue = [];
function confirm(msg){
...
var callback = queue.shift();
ok.onclick = function(){
callback(true);
}
cancel.onclick = function(){
callback(false);
}
}
You use it this way:
queue.push(function(returnValue) {
if ( returnValue ) {
// Code for "yes"
}
else {
// Code for "no"
}
});
confirm("Are you sure?");

like my case i used promise to solve the delete confirmation problem, here is the code
function deleteBook(id, elm) {
const container_alert = document.querySelector('.container-alert')
alertMsg('Anda yakin ingin menghapus?').then(() => {
// console.log('i love you');
let index = books.findIndex(book => book.id == id);
books.splice(index, 1)
updateDataToStorage();
elm.parentNode.parentNode.remove()
container_alert.classList.add('hidden')
}).catch(() => {
container_alert.classList.add('hidden')
})
}
and my alert function code is as follows
function alertMsg(msg) {
const container_alert = document.querySelector('.container-alert')
const btn_yes = document.querySelector('.action-alert .yes')
const btn_cancel = document.querySelector('.action-alert .cancel')
container_alert.classList.remove('hidden')
return new Promise((resolve, reject) => {
btn_yes.addEventListener('click', function(){
resolve()
})
btn_cancel.addEventListener('click', function(){
reject()
})
})
}

Related

Send event when module was executed

I'm really stuck on this.. I need to send an event when both Load module and Hide module code was executed, and only then send the event. Ideas on how to achieve this?
// Load module
(
function() {
var s=document.createElement('script');
s.type='text/javascript';
s.async=true;
s.src='https://example.com/bundles.js';
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
}
)();
// Hide module
var inverval = setInterval(hideClass, 100);
function hideClass () {
if ($(".class").hide().length > 0) clearInterval(inverval);
}
// When both happend = Send a event to Google Analytics
DigitalData.push({'event':Module, 'eventLabel':'Page'});
If this is your only option, then perhaps there's something you are going about wrongly. Anyway, let's see ... Only when both events have taken place.
var HandleTwoEvents = function (key1, key2) {
this.count = 0;
this.pack = [];
$self = this;
this.startListening = function(fn) {
fn = fn || function () {}
window.addEventListener(key1, function (ev) {
if ($self.pack.indexOf(key1) < 0) {
$self.pack.push(key1);
$self.count++;
if ($self.count == 2) {
fn();
$self.count = 0;
}
}
console.log(key1, ev);
});
window.addEventListener(key2, function (ev) {
if ($self.pack.indexOf(key2) < 0) {
$self.pack.push(key2);
$self.count++;
if ($self.count == 2) {
fn();
$self.count = 0;
}
}
console.log(key2, ev);
});
}
}
Forgive me, i always use this function to create events
function createEvent(name, obj) {
var evt = document.createEvent("Event");
evt.initEvent(name, true, true);
evt.data = obj;
dispatchEvent(evt);
}
Now, to log both events ...
var both = new HandleTwoEvents("EventKeyOne", "EventKeyTwo");
both.startListening(function () {console.log("This means that both Events have taken place")});
Now, let's test ...
createEvent("EventKeyOne", {});
//key, data are the arguments ... function defined in startListening above does not execute, and upon inspection, both.count is seen to be 1
createEvent("EventKeyTwo", {});
//Now, function executes.
//It also works if "EventKeyTwo" is raised before "EventKeyOne"
Happy Coding!
PS: I'm sure there's a better way to handle the use of the $self variable, with some function binding, i guess. I've never been able to learn it.

Javascript function to dynamically create buttons with return value based on button clicked

I'm trying to create a stylized yes/no dialog that can be called (created and destroyed) by single java script function, that will return a value depending on which button is clicked. But the function only return the declared value, not the one that is depending by the button clicked. Here's the core of the code:
<script>
function mbox(header, msg) {
var result = false;
var modal = document.createElement("div");
var modal_ok = document.createElement("input");
var modal_cancel = document.createElement("input");
modal.id = "modal";
modal_ok.id = "modal_ok";
modal_ok.type = "submit";
modal_ok.value = "OK";
modal_ok.onclick = function(){clicked(1)};
modal_cancel.id = "modal_cancel";
modal_cancel.type = "submit";
modal_cancel.value = "Cancel";
modal_cancel.onclick = function(){clicked(0)};
modal.appendChild(modal_ok);
modal.appendChild(modal_cancel);
document.body.appendChild(modal);
document.getElementById('modal_ok').focus();
function clicked(param){
if(param == 1){
result = true;
}else{
result = false;}
var elem = document.getElementById("modal");
elem.parentNode.removeChild(elem);
}
return result;
}
</script>
<p id="demo">My First Paragraph.</p>
<script>
if(mbox("header", "msg") == true){document.getElementById("demo").innerHTML = "Paragraph changed.";}
</script>
Please, no jquery or any other instant framework solutions. I'm still learning javascript, so I want to understand the concept.
Thanks in advance for any help, and sorry for my english.
The problem is that showing the dialog (and getting the user input from it) is an asynchronous action (i.e. it does not yield a result right away), and that you are trying to use it synchronously (comparing the return type at the same moment you call the function).
When the mbox() method reaches the return result, the user has not clicked on either OK or Cancel yet.
A way to fix this is by using a callback pattern. You define a function to be executed after the mbox is closed, and pass it to mbox() like this:
<script>
mbox("header", "msg", function (result){
if (result) {
document.getElementById("demo").innerHTML = "Paragraph changed.";
}
});
</script>
Then modify the clicked() method to call the defined callback with the result:
function clicked(param) {
if(param == 1) {
result = true;
} else {
result = false;
}
var elem = document.getElementById("modal");
elem.parentNode.removeChild(elem);
callback(result); // or even shorter: callback(param == 1)
}
Don't forget to update the mbox() method to accept a third (callback) parameter, and you can basically remove the return statement at the end of the function body.
Finally, if you're going to work with a lot of asynchronous functions, you might want to check out other solutions for result handling, such as Promises, as callbacks in callbacks in callbacks are sometimes difficult to handle properly (especially when the async operations might fail/return an error).
You can't return a value in the mbox function because you are waiting for a user to interact.
You should use a callback to the messagebox like so:
function mbox(header, msg, callback) {
And your click function looks something like this:
function clicked(param){
callback && callback(param === 1);
modal.parentNode.removeChild(modal);
}
And now you can call it like so:
mbox('Confirm','Please tell me you like this answer', function(bool){
if(bool){
document.getElementById("demo").innerHTML = "Paragraph changed.";
}
});

return value from onClick

I wrote a method that helps to upload images to page.There is a text area with and input area to upload file with id=imgFileUploadQwersergsd
function forumImageUpload() {
if (!($("input#imgFileUploadQwersergsd").length)) {
$("div").last().append("<input id='imgFileUploadQwersergsd' type='file' data-url='/Images' style='display:none;' />");
}
var uploader = $("input#imgFileUploadQwersergsd");
$("div").last().append("<button id='ok' onClick =\"returnString('imgFileUploadQwersergsd')\">" + "Ok" + "</button>");
returnString method return the uploaded file name:
function returnString(stringValue) {
var imgSrc = document.getElementById(stringValue).value();
var pos = imgSrc.lastIndexOf("\\");
if (pos != -1) {
imgSrc = imgSrc.substr(pos);
}
return imgSrc;
}
My question is how can I use the return value from returŅ‚String method further in code?
Simply assign a variable to the result:
var result = returnString("someString");
Edit:
Just noticed: var imgSrc = document.getElementById(stringValue).value();, .value is not a method, it's a property, remove the ().
var imgSrc = document.getElementById(stringValue).value;
The button is obviously clicked only when the user decides to click it. Therefore, there is no way you can predict when to execute code that you want to run when the user click the button. Fortunately, as you've found out, javascript allows you to intercept the button click via the onclick event.
Which means, the only way to use the return value of returnString() is from inside the onclick handler.
Say for example you have a function that wants to use the result of returnString(). Lets call it doSomething() for this example. The first obvious way to use the return value of returnString() is simply:
$("div").
last().
append(
"<button id='ok' onClick =\"doSomething(returnString('imgFileUploadQwersergsd'))\">" +
"Ok" +
"</button>"
);
But my is that ugly. What with the multiple quoting hell and a string longer than the page width. Not to mention that if you want to do any additional processing with the result you'd end up having to maintain javascript code inside a string:
"<button id='ok' onClick =\"" +
"var x = returnString('imgFileUploadQwersergsd');" +
"if (x.match(somePattern)) {" +
" doSomething(x);" +
"}" +
"\">"
That's barely readable and is a syntax error waiting to happen. Just.. no.. don't do this.
Instead you can create the HTML in string form and let jQuery parse that for you and do javascript in javascript:
$("div").last().append("<button id='ok'>OK</button>");
$("#ok").click(function(){
// from previous example:
var x = returnString('imgFileUploadQwersergsd');
if (x.match(somePattern)) {
doSomething(x);
}
});
See, no more quoting hell and much easier to read and maintain.
But wait, what if you still want to return form that click function to use the result of doSomething()? What if, for example, you're trying to do something like this:
function forumImageUpload() {
// ...
var result;
$("#ok").click(function(){
var x = returnString('imgFileUploadQwersergsd');
if (x.match(somePattern)) {
result = doSomething(x);
}
});
doSomethingElse(result); // DOES NOT WORK!
}
This wouldn't work because when doSomethingElse is called the button have not been clicked yet. The solution is to move any and all code that need to use the result of returnString or doSomething to inside the event handler:
function forumImageUpload() {
// ...
$("#ok").click(function(){
var result;
var x = returnString('imgFileUploadQwersergsd');
if (x.match(somePattern)) {
result = doSomething(x);
doSomethingElse(result); // WORKS!
}
});
}
But wait, you say, what if you want forumImageUpload to return the value? Something like this maybe:
function forumImageUpload() {
// ...
$("#ok").click(function(){
var result;
var x = returnString('imgFileUploadQwersergsd');
if (x.match(somePattern)) {
result = doSomething(x);
return doSomethingElse(result); // WONT WORK
}
});
}
var y = forumImageUpload();
doYetAnotherThing(y); // DOES NOT WORK!
The way to handle a situation like this is to let forumImageUpload accept a callback and move all code that wants to use the result inside the callback:
function forumImageUpload(callback) {
// ...
$("#ok").click(function(){
var result;
var x = returnString('imgFileUploadQwersergsd');
if (x.match(somePattern)) {
result = doSomething(x);
result = doSomethingElse(result);
if (callback) {
callback(result); // execute a callback instead of returning
}
}
});
}
forumImageUpload(function(y){
// move code that needs to use the result in here:
doYetAnotherThing(y); // WORKS!
});
The above is basically how you handle asynchronous code which covers everything from onclick events to ajax calls to setTimeout. Get comfortable passing functions to functions in javascript. You'll be doing it a lot.
var imgSrc = document.getElementById(stringValue).value;

Javascript concatenate a function similar to how text can be added

In javscript we can do this
var text = "the original text";
text+=";Add this on";
If a library has a function already defined (e.g)
//In the js library
library.somefunction = function() {...};
Is there a way to add something on so that I can have two functions run?
var myfunction = function() {...};
Something like:
library.somefunction += myfunction
So that both myfunction() and the original library.somefunction() are both run?
You can use this kind of code (leave scope empty to use default scope):
var createSequence = function(originalFn, newFn, scope) {
if (!newFn) {
return originalFn;
}
else {
return function() {
var result = originalFn.apply(scope || this, arguments);
newFn.apply(scope || this, arguments);
return result;
};
}
}
Then:
var sequence = createSequence(library.somefunction, myFunction);
I think what you want to create is a Hook (function) - you want to call library.somefunction but add a bit of your own code to run before. If that's the case, you can make your myfunction either call or return the library function after it's done with your bit of code.
var myfunction = function() {
// your code
// ...
return library.somefunction();
}

Can I name a JavaScript function and execute it immediately?

I have quite a few of these:
function addEventsAndStuff() {
// bla bla
}
addEventsAndStuff();
function sendStuffToServer() {
// send stuff
// get HTML in response
// replace DOM
// add events:
addEventsAndStuff();
}
Re-adding the events is necessary because the DOM has changed, so previously attached events are gone. Since they have to be attached initially as well (duh), they're in a nice function to be DRY.
There's nothing wrong with this set up (or is there?), but can I smooth it a little bit? I'd like to create the addEventsAndStuff() function and immediately call it, so it doesn't look so amateuristic.
Both following respond with a syntax error:
function addEventsAndStuff() {
alert('oele');
}();
(function addEventsAndStuff() {
alert('oele');
})();
Any takers?
There's nothing wrong with the example you posted in your question.. The other way of doing it may look odd, but:
var addEventsAndStuff;
(addEventsAndStuff = function(){
// add events, and ... stuff
})();
There are two ways to define a function in JavaScript. A function declaration:
function foo(){ ... }
and a function expression, which is any way of defining a function other than the above:
var foo = function(){};
(function(){})();
var foo = {bar : function(){}};
...etc
function expressions can be named, but their name is not propagated to the containing scope. Meaning this code is valid:
(function foo(){
foo(); // recursion for some reason
}());
but this isn't:
(function foo(){
...
}());
foo(); // foo does not exist
So in order to name your function and immediately call it, you need to define a local variable, assign your function to it as an expression, then call it.
There is a good shorthand to this (not needing to declare any variables bar the assignment of the function):
var func = (function f(a) { console.log(a); return f; })('Blammo')
There's nothing wrong with this set up (or is there?), but can I smooth it a little bit?
Look at using event delegation instead. That's where you actually watch for the event on a container that doesn't go away, and then use event.target (or event.srcElement on IE) to figure out where the event actually occurred and handle it correctly.
That way, you only attach the handler(s) once, and they just keep working even when you swap out content.
Here's an example of event delegation without using any helper libs:
(function() {
var handlers = {};
if (document.body.addEventListener) {
document.body.addEventListener('click', handleBodyClick, false);
}
else if (document.body.attachEvent) {
document.body.attachEvent('onclick', handleBodyClick);
}
else {
document.body.onclick = handleBodyClick;
}
handlers.button1 = function() {
display("Button One clicked");
return false;
};
handlers.button2 = function() {
display("Button Two clicked");
return false;
};
handlers.outerDiv = function() {
display("Outer div clicked");
return false;
};
handlers.innerDiv1 = function() {
display("Inner div 1 clicked, not cancelling event");
};
handlers.innerDiv2 = function() {
display("Inner div 2 clicked, cancelling event");
return false;
};
function handleBodyClick(event) {
var target, handler;
event = event || window.event;
target = event.target || event.srcElement;
while (target && target !== this) {
if (target.id) {
handler = handlers[target.id];
if (handler) {
if (handler.call(this, event) === false) {
if (event.preventDefault) {
event.preventDefault();
}
return false;
}
}
}
else if (target.tagName === "P") {
display("You clicked the message '" + target.innerHTML + "'");
}
target = target.parentNode;
}
}
function display(msg) {
var p = document.createElement('p');
p.innerHTML = msg;
document.body.appendChild(p);
}
})();
Live example
Note how if you click the messages that get dynamically added to the page, your click gets registered and handled even though there's no code to hook events on the new paragraphs being added. Also note how your handlers are just entries in a map, and you have one handler on the document.body that does all the dispatching. Now, you probably root this in something more targeted than document.body, but you get the idea. Also, in the above we're basically dispatching by id, but you can do matching as complex or simple as you like.
Modern JavaScript libraries like jQuery, Prototype, YUI, Closure, or any of several others should offer event delegation features to smooth over browser differences and handle edge cases cleanly. jQuery certainly does, with both its live and delegate functions, which allow you to specify handlers using a full range of CSS3 selectors (and then some).
For example, here's the equivalent code using jQuery (except I'm sure jQuery handles edge cases the off-the-cuff raw version above doesn't):
(function($) {
$("#button1").live('click', function() {
display("Button One clicked");
return false;
});
$("#button2").live('click', function() {
display("Button Two clicked");
return false;
});
$("#outerDiv").live('click', function() {
display("Outer div clicked");
return false;
});
$("#innerDiv1").live('click', function() {
display("Inner div 1 clicked, not cancelling event");
});
$("#innerDiv2").live('click', function() {
display("Inner div 2 clicked, cancelling event");
return false;
});
$("p").live('click', function() {
display("You clicked the message '" + this.innerHTML + "'");
});
function display(msg) {
$("<p>").html(msg).appendTo(document.body);
}
})(jQuery);
Live copy
Your code contains a typo:
(function addEventsAndStuff() {
alert('oele');
)/*typo here, should be }*/)();
so
(function addEventsAndStuff() {
alert('oele');
})();
works. Cheers!
[edit] based on comment: and this should run and return the function in one go:
var addEventsAndStuff = (
function(){
var addeventsandstuff = function(){
alert('oele');
};
addeventsandstuff();
return addeventsandstuff;
}()
);
You might want to create a helper function like this:
function defineAndRun(name, func) {
window[name] = func;
func();
}
defineAndRun('addEventsAndStuff', function() {
alert('oele');
});
Even simpler with ES6:
var result = ((a, b) => `${a} ${b}`)('Hello','World')
// result = "Hello World"
var result2 = (a => a*2)(5)
// result2 = 10
var result3 = (concat_two = (a, b) => `${a} ${b}`)('Hello','World')
// result3 = "Hello World"
concat_two("My name", "is Foo")
// "My name is Foo"
If you want to create a function and execute immediately -
// this will create as well as execute the function a()
(a=function a() {alert("test");})();
// this will execute the function a() i.e. alert("test")
a();
Try to do like that:
var addEventsAndStuff = (function(){
var func = function(){
alert('ole!');
};
func();
return func;
})();
For my application I went for the easiest way. I just need to fire a function immediately when the page load and use it again also in several other code sections.
function doMyFunctionNow(){
//for example change the color of a div
}
var flag = true;
if(flag){
doMyFunctionNow();
}

Categories

Resources