I am trying to develop a braces auto completion feature in a text box. I tried the javascript replace function on the textbox. But i am getting a weird output from the function. Here's the code i am work on.
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<input type ="text" id="textbox">
</body>
</html>
Javascript:
var element = document.getElementById('textbox');
element.oninput = function(){
var code = (function(){
var val = element.value;
element.value = val.replace(/\{/ , "{}");
})();
};
When i type a single { brace i am getting {} , when i type more than 1 i am getting {}}}{{ and it goes on .. sometimes my browser freezes when i try to clear the braces.
Here's the js bin link JSBIN
The problem is that you are always replacing { with {}, even if the bracket has already been matched. You should instead ensure it was not with negative lookahead: /\{(?!\})/
To fix the backspace issue, you should instead be using an event which can tell you which key was pressed like onkeyup and add a guard clause. Expanding on #Andi's idea, I also added exclusion for the arrow keys so you won't be forced to the end of the textbox when you want to navigate through the text:
var element = document.getElementById('textbox');
element.onkeyup = function(){
if([8, 37, 39].indexOf(event.which) != -1)
return false;
var code = (function(){
var val = element.value;
element.value = val.replace(/\{(?!\})/g, "{}");
})();
};
Your regex matches '{', you should exclude all '{}':
Snippet: [regex : /(?!{})\{/ ]
var element = document.getElementById('textbox');
element.oninput = function() {
var code = (function() {
var val = element.value;
element.value = val.replace(/(?!{})\{/, "{}");
})();
};
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<input type="text" id="textbox">
</body>
</html>
Update (With Backspace working):
Need to use keyboard event so that we can get keycode of the key pressed. Use onkeyup
var element = document.getElementById('textbox');
element.onkeyup = function(e) {
if (e.which != 8) {
var val = element.value;
element.value = val.replace(/(?!{})\{/, "{}");
}
};
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<input type="text" id="textbox">
</body>
</html>
Regexs may become heavy for an autocompletion tool, especially with negative lookaheads.
Actually, you do not have to look for braces at each input, just test the character typed with onkeypress event.
And you should also put the caret into the braces, otherwise you have still one keystroke because you have to move back :)
var element = document.getElementById('textbox');
element.onkeypress = function(evt){
switch(String.fromCharCode(evt.which)){
case "{":
var currentCaretPosition= this.selectionStart;
var text= this.value;
this.value= text.slice(0, currentCaretPosition)+
"{\n\t\n}"+
text.slice(currentCaretPosition,text.length );
this.setSelectionRange( currentCaretPosition+3, currentCaretPosition+3 );
evt.preventDefault();
}
};
#textbox{
border:inset 1px #aaa;
width:80vw;
height:80vw;
margin:2vw;
padding:0.5vw
}
<textarea id="textbox">
function test()
</textarea>
The whole sting is evaluated each time the function is called.
{ -> {}
if you now add another } you get {}}{}
use val.replace(/\{$/ , "{}");
The $ only evaluates the last character. Here you can try to build regex queries:
https://regex101.com/r/iU4xT9/1
PS: Maybe it gets weirds when you delete the last } you could only call the function, when you add characters and ignore the delete key.
var element = document.getElementById('textbox');
element.onkeyup = function(event){
if(event.which == 8)
return false
var code = (function(){
var val = element.value;
element.value = val.replace(/\{$/ , "{}");
})();
};
Related
I wrote a live search field for a part of my form, when the suggestions come and user clicks on one of them, a js function (selectedService) is being called to get the innerHTML of the li which the user clicked on!
everything works perfectly when you look at the code in 'Inspect Element' of the browser, but not on the web page!
after the user clicks on the on the suggestion the value property of input element changes in the code but on the browser. the content of input field is still what the user is typing in it.
here's the code :
<!DOCTYPE html>
<html dir="rtl">
<head>
<meta charset="UTF-8">
</head>
<body>
<input value="" id="services" placeholder="click or type plz..."/>
<ul id="suggestions">
</ul>
<style>
/* some styles */
</style>
<script>
var input = document.getElementById("services");
var suggestions = document.getElementById("suggestions");
input.oninput = function() {
var q = input.value;
if (q.length < 2) {
suggestions.setAttribute("style","display: none");
return;
}
var xhr2 = new XMLHttpRequest;
xhr2.open("GET", "theURL/service-request-handler.php?q="+q, true);
xhr2.onreadystatechange = function() {
if (xhr2.readyState == 4 && xhr2.status == 200)
{
var result = xhr2.responseText;
console.log("server response = "+result);
var json = JSON.parse(result);
showSuggestions(json);
}
};
xhr2.send();
};
function showSuggestions(json) {
suggestions.setAttribute("style","display: block");
var li_list = '';
var i = 0;
for (i=0; i<json.length; i++)
li_list += '<li id="'+i+'" onclick="selectedService('+i+')">'+json[i]+'</li>';
suggestions.innerHTML = li_list;
}
function selectedService(i) {
li_target = document.getElementById(i);
console.log(li_target.innerHTML);
// input.innerHTML = li_target.innerHTML;
input.setAttribute("value",li_target.innerHTML);
suggestions.setAttribute("style","display: none");
}
</script>
</body>
</html>
the result in the Inspect Element :
I'd appreciate any help or suggestions :)
input.value = li_target.innerHTML
You can set value property directly:
input.value=li_target.innerHTML;
Probably you are using firefox browser, you should use this to work in both, chrome and firefox.
input.value = li_target.innerHTML;
This happens because property and attributes are different.
Attributes are defined on the HTML markup but properties are defined on the DOM.
You can use jQuery UI for autocomplete search.
im working on a translation project and i need to modify some characters at the end for example if user types words like:
typed word: "yilanin" => target word (what i want) :"yilaNG"
"suyunin" => "suyuNG"
"kalinin" => "kaliNG"
"batinin" => "batiNG"
etc etc...
But i have a problem: i don't want to modify "nin" characters if they are at the middle or at the beginning of a word like:
"kinindan*"" => **"kinindan"
"sininteki"" => "sininteki"
"nin" => "nin"
"ninkisi" => "ninkisi"
etc etc...
i mean every "xxxnin" to "xxxNG",
"xxxninxxx" to "xxxninxxx"(no modification),
"nin" to "nin" (no modification)...
i tried to explain my problem very clearly and bascially i hope you understand...
$(document).ready(function(){
$("#ta_1").keyup(function(event) {
var text2 = $(this).val();
text2 = text2.replace(/([abcçdefgğhıijklmnoöprsştuüvyzABCÇDEFGHIİJKLMNOÖPRSTUÜVYZ])nin$/g, '$1NG');
$("#ta_1").val(text2);
});
});
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="utf-8" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<textarea id="ta_1" rows="5" cols="28"></textarea>
</body>
</html>
You need to track two events: keyup (to track text input continuation) and blur (to check for the string input end). Then, use 2 different replacements:
$(document).ready(function(){
$("#ta_1").on("keyup blur", function(event) {
var text2 = $(this).val();
if (event.type !== "blur") { // Trigger only on keyup
text2 = text2.replace(/([a-zA-ZçğıöşüÇİÖÜ])nin\b(?![a-zA-ZçğıöşüÇİÖÜ])([\s\S])/g, '$1NG$2');
}
else { // we have blur
text2 = text2.replace(/([a-zA-ZçğıöşüÇİÖÜ])nin$/, '$1NG');
}
$("#ta_1").val(text2);
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="ta_1" rows="5" cols="28"></textarea>
The keyup event will check for an already input word containing (I guess) Turkish word - ([a-zA-ZçğıöşüÇİÖÜ])nin\b(?![a-zA-ZçğıöşüÇİÖÜ])([\s\S]) - followed with some character that will serve as a word boundary.
The blur event will check for a nin at the end of the whole string only, and perform the replacement if necessary.
Update:
Here is another approach: replace while typing and if another character is typed, revert. However, this approach won't work if several character combinations can be replaced with one and the same replacement pattern (it will be unclear what string to restore then):
$(document).ready(function(){
$("#ta_1").on("keyup", function(event) {
var text2 = $(this).val();
// Replace nin to NG in general
text2 = text2.replace(/([a-zA-ZçğıöşüÇİÖÜ])nin\b(?![a-zA-ZçğıöşüÇİÖÜ])/g, '$1NG');
// Restore nin from NG
text2 = text2.replace(/([a-zA-ZçğıöşüÇİÖÜ])NG(?=[a-zA-ZçğıöşüÇİÖÜ])/g, '$1nin')
$("#ta_1").val(text2);
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="ta_1" rows="5" cols="28"></textarea>
Try this
(\w)(nin)\b
Regex demo
$(document).ready(function(){
//setup before functions
var typingTimer; //timer identifier
var doneTypingInterval = 1000; //time in ms, 1 second for example
var $input = $('#myInput');
//user is "finished typing," do something
function doneTyping () {
//do something
}
$("#ta_1").keyup(function(event) {
var text2 = $(this).val();
var re = /(\w)(nin)([^a-zA-Z])/g;
var subst = '$1NG$3';
text2 = text2.replace(re, subst);
var re = /(\w)(NG)(\w)/;
var subst = '$1nin$3';
text2 = text2.replace(re, subst);
$("#ta_1").val(text2);
clearTimeout(typingTimer);
typingTimer = setTimeout(doneTyping, doneTypingInterval);
});
$("#ta_1").keydown(function(event) {
clearTimeout(typingTimer);
});
function doneTyping () {
var text2 = $("#ta_1").val();
var re = /(\w)(nin)\b/g;
var subst = '$1NG';
text2 = text2.replace(re, subst);
$("#ta_1").val(text2);
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="utf-8" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<textarea id="ta_1" rows="5" cols="28"></textarea>
</body>
</html>
This should work
(?!^nin)(nin$)
Regex Demo
JS Code
var re = /(?!^nin)(nin$)/gm;
var str = 'suyunin\nabcninshs\nning\ngnin\nning\nkinindan*\nsininteki\nnin\nninkisi';
var subst = 'NG';
var result = str.replace(re, subst);
document.writeln(result)
JSFiddle Demo
Ideone Demo
Would something like this work?
text.replace(/([\s\S])nin\b(?![çğıöşüÇİÖÜ])/, '$1NG');
\b matches a word boundary position such as whitespace, punctuation, or the start/end of the string.
?![çğıöşüÇİÖÜ] negative lookahead to specify no match if any of the specified characters are found.
var stringArr = ['suyunin', 'kalinin', 'batinin', 'kinindan', 'sininteki', 'nin', 'ninkisi', 'xxxnin', 'xxxninxxx', 'nin', 'Kalininü'];
var generated = document.getElementById('generated');
for (var i = 0; i < stringArr.length; i++) {
var newStr = stringArr[i].replace(/([\s\S])nin\b(?![çğıöşüÇİÖÜ])/, '$1NG');
var li = document.createElement('li');
li.appendChild(document.createTextNode(newStr));
generated.appendChild(li);
}
#generated {
color: red;
}
<!DOCTYPE html>
<html>
<body>
Array List:
<br>['suyunin', 'kalinin', 'batinin', 'kinindan', 'sininteki', 'nin', 'ninkisi', 'xxxnin', 'xxxninxxx', 'nin'];
<br>Generated List:
<br>
<span id='generated'></span>
</body>
</html>
I need to fix this segment of code for a class and I have fixed a number of things but I'm not sure why it doesn't work. It is supposed to count the number of vowels in the phrase and return them as an alert. When I click on the button nothing appears.
Here's the html. It works fine but added in case I am missing something
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Vowels</title>
<link rel="stylesheet" href="../css/easy.css">
<script src="p3-vowels.js"></script>
</head>
<body>
<header>
<h1>Count Vowels</h1>
</header>
<main>
<label>Type a phrase here:
<input type='text' id='textBox'></input>
</label>
<button id='countBtn' type='button'>
Count Vowels (a,e,i,o,u)</button>
<div id='outputDiv'></div>
</main>
</body>
</html>
here is the JS. It doesn't seem to register the "on.click" at the end of the code
function countVowels() {
var textBox, phrase, i, pLength, letter, vowelCount;
textBox = document.getElementById('textBox');
phrase = textBox.value;
phrase = phrase.toLowerCase();
vowelCount = 0;
for (i = 0; i < phrase.length; i += 1) {
letter = phrase[i];
if (letter === 'a' || letter === 'e' || letter === 'i' || letter === 'o' || letter === 'u') {
vowelCount++;
}
}
alert(vowelCount + ' vowels');
var outArea = document.getElementById('outputDiv');
outArea.innerHTML = vowelCount + ' vowels in ' + phrase;
}
function init() {
alert('init vowels');
var countTag = document.getElementById('countBtn');
countTag.onclick = countVowels;
}
window.onload = init();
The problem is window.onload = init();, here you are calling init method and is assigning the value returned by init as the onload callback. So when the init method is called the countBtn is not yet added to the dom resulting in an error like Uncaught TypeError: Cannot set property 'onclick' of null.
What you really want is to call init on the load event, so you need to pass the reference to init function to onload
It should be
window.onload = init;
Demo: Fiddle
I don't know why search() function returns 0 for any input with SPECIAL CHARACTER, I wanted to find position of 1st occurrence of special character. When I am hardcoding the value for search() method it is working fine, but when I am taking value from text box it is not working properly.
Following is my HTML code:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<script type="text/javascript" src="jquery-1.6.4.min.js"></script>
<script type="text/javascript" src="test.js"></script>
</head>
<body>
<input type="text" id="txt" onkeyup="return checkLength();"/>
<input type="button" id="btn" value="Verify" onclick="getValue()"/>
</body>
</html>
Following is the script where I have implemented the use of search() of Javascript, but don't know why I am getting 0 value for any input. Actually I wanted to find the position of first special character occurrence.
$(document).ready(function() {
$('#btn').attr('disabled',true);
$("#txt").bind({
paste : function(){
$('#btn').attr('disabled',false);
checkLength();
},
cut : function(){
checkLength();
}
});
});
function checkLength(){
var txtLength = $("#txt").val().length;
var banTxt = document.getElementById("txt").value;
if (txtLength != 0) {
if(isAlphaNumeric(document.getElementById("txt").value)) {
$('#btn').attr('disabled',false);
} else {
var str=banTxt;
//Here I am using search() to find position of Special Character.
var n=banTxt.search(/[^a-zA-Z ]/g);
alert("position of special char is: " + n);
var preTxt = banTxt.substring(0,(txtLength - 1));
var preTxtLength = preTxt.length;
alert("Special characters are not allowed!");
if(preTxtLength == 0){
$('#btn').attr('disabled',true);
document.getElementById("txt").value = "";
}else if(preTxtLength != 0){
document.getElementById("txt").value = preTxt;
$('#btn').attr('disabled',false);
}
}
} else {
$('#btn').attr('disabled',true);
}
}
function isAlphaNumeric(inputString) {
return inputString.match(/^[0-9A-Za-z]+$/);
}
function getValue(){
var txtValue = document.getElementById("txt").value;
alert("Value submitted is: " + txtValue);
}
var n=banTxt.search(/[^a-zA-Z ]/g);
I tried with string with special characters like 123#4$5 , 12#4 , etc. and I am getting alert as position of special char is: 0
That's just what your regex matches: No alphabet characters and no blanks - that includes digits. In contrast, your isAlphaNumeric function matches against /^[0-9A-Za-z]+$/ - you probably want to align them with each other.
Actually i have used the following line var n=banTxt.search(/[^a-zA-Z ]/g); for getting the position of special char, at the same time please note that i have used onkeyup event so if i am copy pasting the code i.e first ctrl then v, ctrl + v then ctrl itself is keyup event i think this might be the reason i am getting 0 as position of special char, as after pressing ctrl no text is pasted but onkeyup event is triggered.
I am looking for the solution of it.
Is there a way to maintain the div scroll position on a postback, without using asp? So far I've only found solutions using asp.
http://blogs.x2line.com/al/articles/156.aspx
<!doctype html>
<html>
<head>
<title></title>
<script language="javascript">
// function saves scroll position
function fScroll(val)
{
var hidScroll = document.getElementById('hidScroll');
hidScroll.value = val.scrollTop;
}
// function moves scroll position to saved value
function fScrollMove(what)
{
var hidScroll = document.getElementById('hidScroll');
document.getElementById(what).scrollTop = hidScroll.value;
}
</script>
</head>
<body onload="fScrollMove('div_scroll');" onunload="document.forms(0).submit()";>
<form>
<input type="text" id="hidScroll" name="a"><br>
<div id="div_scroll" onscroll="fScroll(this);" style="overflow:auto;height:100px;width:100px;">
.. VERY LONG TEXT GOES HERE
</div>
</form>
</body>
</html>
Maybe this javascript code works for you
function loadScroll ()
{
var m = /[&?]qs\=(\d+)/.exec (document.location);
if (m != null)
myDiv.scrollTop = parseInt (m[1]);
}
function saveScroll ()
{
var form = document.getElementById ("myForm");
var sep = (form.action.indexOf ("?") == -1) ? "?" : "&";
form.action += sep + "qs=" + myDiv.scrollTop;
}
Now, you can watch for the "submit" event to save the position in the "action" attribute:
document.getElementById ("myForm").addEventListener ("submit", saveScroll, false);
And in your BODY tag...
<body onload="loadScroll ();">
....
</body>
I can't test the code right now, but I think you get the idea.