How to check whether inputs are words, space and newLine? - javascript

let msgInpt = document.getElementById("message");
msgInpt.addEventListener("keydown", function(entEvt){
if (!msgInpt.innerText === ' ') {
if (entEvt.code === 'Enter' && !entEvt.shiftKey) {
entEvt.preventDefault();
postChat();
}
} else {
if (entEvt.code === 'Enter' && !entEvt.shiftKey) {
entEvt.preventDefault();
return false;
} else if(entEvt.code === 'Enter' && entEvt.shiftKey) {
entEvt.preventDefault();
return false;
} else if (entEvt.code === 'Space') {
entEvt.preventDefault();
return false;
}
}
});
div{
background-color: #f2f2f4;
padding: 12px;
height: 150px;
border: 2px solid #333;
border-radius: 10px;
box-shadow: 0px 0px 12px 4px rgba(0,0,0,0.18);
}
<div contenteditable="true" id="message"></div>
After that I tried this
msgInpt.addEventListener("keydown", function(entEvt){
if (msgInpt.innerText) {
if (entEvt.code === 'Enter' && !entEvt.shiftKey) {
entEvt.preventDefault();
if (!msgInpt.innerText === ' ') {
postChat();
}
}
} else {
if (entEvt.code === 'Enter' && !entEvt.shiftKey) {
entEvt.preventDefault();
return false;
} else if(entEvt.code === 'Enter' && entEvt.shiftKey) {
entEvt.preventDefault();
return false;
} else if (entEvt.code === 'Space') {
entEvt.preventDefault();
return false;
}
}
});
I want to validate whether the user is giving input as word only.
When user First gives input of or \n only, then user must not be able to send messages.
Why Both the codes are not working?
Please can anybody tell me what is the logic behind this

You can always use Regular Expression for this kind of query. It helps you to overcome the space and newline input problem easily.
Refer this article for using RegEx in javascript.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions

Related

Make the display hidden work for the empty innerhtml element

I have a form that takes in a name without space and a phone number.
I managed to get the form and the error messages to work but I couldn't find a way to hide the syle of the error when there's no message in it. It does the job in hiding the other subsequent error messages but not the first one, I found this out through Chrome's debugging tool.
I've tried iterating through all elements to find a blank innerHTML and make the error style hidden, but it didn't work, it couldn't find it.
Is there a way? Here's the code:
window.onload = function () {
let form = document.getElementById("formDetails");
form.addEventListener("submit", function (event) {
let haltSubmission = false;
cleanPhoneError();
cleanNameError();
for (let i = 0; i < form.elements.length; i++) {
if (!nameCheck(form.elements[i])) {
haltSubmission = true;
} else if (!matchingPhone(form, form.elements[i])) {
haltSubmission = true;
} else if (!lengthOfPhone(form.elements[i])) {
haltSubmission = true;
}
}
if (haltSubmission) {
event.preventDefault();
}
}, false);
}
function nameCheck(formInput) {
if (formInput.id === "name") {
let value = formInput.value, error = "", letters = /^[a-zA-Z]+$/,
characters = /^[a-zA-Z0-9!##\$%\^\&*\)\(+=._-]+$/g;
if (value === null || value === "") {
error = "This field is empty.";
}
if (value !== "") {
if (value.length < 3) {
error = "This field has less than 3 characters.";
}
if (!value.match(letters)) {
error = "Numbers detected. Please write your first name.";
}
if (!value.match(characters)) {
error = "Special characters detected. Please write your first name.";
}
}
errorMessage(formInput, error);
}
return true;
}
function matchingPhone(form, formInput) {
if (formInput.id === "phone") {
let error = "";
let phone = form.phone.value;
let retypedPhone = form.retypedphone.value;
if (phone === retypedPhone) {
return true;
} else {
error = "Phone numbers do not match.";
phoneError(error);
return false;
}
}
return true;
}
function lengthOfPhone(formInput) {
if (formInput.id === "phone") {
let value = formInput.value, error = "";
if (value === null || value === "") {
error = "This field is empty.";
phoneError(error);
return false;
} else if (value !== "") {
if (value.length < 11) {
error = "Invalid phone number, it has than 11 numbers.";
phoneError(error);
return false;
}
}
}
return true;
}
function errorMessage(selected, error) {
let elem = document.createElement("span");
elem.setAttribute("id", "nameError");
elem.setAttribute("class", "error");
let text = document.createTextNode(error);
elem.appendChild(text);
selected.parentNode.insertBefore(elem, selected.nextSibling);
return selected;
}
function phoneError(error) {
let phoneError = document.getElementById("phoneError");
phoneError.setAttribute("class", "error");
phoneError.innerHTML = error;
}
function cleanPhoneError() {
let error = document.getElementsByTagName("span");
for (let i = 0; i < error.length; i++) {
error[i].innerHTML = "";
}
}
function cleanNameError() {
let error = document.getElementById("nameError");
let errorMessage = document.getElementsByTagName("span");
for (let i = 0; i < errorMessage.length; i++) {
if (errorMessage[i].id === "nameError") {
error.style.display = "none";
}
}
}
label, button {
display: block;
margin: 10px 0 5px 0;
}
input, button {
padding: 8px;
width: 393px;
font-size: 16px;
}
body, button{
font-family: Arial, sans-serif;
}
.error{
color: #FFF;
display: block;
margin: 0 0 15px 0;
background: #990000;
padding: 5px 3px 5px 5px;
width: 405px;
line-height: 25px;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JavaScript</title>
<link rel="stylesheet" href="css/test.css">
<script src="js/test.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<section>
<h1>Form</h1>
<div id="form">
<form id="formDetails" action="confirm.html">
<div>
<label for="name">* Name:</label>
<input type="text" id="name">
</div>
<div>
<label for="phone">* Phone Number</label>
<input type="phone" id="phone">
</div>
<div>
<label for="retypedphone">* Retype Phone Number:</label>
<input type="phone" id="retypedphone">
<span id="phoneError"></span>
</div>
<div>
<button type="submit" id="submitbtn">Submit</button>
</div>
</form>
</div>
</section>
</body>
</html>
You need to modify your function errorMessage(...) to only append the element if there is an error message.
A simple `if` statement might be enough for your needs.
UPDATE
Based on comment, I re-wrote the hiding/showing error logic, please have a look. I think this is a bit more readable too
See demo below
function cleanPhoneError() {
hideElement("phoneError");
}
function hideElement(elementName) {
let elementObj = document.getElementById(elementName);
if (elementObj) {
elementObj.innerHTML = "";
elementObj.setAttribute("class", "hidden");
}
}
window.onload = function() {
let form = document.getElementById("formDetails");
form.addEventListener("submit", function(event) {
let haltSubmission = false;
cleanErrors();
if (!validName()) {
haltSubmission = true;
}
if (!validPhone()) {
haltSubmission = true;
}
if (haltSubmission === true) {
event.preventDefault();
}
}, false);
}
function cleanErrors() {
cleanPhoneError();
cleanNameError();
}
function validName() {
let nameObj = document.getElementById("name");
if (nameObj) {
let value = nameObj.value,
error = "",
letters = /^[a-zA-Z]+$/,
numbers = /[0-9]+/,
characters = /[!##\$%\^\&*\)\(+=._-]+/g;
if (value === null || value === "") {
error = "This field is empty.";
} else if (value.length < 3) {
error = "This field has less than 3 characters.";
} else if (value.match(characters)) {
error = "Special characters detected. Please write your first name.";
} else if (value.match(numbers)) {
error = "Numbers detected. Please write your first name.";
}
if (error !== undefined && error.trim() !== '') {
displayErrorMessage(error, "nameError");
return false;
}
return true;
}
displayErrorMessage("Unable to find Name field.", "nameError");
return false;
}
function validPhone() {
let phoneObj = document.getElementById("phone");
let retypedPhoneObj = document.getElementById("retypedPhone");
if (phoneObj && retypedPhoneObj) {
let phoneValue = phoneObj.value;
let retypedPhoneValue = retypedPhoneObj.value;
if (phoneValue !== retypedPhoneValue) {
displayErrorMessage("Phone numbers do not match.", "phoneError");
return false;
} else {
return validateLengthOfPhone(phoneValue);
}
} else {
displayErrorMessage("Unable to find Phone fields.", "phoneError");
return false;
}
return true;
}
function validateLengthOfPhone(value) {
let error = "";
if (value === null || value === "") {
error = "This field is empty.";
displayErrorMessage(error, "phoneError");
return false;
} else if (value.length < 11) {
error = "Invalid phone number, it has less than 11 numbers.";
displayErrorMessage(error, "phoneError");
return false;
}
return true;
}
function displayErrorMessage(errorMsg, elementName) {
if (errorMsg !== undefined && errorMsg.trim() !== '') {
let elementError = document.getElementById(elementName);
elementError.setAttribute("class", "error visible");
elementError.innerHTML = errorMsg;
}
}
function cleanPhoneError() {
hideElement("phoneError");
}
function cleanNameError() {
hideElement("nameError");
}
function hideElement(elementName) {
let elementObj = document.getElementById(elementName);
if (elementObj) {
elementObj.innerHTML = "";
elementObj.setAttribute("class", "hidden");
}
}
label,
button {
display: block;
margin: 10px 0 5px 0;
}
input,
button {
padding: 8px;
width: 393px;
font-size: 16px;
}
body,
button {
font-family: Arial, sans-serif;
}
.error {
color: #FFF;
display: block;
margin: 0 0 15px 0;
background: #990000;
padding: 5px 3px 5px 5px;
width: 405px;
line-height: 25px;
display: none;
}
.visible {
display: inline-block;
}
.hidden {
display: none;
}
<section>
<h1>Form</h1>
<div id="form">
<form id="formDetails" action="confirm.html">
<div>
<label for="name">* Name:</label>
<input type="text" id="name">
<span id="nameError" class="error"></span>
</div>
<div>
<label for="phone">* Phone Number</label>
<input type="phone" id="phone">
</div>
<div>
<label for="retypedphone">* Retype Phone Number:</label>
<input type="phone" id="retypedPhone">
<span id="phoneError" class="error"></span>
</div>
<div>
<button type="submit" id="submitbtn">Submit</button>
</div>
</form>
</div>
</section>

How logical/boolean operators work in an if else if statement?

I'm building a tic tac toe game and I'm trying to use an if else if statement for my win conditions. I've tried a couple different methods for My conditions.
Here's all my coding for it:
var Box1=document.getElementById("box1"); //getting the grid spots and putting them into variables
var Box2=document.getElementById("box2");
var Box3=document.getElementById("box3");
var Box4=document.getElementById("box4");
var Box5=document.getElementById("box5");
var Box6=document.getElementById("box6");
var Box7=document.getElementById("box7");
var Box8=document.getElementById("box8");
var Box9=document.getElementById("box9");
var a1=document.getElementById("box1").innerHTML; //getting the innerHTML of the grid spots to check for x or o later
var a2=document.getElementById("box2").innerHTML;
var a3=document.getElementById("box3").innerHTML;
var a4=document.getElementById("box4").innerHTML;
var a5=document.getElementById("box5").innerHTML;
var a6=document.getElementById("box6").innerHTML;
var a7=document.getElementById("box7").innerHTML;
var a8=document.getElementById("box8").innerHTML;
var a9=document.getElementById("box9").innerHTML;
var playerchar="x"; //setting the first player as x
Box1.addEventListener("click", box1); //adding click event for when grid spot 1, 1 is clicked
function box1() {
Box1.innerHTML=playerchar; //Setting the innerHTML of the clicked grid spot
Box1.removeEventListener("click", box1);// removing click event
checkwin(); // check for a win condition
if(playerchar=="x") { //
playerchar="o"; //if the last turn was an x then change it to o.
}
else if(playerchar=="o") {
playerchar="x"; //if the last turn was o then change it to x.
}
}
Box2.addEventListener("click", box2);
function box2() {
Box2.innerHTML=playerchar;
Box2.removeEventListener("click", box2);
checkwin();
if(playerchar=="x") {
playerchar="o";
}
else if(playerchar=="o") {
playerchar="x";
}
}
Box3.addEventListener("click", box3);
function box3() {
Box3.innerHTML=playerchar;
Box3.removeEventListener("click", box3);
checkwin();
if(playerchar=="x") {
playerchar="o";
}
else if(playerchar=="o") {
playerchar="x";
}
}
Box4.addEventListener("click", box4);
function box4() {
Box4.innerHTML=playerchar;
Box4.removeEventListener("click", box4);
checkwin();
if(playerchar=="x") {
playerchar="o";
}
else if(playerchar=="o") {
playerchar="x";
}
}
Box5.addEventListener("click", box5);
function box5() {
Box5.innerHTML=playerchar;
Box5.removeEventListener("click", box5);
checkwin();
if(playerchar=="x") {
playerchar="o";
}
else if(playerchar=="o") {
playerchar="x";
}
}
Box6.addEventListener("click", box6);
function box6() {
Box6.innerHTML=playerchar;
checkwin();
Box6.removeEventListener("click", box6)
if(playerchar=="x") {
playerchar="o";
}
else if(playerchar=="o") {
playerchar="x";
}
}
Box7.addEventListener("click", box7);
function box7() {
Box7.innerHTML=playerchar;
Box7.removeEventListener("click", box7);
checkwin();
if(playerchar=="x") {
playerchar="o";
}
else if(playerchar=="o") {
playerchar="x";
}
}
Box8.addEventListener("click", box8);
function box8() {
Box8.innerHTML=playerchar;
Box8.removeEventListener("click", box8);
checkwin();
if(playerchar=="x") {
playerchar="o";
}
else if(playerchar=="o") {
playerchar="x";
}
}
Box9.addEventListener("click", box9);
function box9() {
Box9.innerHTML=playerchar;
Box9.removeEventListener("click", box9);
checkwin();
if(playerchar=="x") {
playerchar="o";
}
else if(playerchar=="o") {
playerchar="x";
}
}
function checkwin() {
if(a1==a2 && a1==a3 && a1=="x" || a1=="o") { //check for win with top row
quit(); //function for what happens when someone wins
}
else if(a4==a5 && a4==a6 && a4=="x" || a4=="o") { // check for win with second row
quit();
}
else if(a7==a8 && a7==a9 && a7=="x" || a7=="o") { //check for win with third row
quit();
}
else if(a1==a4 && a1==a7 && a1=="x" || a1=="o") {// check for win with first column
quit();
}
else if(a2==a5 && a2==a8 && a2=="x" || a2=="o") {//check for win with second column
quit();
}
else if(a3==a6 && a3==a9 && a3=="x" || a3=="o") { // check for win with third column
quit();
}
else if((a1 == 'x' || a1 == 'o') && a1==a5 || a1==a9) { //check for win from top left to bottom right
quit();
}
else if((a3==a5 && a3==a7) && (a3=="x" || a3=="o")) { // check for win from top right to bottom left
quit();
}
}
function quit() {
alert("Someone won");
}
#container {
cell-spacing: 0px;
border-spacing: 0px;
margin: 30px ;
border-collapse: separate;
}
table tr td {
width: 40px;
height: 40px;
border: 2px solid black;
font-size: 35px;
text-align: center;
cursor: pointer;
}
#container tr:first-child td
border-top: none
}
#container tr:last-child td
border-bottom: none
}
#container tr td:first-child
border-left: none;
}
#container tr td:last-child
border-right: none;
}
<title>TicTacToe</title>
</head>
<body>
<h2> Player 1 is x</h2>
<h2>Player 2 is o</h2>
<div id="container">
<table>
<tr>
<td id="box1"></td>
<td id="box2"></td>
<td id="box3"></td>
</tr>
<tr>
<td id="box4"></td>
<td id="box5"></td>
<td id="box6"></td>
</tr>
<tr>
<td id="box7"></td>
<td id="box8"></td>
<td id="box9"></td>
</tr>
</table>
</div>
</body>
<script type="text/javascript" src="TicTacToe.js"></script>
</html>
So when a player clicks on one of the td's that haven't been clicked yet, it takes the player character and puts it into the innerHTML of the td. Then changes the player character to the opposing value. How can I make the checkwin() function check all 8 possible win conditions for x or o.
So you want to test if A1, A5, and A9 all contain the same character (either "x" or "o") and quit. Otherwise, if A3, A5, and A7 all contain the same character (either "x" or "o") then quit? Something like your posted code should work fine.
else if((a1 == 'x' || a1 == 'o') && a1==a5 && a1==a9) {
quit();
}
else if((a3 == 'x' || a3 == 'o') && a3==a5 && a3==a7) {
quit();
}
I figured out what I was doing wrong. My a1-a9 variables were getting innerHTML before being clicked on, so all my win condition variables were null. Just had to move the variables to the checkwin() function to refresh them.

The deletion of span in the content editable in mobile does not works

There are spans in the content editable div which needs to be deleted all at once. Now this works fine on the chrome desktop but when I try to delete it on the following devices this does not works.I am testing it on following
Chrome on Android
Safari on Mac, iOS
Firefox on Windows
When I try to delete the box looses focus and span does not delete.
This is the fiddle link to what I have tried so far.
var EditableDiv = document.getElementById('EditableDiv');
EditableDiv.onkeydown = function(event) {
var ignoreKey;
var key = event.keyCode || event.charCode;
if (!window.getSelection) return;
var selection = window.getSelection();
var focusNode = selection.focusNode,
anchorNode = selection.anchorNode;
var anchorOffset = selection.anchorOffset;
if (!anchorNode) return
if (anchorNode.nodeName.toLowerCase() != '#text') {
if (anchorOffset < anchorNode.childNodes.length)
anchorNode = anchorNode.childNodes[anchorOffset]
else {
while (!anchorNode.nextSibling) anchorNode = anchorNode.parentNode // this might step out of EditableDiv to "justincase" comment node
anchorNode = anchorNode.nextSibling
}
anchorOffset = 0
}
function backseek() {
while ((anchorOffset == 0) && (anchorNode != EditableDiv)) {
if (anchorNode.previousSibling) {
if (anchorNode.previousSibling.nodeName.toLowerCase() == '#text') {
if (anchorNode.previousSibling.nodeValue.length == 0)
anchorNode.parentNode.removeChild(anchorNode.previousSibling)
else {
anchorNode = anchorNode.previousSibling
anchorOffset = anchorNode.nodeValue.length
}
} else if ((anchorNode.previousSibling.offsetWidth == 0) && (anchorNode.previousSibling.offsetHeight == 0))
anchorNode.parentNode.removeChild(anchorNode.previousSibling)
else {
anchorNode = anchorNode.previousSibling
while ((anchorNode.lastChild) && (anchorNode.nodeName.toUpperCase() != 'SPAN')) {
if ((anchorNode.lastChild.offsetWidth == 0) && (anchorNode.lastChild.offsetHeight == 0))
anchorNode.removeChild(anchorNode.lastChild)
else if (anchorNode.lastChild.nodeName.toLowerCase() != '#text')
anchorNode = anchorNode.lastChild
else if (anchorNode.lastChild.nodeValue.length == 0)
anchorNode.removeChild(anchorNode.lastChild)
else {
anchorNode = anchorNode.lastChild
anchorOffset = anchorNode.nodeValue.length
//break //don't need to break, textnode has no children
}
}
break
}
} else
while (((anchorNode = anchorNode.parentNode) != EditableDiv) && !anchorNode.previousSibling) {}
}
}
if (key == 8) { //backspace
if (!selection.isCollapsed) {
try {
document.createElement("select").size = -1
} catch (e) { //kludge for IE when 2+ SPANs are back-to-back adjacent
if (anchorNode.nodeName.toUpperCase() == 'SPAN') {
backseek()
if (anchorNode.nodeName.toUpperCase() == 'SPAN') {
var k = document.createTextNode(" ") // doesn't work here between two spans. IE makes TWO EMPTY textnodes instead !
anchorNode.parentNode.insertBefore(k, anchorNode) // this works
anchorNode.parentNode.insertBefore(anchorNode, k) // simulate "insertAfter"
}
}
}
} else {
backseek()
if (anchorNode == EditableDiv)
ignoreKey = true
else if (anchorNode.nodeName.toUpperCase() == 'SPAN') {
SelectText(event, anchorNode)
ignoreKey = true
} else if ((anchorNode.nodeName.toLowerCase() == '#text') && (anchorOffset <= 1)) {
var prev, anchorNodeSave = anchorNode,
anchorOffsetSave = anchorOffset
anchorOffset = 0
backseek()
if (anchorNode.nodeName.toUpperCase() == 'SPAN') prev = anchorNode
anchorNode = anchorNodeSave
anchorOffset = anchorOffsetSave
if (prev) {
if (anchorOffset == 0)
SelectEvent(prev)
else {
var r = document.createRange()
selection.removeAllRanges()
if (anchorNode.nodeValue.length > 1) {
r.setStart(anchorNode, 0)
selection.addRange(r)
anchorNode.deleteData(0, 1)
}
else {
for (var i = 0, p = prev.parentNode; true; i++)
if (p.childNodes[i] == prev) break
r.setStart(p, ++i)
selection.addRange(r)
anchorNode.parentNode.removeChild(anchorNode)
}
}
ignoreKey = true
}
}
}
}
if (ignoreKey) {
var evt = event || window.event;
if (evt.stopPropagation) evt.stopPropagation();
evt.preventDefault();
return false;
}
}
function SelectText(event, element) {
var range, selection;
EditableDiv.focus();
if (window.getSelection) {
selection = window.getSelection();
range = document.createRange();
range.selectNode(element)
selection.removeAllRanges();
selection.addRange(range);
} else {
range = document.body.createTextRange();
range.moveToElementText(element);
range.select();
}
var evt = (event) ? event : window.event;
if (evt.stopPropagation) evt.stopPropagation();
if (evt.cancelBubble != null) evt.cancelBubble = true;
return false;
}
#EditableDiv {
height: 75px;
width: 500px;
font-family: Consolas;
font-size: 10pt;
font-weight: normal;
letter-spacing: 1px;
background-color: white;
overflow-y: scroll;
overflow-x: hidden;
border: 1px solid black;
padding: 5px;
}
#EditableDiv span {
color: brown;
font-family: Verdana;
font-size: 8.5pt;
min-width: 10px;
/*_width: 10px;*/
/* what is this? */
}
#EditableDiv p,
#EditableDiv br {
display: inline;
}
<div id="EditableDiv" contenteditable="true">
(<span contenteditable='false' onclick='SelectText(event, this);' unselectable='on'>Field1</span> < 500) <span contenteditable='false' onclick='SelectText(event, this);' unselectable='on'>OR</span> (<span contenteditable='false' onclick='SelectText(event, this);' unselectable='on'>Field2</span> > 100 <span contenteditable='false' onclick='SelectText(event, this);' unselectable='on'>AND</span> (<span contenteditable='false' onclick='SelectText(event, this);' unselectable='on'>Field3</span> <= 200) )
</div>
I am using javascript for this.
I am developing a solution for a app using meteor and blaze UI for templates which will run on iOS.
Try to put the css cursor:pointer; on the div that you want to click on and delete.
Sometimes mobile browser, esp. Safari doesnt allow click event on the element unless it has cursor:pointer. It will trigger that this div is link or clickable.

Using jQuery to changing background colour of a div

I'm trying to change the background colour of my div when the user presses either C, M or Y. I need to use the keypress method, but for some reason my code doesn't work.
$(document).ready(function() {
$(document).keypress(function(event) {
if (event === 99) {
$(".light").css('background-color', "#00ffff");
} else if (event === 121) {
$(".light").css('background-color', "#00ffff");
} else if (event === 109) {
$(".light").css('background-color', "#00ffff");
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="light"></div>
You need to use event.which to determine which key was pressed. Here's working code:
$(document).ready(function() {
$(document).keypress(function(event) {
if (event.which === 99) {
$(".light").css('background-color', "#00ffff");
} else if (event.which === 121) {
$(".light").css('background-color', "#00ffff");
} else if (event.which === 109) {
$(".light").css('background-color', "#00ffff");
}
});
});
div.light {
width: 50px;
height: 50px;
background-color: black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="light"></div>
You need to use the which value from the keypress event. I would also suggest that you use a switch-statment.
$(document).ready(function() {
$(document).keypress(function(e) {
var color = null;
switch (e.which || e.keyCode || 0) { // Cover all cases
case 99: // Key - C
color = '#00FFFF'; break;
case 109: // Key - M
color = '#FF00FF'; break;
case 121: // Key - Y
color = '#FFFF00'; break;
default:
color = '#FFFFFF';
}
$('.light').css('background-color', color);
});
});
.light {
width: 95vw;
height: 95vh;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="light"></div>
Thanks to smarx for the heads-up about jQuery and which.

Emulate SO tag editor

I'm trying to implement a 'Tag Editor' field in my app, the same way as SO does.
Right now i got this:
EDIT: I have coded this into a jQuery plugin at:
https://github.com/fernandotenorio/tagme.git
Fiddle
http://jsfiddle.net/FernandoTen/PnYuF/
html
<div style="margin-left: auto; margin-right: auto; width: 400px;">
<span style='color: #333; font-size: small'>
Tags [a-z A-Z 0-9 # + . -]
</span>
<div id='tags_container'>
<span id='tags_queue'></span>
<input type='text' id='tf' />
</div>
</div>
js
$(document).ready(function () {
var rexp = /[^a-zA-Z0-9#+\.\-]/
var left = 37;
var right = 39;
var del = 8;
var space = 32;
var comma = 188;
var minlen = 3;
var maxlen = 15;
var current_tag = null
$('#tf').focus().attr('maxlength', maxlen)
$('#tags_container').click(function () {
$('#tf').focus()
})
$('#tf').keydown(function (e) {
var code = e.keyCode ? e.keyCode : e.which ? e.which : e.charCode;
var txt = $(this).val().trim()
// handle navigation between tags
if ((code === left || code === right) && txt.length === 0) {
if (!current_tag)
{
if (code === left)
current_tag = $('#tags_queue span').last()
else
current_tag = $('#tags_queue span').first()
if (current_tag.length > 0) current_tag.css('background-color', '#9FC2D6')
} else //current tag exists
{
if (code === left)
current_tag = current_tag.css('background-color', '#B8D0DE').prev()
else
current_tag = current_tag.css('background-color', '#B8D0DE').next()
if (current_tag.length > 0)
current_tag.css('background-color', '#9FC2D6')
// hit last/first, clean current_tag
else
{
current_tag.css('background-color', '#B8D0DE')
current_tag = null
}
}
}
});
$('#tf').keypress(function (e) {
var token = String.fromCharCode(e.which)
var code = e.keyCode ? e.keyCode : e.which ? e.which : e.charCode;
if (token.match(rexp) && (code !== del) && (code !== left) && (code !== right))
return false;
});
$('#tf').keyup(function (e) {
var code = e.keyCode ? e.keyCode : e.which ? e.which : e.charCode;
var txt = $(this).val().trim()
if (code === del && txt.length === 0 && current_tag) {
current_tag.remove()
current_tag = null
return
}
// clean current_tag, user is typing
if (current_tag && (code !== left) && (code != right))
{
current_tag.css('background-color', '#B8D0DE')
current_tag = null
}
if (txt.length > maxlen) txt = txt.substring(0, maxlen)
if (txt.match(rexp)) {-
$(this).val("")
return
} else if (code === space || code === comma) {
if (txt.length < minlen) return;
var tag = $('<span></span>', {
'class': 'tag'
}).html(txt).append($('<a></a>', {
'class': 'close_tag',
html: '&times',
click: function () {
$(this).parent().fadeOut(function(){
$(this).remove()
current_tag.css('background-color', '#B8D0DE')
current_tag = null
})
}
}))
$('#tags_queue').append(tag)
$(this).val("")
}
});
})
css
div#tags_container {
border: 1px solid #ccc;
padding-bottom: 5px;
border-radius: 5px;
background-color: beige;
overflow: hidden;
}
input#tf {
border: 1px solid orange !important;
outline: none !important;
background-color: transparent !important;
height: 30px;
margin-top: 2px;
padding-left: 5px;
}
a.close_tag {
margin-left: 5px;
color: #fff;
}
a.close_tag:hover {
cursor: pointer;
}
span.tag {
background-color: #B8D0DE;
color: #111;
margin-left: 5px;
margin-top: 5px;
padding: 5px;
float: left;
border-radius: 5px;
}
span.tag:hover {
background-color: #9FC2D6;
}
span#tags_queue {
margin-right: 5px;
vertical-align: middle;
}
The problem is, how can i handle the 'hidden' content using the arrows keys, the way SO does? It looks like i have to handle the cursor position inside the text-fields, and watch for arrow-left and arrow-right events...and there's also the click on the completed tags.
I can think of the following (anti-SO design) solutions:
remove white-space: nowrap from the tags_container div, and let
the div 'grow' as the user add more tags.
Add overflow: scroll to the tags_container div (very ugly!)
So, i appreciate any new ideas on how to approximate the SO tag-editor behaviour.
Thanks!
Reinvent the wheel is a bad practice : take a look at the excellent Tag-it jQuery plugin code, it implements the stuff you are working on.

Categories