Auto-complete with CodeMirrror - javascript

I am trying to implement auto-complete using CodeMirror show-hint addon, specifically with sql-hint. I want it auto-complete as I type.
What I am doing right now is,
codemirror_editor.on("change", function(instance) {
CodeMirror.commands.autocomplete(instance);
});
But the problem is, it completes words before I even type a single letter for a word. For example after space, it gives a long list of all possible tokens. I want it to show up only if some characters are typed. Can someone please help with that?

Before firing the autocomplete command, check whether the cursor is actually after 'some' (whatever 'some' means) letter characters. Also, do nothing when instance.state.completionActive is true, since that means there's already a completion popup open. Finally, you probably want to listen for the "inputRead" event instead of "change", so that you don't trigger when a change is made to the document in a way that didn't involve the user typing.

This is how I solved this, after Marijn's answer.
codemirror_editor.on("inputRead", function(instance) {
if (instance.state.completionActive) {
return;
}
var cur = instance.getCursor();
var token = instance.getTokenAt(cur);
var string = '';
if (token.string.match(/^[.`\w#]\w*$/)) {
string = token.string;
}
if (string.length > 0) {
CodeMirror.commands.autocomplete(instance);
}
});
This may be specific to SQL.
I am answering my own question to share the actual solution for the question.

Related

Creating a custom command as an alternative to setValue() where I can control the type speed

Hope someone can help with this. I have come across an issue with the application im testing. The developers are using vue.js library and there are a couple of fields which reformat the entered test. So for example if you enter phone number, the field will automatically enter the spaces and hyphens where its needed. This is also the same with the date of birth field where it automatically enters the slashes if the user does not.
So the issue I have is that using both 'setValue()' or 'sendKeys()' are entering the text too fast and the cursor in the field sometimes cannot keep up and the text entered sometimes appears in the incorrect order. For example, if I try to enter '123456789'. Some times it ends up as '132456798' (or any other combination). This cannot be produced manually and sometimes the test does pass. But its flakey.
What I wanted to do was to write a custom command to do something where it enters the string but in a slower manner. For this I need to have control of how fast I want the text to be entered. So I was thinking of something like this where I can pass in a selector and the text and then it will enter one character at a time with a 200 millisecond pause in between each character. Something like this:
let i = 0;
const speed = 200; // type speed in milliseconds
exports.command = function customSetValue(selector, txt) {
console.log(selector);
console.log(txt);
if (i < txt.length) {
this.execute(function () {
document.getElementsByName(selector).innerHTML += txt.charAt(i);
i++;
setTimeout(customSetValue, speed);
}, [selector, txt]);
}
return this;
};
When running document.getElementsByName(selector) in browser console I get a match on the required element. But it is not entering any text. Also note that I added a console.log in there and I was actually expecting this to log out 14 times but it only logged once. So itss as if my if condition is false
I checked my if condition and it should be true. So not sure why its not reiterating the function. Any help is much appreciated.
Also if it helps. I am using the .execute() command to inject javascript which is referenced here: https://nightwatchjs.org/api/execute.html
And the idea on this type writer is based on this: https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_typewriter
We ended up taking a different approach much simpler. Wanted to post here in case anyone else ever needs something similar
exports.command = function customSetValue(selector, txt) {
txt.split('').forEach(char => {
this.setValue(selector, char);
this.pause(200); // type speed in milliseconds
});
return this;
};

How to Simulate Typing in an Input Box with Javascript?

What I am trying to do is make the input box think that I am typing numbers into it rather than changing the value of said input. So the first thing I did was make the input box a variable:
var input = document.querySelectorAll("input")[1];
Then what I did was focus the input box to make it seem like I had clicked in it with my mouse:
input.select();
This is the part that I am now stuck on. What I would like to do is make the input box think that I typed a number into it, say, 41. If anyone could please tell me what code I need to put into console to make the input box think I typed in "41", it would be greatly appreciated. Thank you.
You can use setTimeout and add one character each time like this :
var input = document.querySelectorAll("input")[1];
input.select(); // you can also use input.focus()
input.value="";
var text = "41";
var l=text.length;
var current = 0;
var time = 1000;
var write_text = function() {
input.value+=text[current];
if(current < l-1) {
current++;
setTimeout(function(){write_text()},time);
} else {
input.setAttribute('value',input.value);
}
}
setTimeout(function(){write_text()},time);
<input type="text">
<input type="text">
This will work with any content you want to write, you simply need to adjust the variable with what you need.
I know this was really really long ago, but I'm currently working on a very similar problem and encountering the exact same issues that the original poster was encountering, and I found this code snippet (credit):
element.dispatchEvent(new KeyboardEvent("keydown", {
key: "e",
keyCode: 69, // example values.
code: "KeyE", // put everything you need in this object.
which: 69,
shiftKey: false, // you don't need to include values
ctrlKey: false, // if you aren't going to use them.
metaKey: false // these are here for example's sake.
}));
And the specific key codes you need can be found here.
This is definitely an extremely overcomplicated way of doing things, you'd need something to translate whatever input string you have into a list of instances of KeyboardEvent, and then dispatch them one by one, but as far as I can tell this is the proper way to truly "simulate" keyboard input.

var dataString = \'search=\'+ searchid; - jquery

I'm new to jQuery and I am trying to understand a bit of code to be able to apply a similar concept in my coursework.
$(function(){
$(".search").keyup(function() {
var searchid = $(this).val();
var dataString = \'search=\'+ searchid;
if(searchid!=\'\') {
}
});
})(jQuery);
What is the dataString variable trying to do?
There are quite a few things that seem "off" with this snippet of code, which I'll address below.
What is this code doing?
It looks like some basic functionality that might be used to build a search querystring that is passed onto some AJAX request that will search for something on the server.
Basically, you'll want to build a string that looks like search={your-search-term}, which when posted to the server, the search term {your-search-term} can be easily identified and used to search.
Noted Code Issues
As mentioned, there are a few issues that you might want to consider changing:
The Use of Escaped Quotes (i.e. \') - You really don't need to escape these as they aren't present within an existing string. Since you are just building a string, simply replace them with a normal ' instead. Without knowing more about your complete scenario, it's difficult to advise further on this.
Checking String Length - Your existing code once again checks if the searchId is an empty string, however you may want to consider checking the length to see if it actually empty via searchId.length != 0, you could also trim this as well (i.e. searchId.trim().length != 0).
Consider A Delay (Optional) - At present, your current code will be executed every time a key is pressed, which can be good (or bad) depending on your needs. If you are going to be hitting the server, you may consider adding a delay to your code to ensure the user has stopped typing before hitting the server.
You can see some of these changes implemented below in the annotated code snippet:
// This is a startup function that will execute when everything is loaded
$(function () {
// When a keyup event is triggered in your "search" element...
$(".search").keyup(function () {
// Grab the contents of the search box
var searchId = $(this).val();
// Build a data string (i.e. string=searchTerm), you didn't previously need the
// escaping slashes
var dataString = 'search=' + searchId;
// Now check if actually have a search term (you may prefer to check the length
// to ensure it is actually empty)
if(searchId.length != 0) {
// There is a search, so do something here
}
}
}

How do you compare JavaScript innerHTML return values, when there's a special character involved?

I have a web page with a form on it. The "submit" button is supposed to remain deactivated until the user fills in all the necessary fields. When they fill in a field, a checkmark appears next to it. When all the checkmarks are there, we're good to go.
A checkmark might be set by code like this:
if (whatever) checkLocation.innerHTML = CHECKMARK;
Here's the code I'm using to do the final check. It just loops through all the locations where there may be checkmarks. If it finds a location without a mark, it disables the submit button and leaves. If it gets through them all, it activates the button and returns true.
function checkSubmitButton() {
var button = document.getElementById(SUBMIT_BUTTON);
for (var i=0; i<CHECK_LOCATIONS.length; i++) { // should be for-each, but JS support is wonky
var element = document.getElementById(CHECK_LOCATIONS[i]);
console.log(CHECK_LOCATIONS[i] +": " +element.innerHTML);
// if found unchecked box, deactivate & leave
if (element.innerHTML != CHECKMARK) {
button.disabled = true;
return false;
}
}
// all true--activate!
console.log("ACTIVATING BUTTON!");
button.disabled = false;
return true;
}
Here's the problem: this works so long as the const CHECKMARK contains something simple, like "X". But specs call for a special HTML character to be used: in this case ✓, or ✓. When I do the comparison (in the if line) it ends up comparing the string "✓" to the string "✓". Since these two are not equal, it doesn't recognize a valid checkmark and the button never activates. How can I compare the contents of the HTML element my constant? (And hopefully make the code work even if down the road somebody replaces the checkmark with something else.)
Thanks.
There is no problem with the check character and it behaves exactly like the X character. The problem is, that your html have the checkmark character stored as html entity in hex string. If you compare checkmark to checkmark it works just fine: https://jsfiddle.net/m7yoh026/
What you can do in your case is to make sure the CHECKMARK variable is the actuall checkmark character, not the html entity.
Other option is to decode the html entity: https://jsfiddle.net/m7yoh026/3/
var CHECKMARK = '✓'
var decoded_checkmark = $('<textarea />').html(CHECKMARK).text();
console.log($('div')[0].innerHTML)
if ($('div')[0].innerHTML == decoded_checkmark) {
$('body').append('checkmark recognized<br>')
}
You can convert a character to its HTML entity equivalent like so:
var encoded = raw.replace(/[\u00A0-\u9999<>\&]/gim, function(i) {
return '&#'+i.charCodeAt(0)+';';
});
Well, here's what I ended up doing: I made a function called encodeHtml() that takes a character or string, writes it to a brand new div, and then returns what's contained in that div:
function encodeHtml(character) {
var element = document.createElement("div");
element.innerHTML = character;
return element.innerHTML;
}
Then I can compare to what it returns, since it automatically changes "✓" to "✓", and will work with any unforeseen changes to that character. It's a bit of a kludge, but it works. (It's still not clear to me why JavaScript does this automatic conversion...but there are many design choices in which JavaScript mystifies me, so there you go.)
Thanks all for the help.

how to capture the mouseover element?

i am developing an autocomplete feature.but i am facing one problem there...
when i click on the suggestion box one of the results will not enter into the suggest html box...
function handleOnMouseOver(oTr)
{
deselectAll();
oTr.className ="highlightrow";
position = oTr.id.substring(2, oTr.id.length);
updateKeywordValue(position);
}
can you plz tell the solution
thanks
function updateKeywordValue(oTr)
{
var oKeyword = document.getElementById("keyword");
var strKeyword="";
var crtLink = document.getElementById("a" +oTr.id.substring(2,oTr.id.length)).toString();
crtLink = crtLink.replace("-", "_");
crtLink = crtLink.substring(0, crtLink.length);
oKeyword.value=unescape(crtLink.substring(googleurl.length, crtLink.length));
strKeyword=oKeyword.value.toString();
if (oTr.id.substring(2,oTr.id.length)==0)
{
oKeyword.value=strKeyword.substring(3,strKeyword.length);
}
selectedKeyword=oKeyword.value;
}
you should get rid of the second parameter in the substring() method. Since you just want the remainder of the string, I'm guessing, that is the default if you don't set a second value.
position = oTr.id.substring(2);
My guess is that you are getting the value of the keyword from the id, and pushing that into the input box, right? If that's the case, we'll need to see more of your code. Specifically, I'd like to see the updateKeywordValue function and I'd also like to know if the text that they are hovering over is the text you are trying to send the input box. If so, you could probably simplify the whole thing and go with something like:
function handleOnMouseOver(oTr)
{
deselectAll();
oTr.className ="highlightrow";
keywordbox.value = oTr.innerHTML;
}
But this is based on the assumption that the only data inside the hovered row is the text, and no other html. And I had to make up a name for your input box.
But if this way off, this is because we need more information to see the real problem.

Categories