retrieving data after right-click paste - javascript

I am trying to evaluate some data entered into a textarea after a paste has occurred. When I use onkeyup it detects if fine and does the evaluation okay when the user uses Cntl-V to paste. It does nothing when they right-click and select paste. I changed to onkeyup to onpaste which detects both the Cntl-V and Right-click paste but the data is not there. I know that the onpaste is triggered before the actual paste is performed so I tried to delay the evaluation with a setTimeout(), but even with a 5 second delay it never gets the data until after function function completes. No matter what I do I can't seem to get a count of the number of items that were entered. Here is my code:
function delayStart() {
alert("delayStart() function");
var inData = " ";
setTimeout(function()
{inData = document.getElementById("loanNumberPaste").value},
5000);
var iData = inData.value;
alert("iData = " + iData);
setTimeout(fnUpdCt(iData),5000);
}
function fnUpdCt(vId) {
var strVId = vId.value;
alert("fnUpdCt() function \n" +
"vId = " + strVId);
var i;
var iVal = vId.value;
var vCt = 0;
iVal = iVal.replace(/\s/g,' ');
iVal = iVal.split(' ');
for (i=0; i < iVal.length; i++) {
if (iVal[i].length > 0) {vCt++;}
}
document.getElementById("loanNumberCount").value = vCt;
}
<textarea id="loanNumberPaste" rows=17 cols=37 tabindex="1"
onpaste="delayStart();";onkeyup="fnUpdCt(this);"></textarea>
Any advise you can provide will be greatly appreciated.

The timeout isn't working because instead of passing the function by reference you're calling it immediately and trying to return its value.
Just wrap fnUpdCt in an anonymous function and it should be fine.
setTimeout(function(){fnUpdCt(iData)},5000);
Also, you don't need to wait 5 seconds - its not the fact that its waiting x amount of time, its the fact that its asynchronous.

Related

function outputting function text rather than expected output

I've asked similar questions a few different ways, but here's the simplest version of it - I am trying to increment through a list of keyname values when a function occurs. However, when the function is called, all I am getting is the text of the function itself. Here's a snippet -
var knlist = {
kn10:"2L1qvq6Tg6rMhEwNshr6dQ",
kn11:"2N_Cl_Gl5fX8_TdLgHP3rQ",
kn12:"2RbpjbhM3_EfzejfPgzwAw",
kn13:"2rP8y_ub_alGrzAK_aZrEg",
kn14:"2S8O9KBwxRlvtZX6kjyS0y",
kn15:"2Ua5EnPVDwd7LGq6UbT2bQ",
kn16:"3_17fNbyu2Yw8ozPx8BmkA",
kn17:"3LB0GSXXVadBlCMhSth3IA",
kn18:"48JvNwKSgvnWT8nqzWtE3Q",
kn19:"4CP5JE_mlMMzjvDMMgXncg",
}
var count = 11
var knx = function knxer(){
if (count === 11) {
knx = "kn11";
} else {
knx = ("kn" + count);
}};
var keyname = (knlist[knx]);
console.log (count)
console.log (knx)
console.log (keyname)
Console.log KNX is only giving me the text of the function knxer() itself rather than the expected values the function should return as the count increases.
Once this is solved, I'm going to be having another function increase the count within a different location - here's a full JSFiddle of where that is at. Once thats done I'm going to add an input for the login page so that username has a value that can be imputed the first time someone attempts the survey, and posts each completion over and over.
The problem is that you assign knix to your function
var knlist = {
kn10:"2L1qvq6Tg6rMhEwNshr6dQ",
kn11:"2N_Cl_Gl5fX8_TdLgHP3rQ",
kn12:"2RbpjbhM3_EfzejfPgzwAw",
kn13:"2rP8y_ub_alGrzAK_aZrEg",
kn14:"2S8O9KBwxRlvtZX6kjyS0y",
kn15:"2Ua5EnPVDwd7LGq6UbT2bQ",
kn16:"3_17fNbyu2Yw8ozPx8BmkA",
kn17:"3LB0GSXXVadBlCMhSth3IA",
kn18:"48JvNwKSgvnWT8nqzWtE3Q",
kn19:"4CP5JE_mlMMzjvDMMgXncg",
}
var count = 11
var knx;
function knxer(){
if (count === 11) {
knx = "kn11";
} else {
knx = ("kn" + count++); // update the count each time it calls
}};
knxer(); // call it
var keyname = (knlist[knx]);
console.log (count)
console.log (knx)
console.log (keyname)
you have to call the function ,
you are just mentioning function name in console.log() ,
This will call the function and will return the value console.log(knx())
This will NOT call the function instead,It will return the function body console.log(knx)

How do I get the text() from a function to use in another function?

I'm trying to turn an option from a select list into text to then use the text in a function that returns a message topic for Firebase. I have had to use a function to get the text out of the list correctly but I don't know how to then output the text from the function in the second function to be used for the messaging. I can console.log the text, but I don't know what to use to just output the text itself inside the message function. I may be confusing myself a little. Please note: There are const being declared that are being used later on so any comment of "Why are you declaring those consts" won't be helpful. I need to know what to put in the TWO ### WHAT GOES HERE ### blocks to make this work?
I have tried just using jquery's text() to simply output the data I want but that just brings back undefined every time. The only way I've been able to actually get the option text is to place it in a function, but I have to actually DO something with it and I'm not sure what function will give me my desired results.
Here is the code
const select = $("#schoolSelect");
selectedOption = function() {
### WHAT GOES HERE? ###($("#schoolSelect option:selected").text())
}
const stage2 = $("#stage2Div");
const stage3 = $("#stage3Div");
const popupClose = $("#popupClose");
const popup = $("#popup");
const selectedValues = getSelectValues(select);
// Alert Buttons Functions
// Stage 2 Button
// Sends Soft Lockdown to all devices subscribed
stage2.click(function() {
var select = $("#schoolSelect"),
selectedValues = getSelectValues(select);
if (selectedValues.length == 0) {
popup.addClass("show");
}
else if (selectedValues.length > 0) {
for (var i = 0; i < selectedValues.length; i++) {
var message = createSLMessage(
"/topics/" + ### WHAT GOES HERE? ###
)
sendMessage(message);
}
}
});
For reference, here is the jQuery that is creating the list
populateList = function() {
$.getJSON("/assets/JSON/schools.JSON", function(result) {
$.each(result, function(i){
var schools = result.schools;
var output = "";
for (var i = 0; i < schools.length; i++) {
output += "<option>" + schools[i].topic + "</option>";
}
$("#schoolSelect").html(output);
});
})
};
Here is the html of the table (though less important) for reference
<select
size="100"
multiple
id="schoolSelect"
class="school_select"
></select>
I would like the function selectedOption to actually output the text. If I place console.log where the ### WHAT GOES HERE ### tag is in the function selectedOption itself and then call the selectedOption() later, the console indeed logs the correct value from the select list. I am losing my mind a little because I know there has to be some simple way to do this I just can't seem to figure it out.

Several setTimeout() functions [duplicate]

I'm trying to send emails with a 10 seconds delay between. I wrote this code:
$(document).ready(function() {
for (i = 0; i < 20; i++) {
setTimeout("SendEmail(" + i + ")", 5000);
}
});
function SendEmail(id) {
$.get("mimesender.php?id=" + id, function(data) {
var toAppend = "<span> " + data + "</span>"
$("#sentTo").append(toAppend);
});
}
server side code(php) gets the id and selects the email with the specified id from the database
$query="select email from clienti where id =".$id;
then sends the email, and sends back the current email
echo email;
However, something is wrong here. It seems like the the js function waits for 5 seconds, and then displays all the 20 email addresses at once.
Can you tell me what I'm doing wrong ? any "sleep "workaround will be greatly appreciated :)
Use interval instead of loop.
Working demo: http://jsfiddle.net/xfVa9/2/
$(document).ready(function() {
var tmr;
var i=0;
tmr=setInterval(function(){
if(i<20){
SendEmail(i);
alert("Sent "+i)
i++;
}else{
clearInterval(tmr);
}
},5000)
});
You should create a function which calls itself after 5 seconds
var i=0;
function sendEmailNow() {
SendEmail(i);
++i;
if(i<20) {
setTimeout(sendEmailNow, 5000);
}
}
What happens is that you call setTimeout 20 times, just after one another, with a timeout of 5 seconds. So naturally, all emails gets sent at once. You could change the loop to look like this:
for (i=0;i<20;i++) {
setTimeout("SendEmail("+ i + ")",(i+1)*5000);
}
There's alot of other options though, and they'd depend on just what suits your specific problem best.
First, pass a function to setTimeout.
Secondly, you'd be better off if you set the timeout for the next one in the queue after the current one is finished.
In the for loop:
sendEmail(0); // start sending first
and in the callback:
, function(data) {
if(id < 19) { // if next should be sent
setTimeout(function() {
SendEmail(id + 1);
}, 5000);
}
var toAppend = "<span> " + data + "</span>"
$("#sentTo").append(toAppend);
}
Your loop is setting up 20 timers to wait 5 seconds, then letting them all go at once.
Try something like this:
var email_count = 20;
var sendMails = function(){
SendEmail(email_count--);
if(email_count > 0){
setTimeout(sendMails, 5000);
}
}
setTimeout(sendMails, 5000)
Avoid jQuery. Learn JavaScript.
var i = 0; (otherwise leak into outer scope or runtime error)
Extra closure:
window.setTimeout(
(function (j) {
return function () {
sendEmail(j);
};
}(i)),
i * 10000);
sendEmail (code style: not a constructor)
You really want to escape $id in the server-side code to prevent SQL injection.

execCommand('copy') not working programatically, only when executed via DevTools console

Source:
const package = document.querySelector('td[data-bind="text: packageName"');
if (package.textContent.indexOf('Adaptive') !== -1) {
package.click();
const stacks_tab = document.querySelector('ul[class="tabsExpanded"]').children[5];
stacks_tab.click();
function get_sources() {
const sources = [];
const stacks = document.querySelectorAll('span[data-bind="text:duration"]');
for (let i = 0; i < stacks.length; i++) {
stacks[i].click();
let renditions = document.querySelectorAll('span[class="blockUnSelected"]');
renditions[(i+1) * 8 - 1].click();
sources.push(document.querySelectorAll('p[data-bind="text: $data.name"]')[0].textContent);
}
let copy = '';
for (let i = 0; i < sources.length; i++) {
const change_brackets = sources[i].replace(/\/tveorigin\/vod\/ae\//, '');
const no_pd1 = change_brackets.replace(/-pd1/g, '');
copy += no_pd1 + ',';
}
if (copy === '') {
setTimeout(get_sources, 500);
} else {
const hidden = document.createElement('input');
hidden.value = copy;
document.querySelector('body').appendChild(hidden);
hidden.select();
function copy_sources() {
console.log('running');
hidden.select();
if (!document.execCommand('copy')) {
setTimeout(copy_sources, 500);
} else {
console.log('Sources copied!');
}
}
copy_sources();
}
}
get_sources();
} else {
console.log('There is no Adaptive package in this content.');
}
Line 45 is what isn't working.
That code won't make a lot of sense, but here's the use case:
I'm trying to automate part of my job by injecting some JavaScript into the Chrome DevTools console on our CMS that we use for video content where I work. What the script does is click a few elements, then grabs some file locations and copies them to the clipboard as comma separated values. I had this working just fine before, but I decided to try and make the script better...and now the document.execCommand('copy') is just not working.
As you can see, I use some recursion to continuously select the hidden input value and then I try to copy it, and if it fails, I try again in 500 ms. I also log 'running' to ensure the function is actually running (it is). The execCommand() function keeps returning false every 500ms. BUT, if I type it into the console manually and run it, it returns true and works fine even as the recursive function continues to return false. So for some reason, it won't work in the context of my script, but works totally fine when run manually.
Like I said before, it WAS working programatically before, but I changed some stuff to make the script better and more automated, and it won't work anymore. Here's the code with execCommand() working fine:
const sources = [];
const stacks = document.querySelectorAll('span[data-bind="text:duration"]');
for (let i = 0; i < stacks.length; i++) {
stacks[i].click();
let renditions = document.querySelectorAll('span[class="blockUnSelected"]');
renditions[(i+1) * 8 - 1].click();
sources.push(document.querySelectorAll('p[data-bind="text: $data.name"]')[0].textContent);
}
let copy = '';
for (let i = 0; i < sources.length; i++) {
const change_brackets = sources[i].replace(/\/tveorigin\/vod\/ae\//, '');
const no_pd1 = change_brackets.replace(/-pd1/g, '');
copy += no_pd1 + ',';
}
const hidden = document.createElement('input');
hidden.value = copy;
document.querySelector('body').appendChild(hidden);
hidden.select();
document.execCommand('copy');
I just tested that code and it still works, and copies the text to the clipboard as intended. The only notable different I see is that in the older code, I run execCommand() in the global context, whereas in the new script, it's in a function context. Could this have something to do with it?
So the solution to this was odd. execCommand() can only be triggered by a user event handler, so what I had to do was attach a click listener to the window, then invoke a click event on the hidden node. Because that triggered a click handler, that made it work!

Javascript - Run functions in order (not at same time)

I have a webpage the currently types text# (automated with code below) into a text box ta#.
Problem #1) When I run the function, I can only figure out how to make it type into all textboxes at the same time. -- I want it to type naturally (1 by 1, with a slight delay between each) into each textbox. How can I accomplish this?
Problem #2) What is the proper way to shut off/clear this automated typing once the user clicks/selects a text box?
var text1 = "Type this into textbox usr";
var text2 = "Type this into textbox usr2";
var ta1 = document.getElementById("usr");
var ta2 = document.getElementById("usr2");
function type(string,element){
(function writer(i){
if(string.length <= i++){
element.value = string;
return;
}
element.value = string.substring(0,i);
if( element.value[element.value.length-1] != " " )element.focus();
var rand = Math.floor(Math.random() * (100)) + 140;
setTimeout(function(){writer(i);},rand);
})(0)
}
type(text1,ta1);
type(text2,ta2); // This doesnt work right.
setTimeout makes this inherently asynchronous so the Promise object is your friend. Note that the following code will work in all modern browsers. And that excludes Internet Explorer :).
Here we make type return a Promise that will be resolved when the typing has completed. I've modified your code slightly such that writer returns false when the typing is complete, and if it has, then the code will resolve the Promise, and stop running the timeout. There are a few ways of doing this, but this is what I had time for...
I've also added quick-and-dirty code that will stop the typing when you click into a textbox. However, note that it stops all typing for both textboxes. You can play around with the code to get it to keep going to the second textbox if that's what you want.
var text1 = "Type this into textbox usr";
var text2 = "Type this into textbox usr2";
var ta1 = document.getElementById("usr");
var ta2 = document.getElementById("usr2");
function type(string, element) {
var timeout;
element.addEventListener('click', function() {
if (timeout) {
clearTimeout(timeout);
}
});
var completePromise = new Promise(function(resolve, reject) {
(function writer(i) {
if (string.length <= i++) {
element.value = string;
return false;
}
element.value = string.substring(0, i);
if (element.value[element.value.length - 1] != " ") {
element.focus();
}
var rand = Math.floor(Math.random() * (100)) + 140;
timeout = setTimeout(function() {
if (!writer(i)) {
resolve();
clearTimeout(timeout);
}
}, rand);
return true;
})(0);
});
return completePromise;
}
type(text1, ta1).then(function() {
type(text2, ta2);
});
<input id="usr" type="text" />
<input id="usr2" type="text" />

Categories

Resources