I'm trying to write a function that will auto suggest what the user means when they type into an input field. Right now I have all of the auto suggest code complete but in my javascript I can't get to the first if in toggleGenusInput no matter what I do (this first if queries the database through php and gets the suggestions).
Does anyone know how I could modify my code so that if something is typed in the input field and is not changed after 2 seconds it will enter that first if? Thanks.
Here are my script globals:
var time = new Date();
var timeout = 2000; //query db every 2 seconds of not typing anything
var autoSuggest = true;
var lastQueryTyped = "";
var queryTypedAt = time.getTime(); //what time the last new text was entered
Here's the function that's connected to an input node's onfocus method:
function toggleGenusInput(inputNode) {
if(autoSuggest) {
if((time.getTime() - queryTypedAt) >= timeout && inputNode.value == lastQueryTyped) {
//the input has not changed and it's reached the timeout time, requery the db
responseDoc = getXMLFrom("getsimilaritems.php?query=" + inputNode.value);
if(queryFindsSuggestions(responseDoc)) {
cleanUpSuggestions();
appendSuggestions(inputNode, responseDoc);
}
}
else if(inputNode.value != lastQueryTyped) {
//something new was entered so update the time and what was put in
lastQueryTyped = inputNode.value;
queryTypedAt = time.getTime();
}
}
}
And here's the html object that function is attached to:
<input type="text" name="autoSuggestInput" onfocus="toggleGenusInput(document.myForm.autoSuggestInput)" />
You could use setTimeout and bind the handler to the keyup event instead:
function toggleGenusInput(inputNode) {
if(autoSuggest) {
if(_timeout) {
clearTimeout(_timeout);
}
_timeout = setTimeout(function() {
//the input has not changed and it's reached the timeout time, requery the db
responseDoc = getXMLFrom("getsimilaritems.php?query=" + inputNode.value);
if(queryFindsSuggestions(responseDoc)) {
cleanUpSuggestions();
appendSuggestions(inputNode, responseDoc);
}
}, 2000);
}
}
and
<input type="text" name="autoSuggestInput" onkeyup="toggleGenusInput(document.myForm.autoSuggestInput)" />
Now whenever a key is pressed (not on focus), your function will be called and wait a certain time to execute the functionality. If another timeout is running, it will be canceled first (otherwise you would keep creating timeouts over and over again while the user inserts text which would lead to strange results).
Related
I have in my VUE application a text type input in which I collect a data and when I finish collecting it I must show another component.
<input
type="text"
v-model="textFormInfo.text"
#keypress="onChangeText($event)"
/>
<div class="loader-spinner" v-if="loading">
<app-loader ref="spinner"/>
</div>
and this is the method in which I control the interaction. I'm detecting through the keypress when they start typing in the input and when there is .length I launch a settimeout to give time for them to type and display a loader and load the next component.
export default {
data() {
return {
myTimeout: null
};
},
onChangeName(event) {
if (event.target._value.length > 0) {
this.loading = true;
this.myTimeout = setTimeout(() => (
this.isNameCompleted = true,
this.loading = false,
this.isLoaderFinished = true,
this.$refs.scrolled_3.focus()), 2200);
}
}
the problem is that if you type slowly or the information is too long the next component is displayed before you have finished typing.
I'm trying to make sure that every time I receive the keypress ecent I reset the settimeout so that the total settimeout value is applied only when I stop receiving the keypress.
I have tried to follow examples in which is used the clearTimeout method but I do not see how to implement it in this case.
How can I get this? Any idea.
greetings and thanks in advance for your time and help
i think what you are trying to achieve here is debouncing if i'm correct you can do it like this for every kry press we create a timeout and if the key not pressed for certain time the method in settimeout will be called
var timeoutId = 0;
function keypress() {
if (timeoutId >= 0) {
clearTimeout(timeoutId);
}
timeoutId = window.setTimeout(() => {
callMethod();
}, 500);// time to wait to listen for next keypress if not pressed callMethod will execute
}
Essentially what I need is to run some JavaScript after a record has been saved. This will pick up a guid from a field which has been populated by a plugin. My code looks like;
Xrm.Page.data.entity.save();
var newguid = Xrm.Page.getAttribute("new_copyguid").getValue();
Xrm.Utility.openEntityForm("new_myentity", newguid);
The problem is the code runs past the call to save() and continues executing before a plugin has populated the "new_copyguid" field. Is there a way to wait for the plugin to complete before continuing with the javascript? I have tried AddOnSave() without success. Any javascript callback seems to execute before the plugin finishes as well. The plugin is set to run synchronously.
I am performing this javascript from a button on the form. The button sets a field value and then saves the record, triggering the plugin. The button is a "Copy Entity" button which creates a clone. I need to open this new record in the browser.
I have read that this does not work either, as it happens before the save;
Xrm.Page.data.refresh(save).then(successCallback, errorCallback);
Any pointers would be great!
I think you'll have to run your logic in the OnLoad section. The save should force a refresh and your onload logic will run again. You'll need to do some check to see if the modified on date is within a certain time frame.
Other option is you perform the update manually through a rest call or Soap call, then you can read the value from the plugin in another call.
You can just wait for some seconds by putting this code.
function YourFunction()
{
Xrm.Page.data.entity.save();
OpenForm();
}
Its a new function.
function OpenForm()
{
setTimeout(function () {
var newguid = Xrm.Page.getAttribute("new_copyguid").getValue();
Xrm.Utility.openEntityForm("new_myentity", newguid);
}, 3000);
}
Try this:
function onPageLoad() {
var formType = Xrm.Page.ui.getFormType();
if (formType == 0 || formType == 1) { // 0 = Undefined, 1 = Create
// If form is in Create Mode then
if (Xrm.Page.data != null && Xrm.Page.data.entity != null) {
Xrm.Page.data.entity.addOnSave(onSaveDoThis);
}
}
}
function onSaveDoThis() {
setTimeout(onFormSaveSuccess, 300);
}
function onFormSaveSuccess() {
var newguid = Xrm.Page.getAttribute("new_copyguid").getValue();
if (newguid == "") {
onSaveDoThis();
} else {
// Don't need to trigger the function onSaveDoThis anymore
Xrm.Page.data.entity.removeOnSave(onSaveDoThis);
Xrm.Utility.openEntityForm("new_myentity", newguid);
}
}
Try this:
function OpenForm()
{
setTimeout(function () {
var newguid = Xrm.Page.getAttribute("new_copyguid").getValue();
Xrm.Utility.openEntityForm("new_myentity", newguid);
}, 3000);
}
In an experiment I'm coding, on every trial, I need to display a stimulus (search array) and then wait for a maximum of 5 seconds for the subject to respond with a keypress. If a key is pressed, the next trial begins immediately or else after 5 seconds.
I just want to know if I can code up something like this in JavaScript, and if so, how should I code up the experiment? Also, I should be able to store the identity and timestamp of the key pressed.
The flow of your experiment, as I understood them, are this:
Show Stimulus
Check for keypresses repeatedly
If 5 seconds have passed, show next stimulus
If key was pressed, store keypress in array, then show next stimulus.
To do this, I would use Keypress, a JS library for catching input.
You would first want to define your stimuli
E.g.:
var stimuli = ["Apple","Orange","Keira Knightley","Banana"];
You would then want to set up your event listeners. These will log your keypresses for you.
var listener = new window.keypress.Listener();
var results = [];
listener.simple_combo("shift s", function() {
results.push("You pressed shift and s");
});
Then you want to set up the timing system. I would use a setInterval() function to increment the position in the array that the subject is in.
var pos = -1; //Arrays start at 0, and you want to run this function to start.
function nextStim() {
pos = pos + 1;
myDiv.innerHTML = stimuli[pos]
}
var results = [];
listener.simple_combo("shift s", function() {
results.push("The stimulus was: " + stimuli[pos] + "And you pressed Shift + S" );
});
setInterval(nextStim,5000);
<script>
var timeout;
timeout = setTimeout(next, 5000); //execute function "next" after 5000 miliseconds
//With jQuery
//$("#element").on("keypress", function(){ clearTimeout(timeout); next();} );
//Without jQuery
function elementOnKeypress()
{
clearTimeout(timeout); //don't execute "next" after 5000 (or less) ms
next(); //run "next"
}
function next()
{
//your code ..
}
</script>
<element onkeypress="elementOnKeypress();"></element><!-- element is your html-element to be keypressed -->
i have a simple question, there is a function with parameter emp_id that opens up a form for a chat with different attributes, i want it to be refreshed automatically each 10 sec, now it works a bit wrongly, since there is a parameter emp_id that is can be changed, and once i change it, the chat with messages and form are refreshed double time or triple times :) depend on how many times u change the emp_id, i hope i was clear )) anyway here is the javascript function:
function load_chat(emp_id) {
var url = "#request.self#?fuseaction=objects2.popup_list_chatform"
url = url + "&employee_id=" + emp_id;
document.getElementById('form_div').style.display = 'block'; AjaxPageLoad(url,'form_div',1,'Yükleniyor');
setInterval( function() {
load_chat(emp_id);
},10000);
}
there a list of names, once i click on one of them, this form is opened by this function, but if i click another user, i mean if i change the emp_id, it refreshes, the previous and present form. how do i change it so that it will refresh only the last emp_id, but not all of id's which i've changed
thank you all for the help, i really appreciate it!
This would nicely encapsulate what you're doing. The timer id (tid) is kept inside the closure, so when you call load_chat it will stop the interval if there was one running.
Once the new url is set up, it will start the interval timer again.
var ChatModule = (function() {
var tid,
url;
function refresh()
{
AjaxPageLoad(url, 'form_div', 1, 'Yükleniyor');
}
return {
load_chat: function(emp_id) {
if (tid) {
clearInterval(tid);
}
// setup url
url = "#request.self#?fuseaction=objects2.popup_list_chatform"
url = url + "&employee_id=" + emp_id;
document.getElementById('form_div').style.display = 'block';
// load ajax
refresh();
// set timer
tid = setInterval(refresh, 10000);
}
}
}());
ChatModule.load_chat(123);
Use setTimeout instead. Each time your function is executed, it will set up the next execution (you could also make it conditional):
function load_chat(emp_id) {
... // do something
if (condition_still_met)
setTimeout(function() {
load_chat(emp_id); // with same id
}, 10000);
}
load_chat("x"); // to start
Or you will have to use setInterval outside the load_chat function. You can clear the interval when necessary.
function get_chat_loader(emp_id) {
return function() {
... // do something
};
}
var id = setInterval(get_chat_loader("x"), 10000); // start
// then, somewhen later:
clearInterval(id);
I'm still kindof new to jQuery, so there probably is an easy solution, but I can't find anything.
I've made this registration form, that checks if the username or email is taken as the user is typing in the username. Basically it just makes a json request that returns true or false depending on if the username / email is already taken.
The problem is, that now it makes a request on basically every keypress that the user makes while focused on the field if the input text is more than 3 characters long. For now, that works, but that's a lot of server requests. I'd like it to make a request only when the user has not typed for, say, a half second.
Any ideas on how I might be able to do that ?
$(document).ready(function() {
$("#user_username").keyup(function () {
var ln = $(this).val().length;
if (ln > 3) {
$.getJSON("/validate/username/",
{value:$(this).val()},
function(data){
if (data.reg == true) {
$("#status-for-username").html("Username already in use");
} else {
$("#status-for-username").html("Username available");
}
});
}
});
$("#user_email").keyup(function () {
var ln = $(this).val().length;
if (ln > 3) {
$.getJSON("/validate/email/",
{value:$(this).val()},
function(data){
if (data.reg == true) {
$("#status-for-email").html("E-mail already in use");
} else {
$("#status-for-email").html("");
}
});
}
});
});
For waiting an amount of time since the last keystroke, you could do something like the jQuery.typeWatch plugin does.
Here I post you a light implementation of the concept:
Usage:
$("#user_username").keyup(function () {
typewatch(function () {
// executed only 500 ms after the last keyup event.
}, 500);
Implementation:
var typewatch = function(){
var timer = 0; // store the timer id
return function(callback, ms){
clearTimeout (timer); // if the function is called before the timeout
timer = setTimeout(callback, ms); // clear the timer and start it over
}
}();
StackOverflow uses the plugin I mention, for syntax coloring the code on edition.
You can use window.setTimeout and window.clearTimeout. Basically trigger a function to invoke in x milliseconds and if another keypress event is fired beforehand then you clear that handler and start a new one.
//timeout var
var timer;
$('#username').keyUp( function(){
//clear any existing timer
window.clearTimeout( timer );
//invoke check password function in 0.5 seconds
timer = window.setTimeout( checkPasswordFunc, 500 );
});
function checkPasswordFunc(){
//ajax call goes here
}