return value from onClick - javascript

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;

Related

Protractor - Issue in using one function value from another function

Hi I am new to protractor, I have below two functions, the first function is returning a promise, which I want to use in 2nd function to retrieve value from it and use it.
getColumnNumber(columnName) {
this.eh.waitForElement(this.GridsEleMap.get("HeaderTableHeaderRow"));
var colEle = this.GridsEleMap.get("HeaderTableHeaderRow").all(by.xpath(".//td//div[contains(#class,'text-content')]"));
return colEle.getText().then(function (text) {
var actIndex = text.indexOf(columnName) + 1;
logger.info("Column Index:" + actIndex);
});
}
clickRowElementUsingRowTextAndColumnName(rowText, columnName) {
var ele = this.GridsEleMap.get("BodyTable");
return this.getColumnNumber(columnName).then(function (result) {
logger.info("Text:" + result);
var cellEle = ele.all(by.xpath(".//tr//td[" + result + "]//div[#class='virtualLink']"));
logger.info("Result:" + cellEle);
return cellEle.filter(function (elem) {
browser.actions().mouseMove(elem).perform();
browser.sleep(50);
return elem.getText().then(function (text) {
return text.trim() === rowText.trim();
});
}).each(function (element) {
browser.actions().mouseMove(element).perform();
element.click();
browser.sleep(10*1000);
});
});
Whenever I am trying to use "result" object of then function applied on first function in clickRowElementUsingRowTextAndColumnName, its value is coming as undefined. Please help me with it.
I have to pass this result value to form a xpath of particular column index and perform operation on it.
You should return properly the value from the first function.
You can try the following code for example:
getColumnNumber(columnName) {
...
return colEle.getText().then(function (text) {
return text.indexOf(columnName) + 1;
});
}
If you see, it returns the actIndex.
Pay also attention that you have few code not chained properly, all protractor methods return promises which need to be chained in order to be sure to keep the flow sync.
Then, just as suggestion, try to avoid the use of xpath locators.
They are unreadable and they bring to a decrease of performances.

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.";
}
});

Understanding how javascript works when a parent function returns an inner function

I have an inner_function inside a parent_function.
I think I understand how this works: http://jsfiddle.net/93pp5/
var text = 'Look at me';
function parent_function() {
function inner_function() {
var scream = '!!!';
alert(text);
}
inner_function();
};
parent_function();
However, I'm trying to figure out why my javascript below does not work. Can parent_function() not return inner_function()? My expectation was that calling parent_function() at the bottom would bring up an alert, but it does not: http://jsfiddle.net/93pp5/1/
var text = 'Look at me';
function parent_function() {
return function inner_function() {
var scream = '!!!';
alert(text);
}
};
parent_function();
Thats because parent_function returns a function which still needs to be called (executed).
var runAlert = parent_function();
// runAlert now holds the returned function but it still needs to be called to get the alert
runAlert(); // will alert

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();
}

How to make function like confirm

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()
})
})
}

Categories

Resources