I have two text input id: input1 and input2. I would like to simulate keypress on input1 to input2. I cannot copy values onblur because after simulation I shall change the value of input1. Could you please let me know how to do this in jQuery 1.6 or Javascript? I tried below, but this isn't working and changing the value i.e. $('#'+origid).val() returns blank.
$(".maskedinput").keyup(function (e) {
var value = $.trim($(this).val());
var origid = $(this).attr('origid');
var originalelemevt = jQuery.Event( "keypress" );
originalelemevt.which = e.which;
originalelemevt.keycode = e.keycode;
$('#'+origid).trigger( originalelemevt );
var newval = '';
if(value.length >=4){
var orignal = value.substring(0,value.length-4);
for(var i=0;i<orignal.length;i++)
newval +='*';
newval +=value.substring(orignal.length);
$(this).val(newval);
}
});
$(document).ready(function() {
$("#I1").keyup(function (e) {
var value = $.trim($(this).val());
var newval = '';
if(value.length >=4){
var orignal = value.substring(0,value.length-4);
for(var i=0;i<orignal.length;i++)
newval +='*';
newval +=value.substring(orignal.length);
$(this).val(newval);
}
$('#I2').val(e.target.value);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<form id='F1'>
<input id='I1'>
<input id='I2'>
</form>
This what I was looking for, keypress event on id1.
$("#id1").keypress(function(e) {
var inputkey = e.which || e.keyCode;
var result = getInputSelection(document.getElementById("id1"));
$("#id2").trigger("keypress")
.val(function(i, val) {
var key = e.which || e.keyCode;
// return this.value + String.fromCharCode(key);
return this.value.substr(0, result.start) + String.fromCharCode(key) + this.value.substr(result.end)
});
});
$("#id1").keyup(function(e) {
mask('id1');
});
$("#id1").keydown(function(e) {
var inputkey = e.which || e.keyCode;
//alert(inputkey);
if (inputkey == 8) {
e.preventDefault();
var new_val = replaceValue(inputkey);
//alert(new_val);
$("#id1").val(new_val);
$("#id2").val(new_val);
// mask('id1');
} else if (inputkey == 46) {
e.preventDefault();
var new_val = replaceValue(inputkey);
//alert(new_val);
$("#id1").val(new_val);
$("#id2").val(new_val);
// mask('id1');
}
});
function mask(elid) {
var $this = $('#' + elid);
$this.val($this.val().replace(/.(?=.{4})/g, '*'));
}
function replaceValue(inputkey) {
var result = getInputSelection(document.getElementById("id1"));
// alert("Backspace "+result.start +","+result.end);
var new_val = $("#id1").val();
if (result.start == result.end) {
if (inputkey == 8) {
new_val = $("#id2").val().substr(0, result.start - 1) + $("#id2").val().substr(result.end);
} else if (inputkey == 46) {
new_val = $("#id2").val().substr(0, result.start) + $("#id2").val().substr(result.end + 1);
}
} else {
new_val = $("#id2").val().substr(0, result.start) + $("#id2").val().substr(result.end);
}
return new_val;
}
function getInputSelection(el) {
var start = 0,
end = 0,
normalizedValue, range,
textInputRange, len, endRange;
if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
start = el.selectionStart;
end = el.selectionEnd;
} else {
range = document.selection.createRange();
if (range && range.parentElement() == el) {
len = el.value.length;
normalizedValue = el.value.replace(/\r\n/g, "\n");
// Create a working TextRange that lives only in the input
textInputRange = el.createTextRange();
textInputRange.moveToBookmark(range.getBookmark());
// Check if the start and end of the selection are at the very end
// of the input, since moveStart/moveEnd doesn't return what we want
// in those cases
endRange = el.createTextRange();
endRange.collapse(false);
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
start = end = len;
} else {
start = -textInputRange.moveStart("character", -len);
start += normalizedValue.slice(0, start).split("\n").length - 1;
if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
end = len;
} else {
end = -textInputRange.moveEnd("character", -len);
end += normalizedValue.slice(0, end).split("\n").length - 1;
}
}
}
}
return {
start: start,
end: end
};
}
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#banner-message {
background: #fff;
border-radius: 4px;
padding: 20px;
font-size: 25px;
text-align: center;
transition: all 0.2s;
margin: 0 auto;
width: 300px;
}
button {
background: #0084ff;
border: none;
border-radius: 5px;
padding: 8px 14px;
font-size: 15px;
color: #fff;
}
#banner-message.alt {
background: #0084ff;
color: #fff;
margin-top: 40px;
width: 200px;
}
#banner-message.alt button {
background: #fff;
color: #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="banner-message">
SSN:
<input type="text" id="id1" />
<input type="text" id="id2" style="display:none" />
</div>
Related
I was building a website and came across a problem.
The problem is, when users are asked to enter a price, they can type not only numbers but whatever they want. I want to restrict users to type numbers only in that input field. I've tried type=number and pattern="[0-9]+" attributes and gave it a style of appearence: textfield (Because it shows an uparrow and a downarrow when shown in browser) but it doesn't seem to work. I suppose there is a solution for this with javascript.
HTML :
<input class="input-price" type="number">
CSS:
input[type="number"] {
appearance: textfield;
}
input[type="number"] {
appearance: textfield;
}
<input class="input-price" type="number">
Hopefully, someone will give me a solution. Thanks in advance!
type="number" is only available to HTML5 compliant browsers. There is an answer available in an overflow already, for getting the result you are after using Javascript here.
I don't know what browser your users use that can bypass restrictions in the numerical input, but in the days when not all browsers supported type="number" I've used something like this:
const inputs = document.querySelectorAll('input[data-type="number"]');
for(let i = 0; i < inputs.length; i++)
{
inputs[i].addEventListener("input", onInput);
inputs[i].addEventListener("keydown", onKeydown);
inputs[i].nextSibling.addEventListener("mousedown", onMousedown);
inputs[i].nextSibling.addEventListener("mouseup", onMouseup);
}
function onInput(e)
{
clearTimeout(this._timer);
const input = e.target,
min = input.min === "" ? null : Number(input.min),
max = input.max === "" ? null : Number(input.max),
canMinus = min === null || min < 0,
canPoint = input.hasAttribute("nopoint") ? false : true;
let curStart = input.selectionStart,
dot = 0,
minus = 0,
i = 0,
timeout = null,
val = input.value;
val = val.replace(/[^0-9]/g, (char, pos) =>
{
if ( (char == "-" && canMinus && !(pos-i) && --minus)
|| ((char == "." || char == ",") && canPoint && pos && (pos-i > 1 || !minus) && !dot++))
{
return char;
}
if (i < curStart)
curStart--;
i++;
return "";
});
if (curStart < 0)
curStart = 0;
const isNumber = val.match(/[0-9]/);
if (isNumber && min !== null && val < min)
val = timeout = min;
if (isNumber && max !== null && val > max)
val = timeout = max;
const exec = () =>
{
input.value = val
input.selectionStart = curStart;
input.selectionEnd = curStart;
}
if (timeout === null)
return exec();
this._timer = setTimeout(exec, 1000);
}
function onKeydown(e)
{
const input = e.target,
min = input.min === "" ? null : Number(input.min),
max = input.max === "" ? null : Number(input.max),
step = input.step === "" ? 1 : Number(input.step),
keys = {ArrowUp: step, ArrowDown: -step};
if (keys[e.key])
{
let val = (keys[e.key] == ~~keys[e.key] ? ~~input.value : Number(input.value)) + keys[e.key];
if (min !== null && val < min)
val = min;
if (max !== null && val > max)
val = max;
input.value = val;
return e.preventDefault();
}
}
function onMousedown(e)
{
if (e.target.parentNode.previousSibling.tagName != "INPUT")
return;
const that = this,
obj = {
target: e.target.parentNode.previousSibling,
key: (e.target.previousSibling === null) ? "ArrowUp" : "ArrowDown",
preventDefault: ()=>{}
};
let time = 300;
!function loop()
{
onKeydown(obj);
that._timer = setTimeout(loop, time);
time = 30;
}();
}
function onMouseup(e)
{
clearTimeout(this._timer);
}
input[data-type="number"] {
appearance: textfield;
padding-right: 1.2em;
}
input[data-type="number"]:not(:focus):not(:hover) ~ span:not(:focus):not(:hover)
{
visibility: hidden;
}
input[data-type="number"] ~ span
{
float:right;
position: relative;
right: 1.8em;
top: 0.2em;
height: 1.8em;
width: 1.5em;
line-height: 1em;
font-size: 0.6em;
cursor: default;
display: grid;
background-color: #F1F1F1;
user-select: none;
}
input[data-type="number"] ~ span > span:nth-child(1):before,
input[data-type="number"] ~ span > span:nth-child(2):before
{
transform: scaleY(0.6);
display: block;
}
input[data-type="number"] ~ span > span:nth-child(1):before
{
content: "▲";
}
input[data-type="number"] ~ span > span:nth-child(2):before
{
content: "▼";
}
input[data-type="number"] ~ span > span:nth-child(1),
input[data-type="number"] ~ span > span:nth-child(2)
{
color: #505050;
width: 100%;
text-align: center;
}
input[data-type="number"] ~ span > span:nth-child(1):hover,
input[data-type="number"] ~ span > span:nth-child(2):hover
{
background-color: #D2D2D2;
}
input[data-type="number"] ~ span > span:nth-child(1):active,
input[data-type="number"] ~ span > span:nth-child(2):active
{
color: white;
background-color: #787878;
}
input[data-type="number"] ~ span > span:nth-child(1)
{
top: 0;
}
input[data-type="number"] ~ span > span:nth-child(2)
{
bottom: 0;
}
<table>
<tr>
<td>Native type="number"</td>
<td><input class="input-price" type="number"></td>
</tr>
<tr>
<td>Any number</td>
<td><input class="input-price" data-type="number"><span><span></span><span></span></span></td>
</tr>
<tr>
<td>Min 11 / max 123</td>
<td><input class="input-price" data-type="number" min="11" max="123"><span><span></span><span></span></span></td>
</tr>
<tr>
<td>No decimal point</td>
<td><input class="input-price" data-type="number" nopoint=""><span><span></span><span></span></span></td>
</tr>
</table>
I'm a self taught programmer and I got my hands on a TicTacToe project, but I got stucked at the following part.
I did a relatively working TicTacToe(inspired from youtube) then I wanted to do a responsive TicTacToe matrix that changes it's numbers from(0-9) in X's and O's in the console depending of the inputs of the first game. But now I'm stuck at trying to find a way to check the winners of the matrix oh and I'm trying to start the "checking" from the last X or O
Hopefully seeing the code is much more easier to understand.
I'd really really appreciate some help!
const statusDiv = document.querySelector('.status');
const resetDiv = document.querySelector('.reset');
const cellDivs = document.querySelectorAll('.game-cell');
// game constants
const xSymbol = '×';
const oSymbol = '○';
// game variables
let gameIsLive = true;
let xIsNext = true;
var currentPlayer = 0;
//Random generated
function getInputValue() {
document.getElementById("formInput").style.display = "none";
document.getElementById("container").style.display = "inline";
let player1Input = document.getElementById("player1Input").value;
let player2Input = document.getElementById("player2Input").value;
currentPlayer = 1;
var random = Math.random() * 100;
if (random <= 60) {
currentPlayer = 1;
statusDiv.innerHTML = player1Input + " turn";
statusDiv.style.color = "blue";
}
else {
currentPlayer = 2;
statusDiv.innerHTML = player2Input + " turn";
statusDiv.style.color = "red";
}
}
// statusDiv.style.filter= "green";
//functions
const letterToSymbol = (letter) => letter === 'x' ? xSymbol : oSymbol;
const handleWin = (letter) => {
gameIsLive = false;
if (currentPlayer === 1) {
statusDiv.innerHTML = player1Input.value + " has won!";
statusDiv.style.color = "blue";
} else {
statusDiv.innerHTML = player2Input.value + " has won!";
statusDiv.style.color = "red";
}
};
const checkGameStatus = () => {
const topLeft = cellDivs[0].classList[1];
const topMiddle = cellDivs[1].classList[1];
const topRight = cellDivs[2].classList[1];
const middleLeft = cellDivs[3].classList[1];
const middleMiddle = cellDivs[4].classList[1];
const middleRight = cellDivs[5].classList[1];
const bottomLeft = cellDivs[6].classList[1];
const bottomMiddle = cellDivs[7].classList[1];
const bottomRight = cellDivs[8].classList[1];
// check winner
if (topLeft && topLeft === topMiddle && topLeft === topRight) {
handleWin(topLeft);
cellDivs[0].classList.add('won');
cellDivs[1].classList.add('won');
cellDivs[2].classList.add('won');
} else if (middleLeft && middleLeft === middleMiddle && middleLeft === middleRight) {
handleWin(middleLeft);
cellDivs[3].classList.add('won');
cellDivs[4].classList.add('won');
cellDivs[5].classList.add('won');
} else if (bottomLeft && bottomLeft === bottomMiddle && bottomLeft === bottomRight) {
handleWin(bottomLeft);
cellDivs[6].classList.add('won');
cellDivs[7].classList.add('won');
cellDivs[8].classList.add('won');
} else if (topLeft && topLeft === middleLeft && topLeft === bottomLeft) {
handleWin(topLeft);
cellDivs[0].classList.add('won');
cellDivs[3].classList.add('won');
cellDivs[6].classList.add('won');
} else if (topMiddle && topMiddle === middleMiddle && topMiddle === bottomMiddle) {
handleWin(topMiddle);
cellDivs[1].classList.add('won');
cellDivs[4].classList.add('won');
cellDivs[7].classList.add('won');
} else if (topRight && topRight === middleRight && topRight === bottomRight) {
handleWin(topRight);
cellDivs[2].classList.add('won');
cellDivs[5].classList.add('won');
cellDivs[8].classList.add('won');
} else if (topLeft && topLeft === middleMiddle && topLeft === bottomRight) {
handleWin(topLeft);
cellDivs[0].classList.add('won');
cellDivs[4].classList.add('won');
cellDivs[8].classList.add('won');
} else if (topRight && topRight === middleMiddle && topRight === bottomLeft) {
handleWin(topRight);
cellDivs[2].classList.add('won');
cellDivs[4].classList.add('won');
cellDivs[6].classList.add('won');
} else if (topLeft && topMiddle && topRight && middleLeft && middleMiddle && middleRight && bottomLeft && bottomMiddle && bottomRight) {
gameIsLive = false;
statusDiv.innerHTML = 'Game is tied!';
} else {
xIsNext = !xIsNext;
if (currentPlayer === 2) {
statusDiv.innerHTML = player1Input.value + ` turn`;
statusDiv.style.color = "blue";
currentPlayer = 1;
} else {
currentPlayer = 2;
statusDiv.style.color = "red";
statusDiv.innerHTML = player2Input.value + ` turn`;
}
}
};
// event Handlers
const handleReset = () => {
document.getElementById("formInput").style.display = "inline";
document.getElementById("container").style.display = "none";
xIsNext = true;
statusDiv.innerHTML = `Press Start Game`;
for (const cellDiv of cellDivs) {
cellDiv.classList.remove('x');
cellDiv.classList.remove('o');
cellDiv.classList.remove('won');
document.location.reload()
}
gameIsLive = true;
};
const handleCellClick = (e) => {
const classList = e.target.classList;
if (!gameIsLive || classList[1] === 'x' || classList[1] === 'o') {
return;
}
if (currentPlayer === 1) {
classList.add('playerOneColour');
} else {
classList.add('playerTwoColour');
}
if (xIsNext) {
classList.add("x");
} else {
classList.add('o');
}
checkGameStatus();
};
// event listeners
resetDiv.addEventListener('click', handleReset);
for (const cellDiv of cellDivs) {
cellDiv.addEventListener('click', handleCellClick);
cellDiv.addEventListener('click', handleCellSelection);
}
//Matrix Builder
var counter = 0;
var matrix = [];
for (var i = 0; i < 3; i++) {
matrix[i] = [];
for (var j = 0; j < 3; j++) {
matrix[i][j] = [];
matrix[i][j] = counter;
++counter;
}
}
// 0,1,2,3,4,5,6,7,8
// 0,1,2,0,1,2,0,1,2
var playerCounter = 1;
var currentPlayer = 1;
function handleCellSelection(e) {
playerCounter++;
let htmlElement = e.target;
let cellType = htmlElement.getAttribute("data-cell");
let reuseNTI = numberToIndexes(cellType);
let matrixIndex = indexInMatrix(reuseNTI[0], reuseNTI[1]);
let isWinnerFunction = isPlayerWinner(matrix);
function indexInMatrix(index1, index2) {
if (currentPlayer === 2) {
return matrix[index1].splice([index2], 1, "X")
currentPlayer = 1;
} else {
return matrix[index1].splice([index2], 1, "O");
currentPlayer = 2;
}
}
function isPlayerWinner(matrix, currentPlayer) {
if (playerCounter < 6) {
return;
} else {
var xSign = "X";
var oSign = "O";
let rowX = 0;
let rowO = 0;
//TO DO CHECK COLUMN
for (var i = 0; i < matrix[0].length; i++) {
if (xSign === matrix[i][reuseNTI[0]]) {
rowX++
} else if (oSign === matrix[i][reuseNTI[0]]) {
rowO++
console.log(rowO)
}
// console.log(matrix[i, 0].lastIndexOf("X")) ; //000↓,111↓,222↓
// console.log(matrix[i, 0].lastIndexOf("O"));
}
//TO DO CHECK ROW
for (var i = 0; i < matrix[0].length; i++) {
if (xSign === matrix[reuseNTI[0][i]]) {
} else if (oSign === matrix[reuseNTI[0]][i]) {
}
// console.log(matrix[0, i].lastIndexOf("X")) ; //row is 000->,111->,222->
// console.log(matrix[0, i].lastIndexOf("O"));
}
//TO DO CHECK PRIMARY DIAGONAL
for (var i = 0; i < matrix[0].length; i++) {
if (xSign === matrix[i][i]) {
} else if (oSign === matrix[i][i]) {
}
// matrix[i][i];
// console.log(matrix[i, i].lastIndexOf("X")); //012->,012->,012->
// console.log(matrix[i, i].lastIndexOf("O"));
}
//TO DO CHECK SECONDARY DIAGONAL
for (var i = 0; i < matrix[0].length; i++) {
if (xSign === matrix[i][matrix.length - 1 - i]) {
} else if (oSign === matrix[i][matrix.length - 1 - i]) {
}
// matrix[i][matrix.length - 1 - i];
// console.log(matrix[i, matrix.length - 1 - i].lastIndexOf("X"));
// console.log(matrix[i, [matrix.length - 1 - i]].lastIndexOf("O"));
}
}
}
isPlayerWinner(matrix);
console.log(matrix);
}
function numberToIndexes(number) {
let row = Math.floor(number / 3);
let column = number % 3;
return [row, column];
}
var cellSize = 100;
var cellSpace = 10;
var matrixRows = matrix.length;
var matrixColumns = matrix[0].length;
for (var i = 0; i < matrixRows; i++) {
for (var j = 0; j < matrixColumns; j++) {
var cell = document.createElement("div");
cell.setAttribute("class", "cell");
matrixStage.appendChild(cell);
cell.style.top = i * (cellSize + cellSpace) + "px";
cell.style.left = j * (cellSize + cellSpace) + "px";
}
}
function newMatrixGrid() {
var grid3x3 = document.getElementById("matrixMaker").value;
if (grid3x3 == "3") {
var matrixStage = document.querySelector("#matrixStage").style.display = "block";
} else {
matrixStage = document.querySelector("#matrixStage").style.display = "none";
}
}
#player1{
color: blue;
}
#player2{
color: red;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
color: #545454;
display: grid;
font-family: sans-serif;
justify-content: center;
}
.container {
background: #ffffff;
margin: 50px;
padding: 50px;
border-radius: 25px;
}
.title {
text-align: center;
}
.title span {
color: #F2EBD3;
}
.status-action {
color:blue;
display: flex;
margin-top: 25px;
font-size: 25px;
justify-content: space-around;
height: 30px;
}
.status span {
color: red;
}
.reset {
color: black;
cursor: pointer;
}
.reset:hover {
color: #10976c;
}
.game-grid {
background: #000000;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
grid-gap: 15px;
margin-top: 50px;
}
.game-cell {
background:white;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
height: 200px;
width: 200px;
}
.playerOneColour{
filter: invert(9%) sepia(100%) saturate(7261%) hue-rotate(247deg) brightness(91%) contrast(146%);
}
.playerTwoColour{
filter: invert(14%) sepia(95%) saturate(6042%) hue-rotate(358deg) brightness(109%) contrast(117%);
}
.x {
color: transparent;
cursor: default;
}
.o {
color: transparent;
cursor: default;
}
.x::after {
background-image: url(../Resources/X.png);
background-size:contain;
background-repeat: no-repeat;
margin-top: 80px;
content: '×';
}
.o::after {
background-image: url(../Resources/O.png);
background-size:contain;
background-repeat: no-repeat;
margin-top: 100px;
content: '○';
}
.won::after {
filter: invert(100%) sepia() saturate(10000%) hue-rotate(0deg);
}
#media only screen and (min-width: 1024px) {
.game-grid {
margin-top: 25px;
grid-gap: 10px;
}
.game-cell {
height: 150px;
width: 150px;
}
.x::after {
font-size: 150px;
}
.o::after {
font-size: 175px;
}
}
#media only screen and (max-width: 540px) {
.container {
margin: 25px;
padding: 25px;
}
.game-cell {
height: 100px;
width: 100px;
}
.x::after {
font-size: 100px;
}
.o::after {
font-size: 125px;
}
}
#matrixStage{
position:relative;
}
.cell
{
position: absolute;
width: 100px;
height: 100px;
border: 1px solid black;
background-color: white;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Play XO</title>
<link rel="StyleSheet" href="Styles/index.css">
</head>
<body>
<form id="formInput">
<h1>Play X O </h1><br>
<label for="player1" id="player1">Player 1:</label><br>
<input type="text" id="player1Input"><br>
<label for="player1" id="player2">Player 2:</label><br>
<input type="text" id="player2Input"><br><br>
<button type="button" onclick="getInputValue();"> Start Game</button>
</form>
<br>
</form>
<div class="container" style="display:none" id="container">
<h1 class="title">Play X O </h1>
<div class="status-action">
<div class="status">Player 1 turn</div>
<div class="reset">Reset</div>
</div>
<div class="game-grid">
<div class="game-cell" data-cell="0"></div>
<div class="game-cell" data-cell="1"></div>
<div class="game-cell" data-cell="2"></div>
<div class="game-cell" data-cell="3"></div>
<div class="game-cell" data-cell="4"></div>
<div class="game-cell" data-cell="5"></div>
<div class="game-cell" data-cell="6"></div>
<div class="game-cell" data-cell="7"></div>
<div class="game-cell" data-cell="8"></div>
</div>
</div>
<select name="matrix-size" id="matrixMaker" onchange="newMatrixGrid()">
<option value="3">3X3</option>
<option value="4">4X4</option>
<option value="5">5X5</option>
</select>
</br></br></br>
<div id="matrixStage"></div>
<script src="Scripts/index.js"></script>
</body>
</html>
I think you can simplify your isPlayerWinner function by ignoring if you are looking for Xs or Os. You must assume the last token used was not the winner in the previous turn or the game would already be finished.
So if you have matrix = [[0,1,2],[3,4,5],[6,7,8]] and the numbers will be progressively replaced by x or o just check if all items in a combination are equal
function isPlayerWinner(){
for(let i=0; i<3; i++){
const row = matrix[i][0] === matrix[i][1] && matrix[i][1] === matrix[i][2];
const column = matrix[0][i] === matrix[1][i] && matrix[1][i] === matrix[2][i];
if(column || row){
return true
}
}
if(matrix[0][0] === matrix[1][1] && matrix[1][1] === matrix[2][2]){
return true;
}
if(matrix[0][2] === matrix[1][1] && matrix[1][1] === matrix[2][0]){
return true;
}
return false
}
When I'm sending this ajax request:
$.ajax({
url: "{{URL::to('admin/repcasetracker/getdiscount')}}",
data: {
serialnumber: serialnumberdata,
},
success: function (data) {
console.log(data);
}
});
Controller:
public function getdiscount(Request $request) {
print_r("hi");
dd($request->all());
}
Then it give me in controller side this type of response:
Sfdump = window.Sfdump || (function (doc) { var refStyle =
doc.createElement('style'), rxEsc = /([.+?^${}()|[]/\])/g, idRx =
/\bsf-dump-\d+-ref[012]\w+\b/, keyHint = 0 <=
navigator.platform.toUpperCase().indexOf('MAC') ? 'Cmd' : 'Ctrl',
addEventListener = function (e, n, cb) { e.addEventListener(n, cb,
false); }; (doc.documentElement.firstElementChild ||
doc.documentElement.children[0]).appendChild(refStyle); if
(!doc.addEventListener) { addEventListener = function (element,
eventName, callback) { element.attachEvent('on' + eventName, function
(e) { e.preventDefault = function () {e.returnValue = false;};
e.target = e.srcElement; callback(e); }); }; } function toggle(a,
recursive) { var s = a.nextSibling || {}, oldClass = s.className,
arrow, newClass; if (/\bsf-dump-compact\b/.test(oldClass)) { arrow =
'▼'; newClass = 'sf-dump-expanded'; } else if
(/\bsf-dump-expanded\b/.test(oldClass)) { arrow = '▶'; newClass
= 'sf-dump-compact'; } else { return false; } a.lastChild.innerHTML = arrow; s.className =
s.className.replace(/\bsf-dump-(compact|expanded)\b/, newClass); if
(recursive) { try { a = s.querySelectorAll('.'+oldClass); for (s = 0;
s < a.length; ++s) { if (-1 == a[s].className.indexOf(newClass)) {
a[s].className = newClass; a[s].previousSibling.lastChild.innerHTML =
arrow; } } } catch (e) { } } return true; }; function collapse(a,
recursive) { var s = a.nextSibling || {}, oldClass = s.className; if
(/\bsf-dump-expanded\b/.test(oldClass)) { toggle(a, recursive); return
true; } return false; }; function expand(a, recursive) { var s =
a.nextSibling || {}, oldClass = s.className; if
(/\bsf-dump-compact\b/.test(oldClass)) { toggle(a, recursive); return
true; } return false; }; function collapseAll(root) { var a =
root.querySelector('a.sf-dump-toggle'); if (a) { collapse(a, true);
expand(a); return true; } return false; } function reveal(node) { var
previous, parents = []; while ((node = node.parentNode || {}) &&
(previous = node.previousSibling) && 'A' === previous.tagName) {
parents.push(previous); } if (0 !== parents.length) {
parents.forEach(function (parent) { expand(parent); }); return true; }
return false; } function highlight(root, activeNode, nodes) {
resetHighlightedNodes(root); Array.from(nodes||[]).forEach(function
(node) { if (!/\bsf-dump-highlight\b/.test(node.className)) {
node.className = node.className + ' sf-dump-highlight'; } }); if
(!/\bsf-dump-highlight-active\b/.test(activeNode.className)) {
activeNode.className = activeNode.className + '
sf-dump-highlight-active'; } } function resetHighlightedNodes(root) {
Array.from(root.querySelectorAll('.sf-dump-str, .sf-dump-key,
.sf-dump-public, .sf-dump-protected,
.sf-dump-private')).forEach(function (strNode) { strNode.className =
strNode.className.replace(/\bsf-dump-highlight\b/, '');
strNode.className =
strNode.className.replace(/\bsf-dump-highlight-active\b/, ''); }); }
return function (root, x) { root = doc.getElementById(root); var
indentRx = new RegExp('^('+(root.getAttribute('data-indent-pad') || '
').replace(rxEsc, '\$1')+')+', 'm'), options =
{"maxDepth":1,"maxStringLength":160,"fileLinkFormat":false}, elt =
root.getElementsByTagName('A'), len = elt.length, i = 0, s, h, t = [];
while (i < len) t.push(elt[i++]); for (i in x) { options[i] = x[i]; }
function a(e, f) { addEventListener(root, e, function (e) { if ('A' ==
e.target.tagName) { f(e.target, e); } else if ('A' ==
e.target.parentNode.tagName) { f(e.target.parentNode, e); } else if
(e.target.nextElementSibling && 'A' ==
e.target.nextElementSibling.tagName) { f(e.target.nextElementSibling,
e, true); } }); }; function isCtrlKey(e) { return e.ctrlKey ||
e.metaKey; } function xpathString(str) { var parts =
str.match(/[^'"]+|['"]/g).map(function (part) { if ("'" == part) {
return '"\'"'; } if ('"' == part) { return "'\"'"; } return "'" + part
+ "'"; }); return "concat(" + parts.join(",") + ", '')"; } addEventListener(root, 'mouseover', function (e) { if ('' !=
refStyle.innerHTML) { refStyle.innerHTML = ''; } }); a('mouseover',
function (a, e, c) { if (c) { e.target.style.cursor = "pointer"; }
else if (a = idRx.exec(a.className)) { try { refStyle.innerHTML =
'pre.sf-dump .'+a[0]+'{background-color: #B729D9; color: #FFF
!important; border-radius: 2px}'; } catch (e) { } } }); a('click',
function (a, e, c) { if (/\bsf-dump-toggle\b/.test(a.className)) {
e.preventDefault(); if (!toggle(a, isCtrlKey(e))) { var r =
doc.getElementById(a.getAttribute('href').substr(1)), s =
r.previousSibling, f = r.parentNode, t = a.parentNode;
t.replaceChild(r, a); f.replaceChild(a, s); t.insertBefore(s, r); f =
f.firstChild.nodeValue.match(indentRx); t =
t.firstChild.nodeValue.match(indentRx); if (f && t && f[0] !== t[0]) {
r.innerHTML = r.innerHTML.replace(new RegExp('^'+f[0].replace(rxEsc,
'\$1'), 'mg'), t[0]); } if (/\bsf-dump-compact\b/.test(r.className))
{ toggle(s, isCtrlKey(e)); } } if (c) { } else if (doc.getSelection) {
try { doc.getSelection().removeAllRanges(); } catch (e) {
doc.getSelection().empty(); } } else { doc.selection.empty(); } } else
if (/\bsf-dump-str-toggle\b/.test(a.className)) { e.preventDefault();
e = a.parentNode.parentNode; e.className =
e.className.replace(/\bsf-dump-str-(expand|collapse)\b/,
a.parentNode.className); } }); elt =
root.getElementsByTagName('SAMP'); len = elt.length; i = 0; while (i <
len) t.push(elt[i++]); len = t.length; for (i = 0; i < len; ++i) { elt
= t[i]; if ('SAMP' == elt.tagName) { elt.className = 'sf-dump-expanded'; a = elt.previousSibling || {}; if ('A' !=
a.tagName) { a = doc.createElement('A'); a.className = 'sf-dump-ref';
elt.parentNode.insertBefore(a, elt); } else { a.innerHTML += ' '; }
a.title = (a.title ? a.title+'\n[' : '[')+keyHint+'+click] Expand all
children'; a.innerHTML += '▼'; a.className += '
sf-dump-toggle'; x = 1; if ('sf-dump' != elt.parentNode.className) { x
+= elt.parentNode.getAttribute('data-depth')/1; } elt.setAttribute('data-depth', x); if (x > options.maxDepth) {
toggle(a); } } else if (/\bsf-dump-ref\b/.test(elt.className) && (a =
elt.getAttribute('href'))) { a = a.substr(1); elt.className += ' '+a;
if (/[[{]$/.test(elt.previousSibling.nodeValue)) { a = a !=
elt.nextSibling.id && doc.getElementById(a); try { s = a.nextSibling;
elt.appendChild(a); s.parentNode.insertBefore(a, s); if
(/^[##]/.test(elt.innerHTML)) { elt.innerHTML += '
▶'; } else { elt.innerHTML =
'▶'; elt.className = 'sf-dump-ref'; } elt.className
+= ' sf-dump-toggle'; } catch (e) { if ('&' == elt.innerHTML.charAt(0)) { elt.innerHTML = '…'; elt.className =
'sf-dump-ref'; } } } } } if (doc.evaluate && Array.from &&
root.children.length > 1) { root.setAttribute('tabindex', 0);
SearchState = function () { this.nodes = []; this.idx = 0; };
SearchState.prototype = { next: function () { if (this.isEmpty()) {
return this.current(); } this.idx = this.idx < (this.nodes.length - 1)
? this.idx + 1 : this.idx; return this.current(); }, previous:
function () { if (this.isEmpty()) { return this.current(); } this.idx
= this.idx > 0 ? this.idx - 1 : this.idx; return this.current(); }, isEmpty: function () { return 0 === this.count(); }, current: function
() { if (this.isEmpty()) { return null; } return this.nodes[this.idx];
}, reset: function () { this.nodes = []; this.idx = 0; }, count:
function () { return this.nodes.length; }, }; function
showCurrent(state) { var currentNode = state.current(); if
(currentNode) { reveal(currentNode); highlight(root, currentNode,
state.nodes); } counter.textContent = (state.isEmpty() ? 0 : state.idx
+ 1) + ' of ' + state.count(); } var search = doc.createElement('div'); search.className = 'sf-dump-search-wrapper
sf-dump-search-hidden'; search.innerHTML = ' 0 of
0</span> </svg> </button> </svg> </button> '; root.insertBefore(search, root.firstChild); var state = new SearchState(); var searchInput =
search.querySelector('.sf-dump-search-input'); var counter =
search.querySelector('.sf-dump-search-count'); var searchInputTimer =
0; var previousSearchQuery = ''; addEventListener(searchInput,
'keyup', function (e) { var searchQuery = e.target.value; / Don't
perform anything if the pressed key didn't change the query / if
(searchQuery === previousSearchQuery) { return; } previousSearchQuery
= searchQuery; clearTimeout(searchInputTimer); searchInputTimer = setTimeout(function () { state.reset(); collapseAll(root);
resetHighlightedNodes(root); if ('' === searchQuery) {
counter.textContent = '0 of 0'; return; } var xpathResult =
doc.evaluate('//pre[#id="' + root.id + '"]//span[#class="sf-dump-str"
or #class="sf-dump-key" or #class="sf-dump-public" or
#class="sf-dump-protected" or
#class="sf-dump-private"][contains(child::text(), ' +
xpathString(searchQuery) + ')]', document, null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE, null); while (node =
xpathResult.iterateNext()) state.nodes.push(node); showCurrent(state);
}, 400); });
Array.from(search.querySelectorAll('.sf-dump-search-input-next,
.sf-dump-search-input-previous')).forEach(function (btn) {
addEventListener(btn, 'click', function (e) { e.preventDefault(); -1
!== e.target.className.indexOf('next') ? state.next() :
state.previous(); searchInput.focus(); collapseAll(root);
showCurrent(state); }) }); addEventListener(root, 'keydown', function
(e) { var isSearchActive =
!/\bsf-dump-search-hidden\b/.test(search.className); if ((114 ===
e.keyCode && !isSearchActive) || (isCtrlKey(e) && 70 === e.keyCode)) {
/ F3 or CMD/CTRL + F / e.preventDefault(); search.className =
search.className.replace(/\bsf-dump-search-hidden\b/, '');
searchInput.focus(); } else if (isSearchActive) { if (27 ===
e.keyCode) { / ESC key / search.className += '
sf-dump-search-hidden'; e.preventDefault();
resetHighlightedNodes(root); searchInput.value = ''; } else if (
(isCtrlKey(e) && 71 === e.keyCode) / CMD/CTRL + G / || 13 ===
e.keyCode / Enter / || 114 === e.keyCode / F3 */ ) {
e.preventDefault(); e.shiftKey ? state.previous() : state.next();
collapseAll(root); showCurrent(state); } } }); } if (0 >=
options.maxStringLength) { return; } try { elt =
root.querySelectorAll('.sf-dump-str'); len = elt.length; i = 0; t =
[]; while (i < len) t.push(elt[i++]); len = t.length; for (i = 0; i <
len; ++i) { elt = t[i]; s = elt.innerText || elt.textContent; x =
s.length - options.maxStringLength; if (0 < x) { h = elt.innerHTML;
elt[elt.innerText ? 'innerText' : 'textContent'] = s.substring(0,
options.maxStringLength); elt.className += ' sf-dump-str-collapse';
elt.innerHTML = ''+h+'
◀'+ ''+elt.innerHTML+'
▶'; } } } catch (e) { } }; })(document);
pre.sf-dump { display: block; white-space: pre;
padding: 5px; } pre.sf-dump:after { content: ""; visibility: hidden;
display: block; height: 0; clear: both; } pre.sf-dump span { display:
inline; } pre.sf-dump .sf-dump-compact { display: none; } pre.sf-dump
abbr { text-decoration: none; border: none; cursor: help; }
pre.sf-dump a { text-decoration: none; cursor: pointer; border: 0;
outline: none; color: inherit; } pre.sf-dump .sf-dump-ellipsis {
display: inline-block; overflow: visible; text-overflow: ellipsis;
max-width: 5em; white-space: nowrap; overflow: hidden; vertical-align:
top; } pre.sf-dump .sf-dump-ellipsis+.sf-dump-ellipsis { max-width:
none; } pre.sf-dump code { display:inline; padding:0; background:none;
} .sf-dump-str-collapse .sf-dump-str-collapse { display: none; }
.sf-dump-str-expand .sf-dump-str-expand { display: none; }
.sf-dump-public.sf-dump-highlight,
.sf-dump-protected.sf-dump-highlight,
.sf-dump-private.sf-dump-highlight, .sf-dump-str.sf-dump-highlight,
.sf-dump-key.sf-dump-highlight { background: rgba(111, 172, 204, 0.3);
border: 1px solid #7DA0B1; border-radius: 3px; }
.sf-dump-public.sf-dump-highlight-active,
.sf-dump-protected.sf-dump-highlight-active,
.sf-dump-private.sf-dump-highlight-active,
.sf-dump-str.sf-dump-highlight-active,
.sf-dump-key.sf-dump-highlight-active { background: rgba(253, 175, 0,
0.4); border: 1px solid #ffa500; border-radius: 3px; } pre.sf-dump .sf-dump-search-hidden { display: none; } pre.sf-dump
.sf-dump-search-wrapper { float: right; font-size: 0; white-space:
nowrap; max-width: 100%; text-align: right; } pre.sf-dump
.sf-dump-search-wrapper > * { vertical-align: top; box-sizing:
border-box; height: 21px; font-weight: normal; border-radius: 0;
background: #FFF; color: #757575; border: 1px solid #BBB; }
pre.sf-dump .sf-dump-search-wrapper > input.sf-dump-search-input {
padding: 3px; height: 21px; font-size: 12px; border-right: none;
width: 140px; border-top-left-radius: 3px; border-bottom-left-radius:
3px; color: #000; } pre.sf-dump .sf-dump-search-wrapper >
.sf-dump-search-input-next, pre.sf-dump .sf-dump-search-wrapper >
.sf-dump-search-input-previous { background: #F2F2F2; outline: none;
border-left: none; font-size: 0; line-height: 0; } pre.sf-dump
.sf-dump-search-wrapper > .sf-dump-search-input-next {
border-top-right-radius: 3px; border-bottom-right-radius: 3px; }
pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next >
svg, pre.sf-dump .sf-dump-search-wrapper >
.sf-dump-search-input-previous > svg { pointer-events: none; width:
12px; height: 12px; } pre.sf-dump .sf-dump-search-wrapper >
.sf-dump-search-count { display: inline-block; padding: 0 5px; margin:
0; border-left: none; line-height: 21px; font-size: 12px;
}pre.sf-dump, pre.sf-dump .sf-dump-default{background-color:#fff;
color:#222; line-height:1.2em; font-weight:normal; font:12px Monaco,
Consolas, monospace; word-wrap: break-word; white-space: pre-wrap;
position:relative; z-index:100000}pre.sf-dump
.sf-dump-num{color:#a71d5d}pre.sf-dump
.sf-dump-const{color:#795da3}pre.sf-dump
.sf-dump-str{color:#df5000}pre.sf-dump
.sf-dump-cchr{color:#222}pre.sf-dump
.sf-dump-note{color:#a71d5d}pre.sf-dump
.sf-dump-ref{color:#a0a0a0}pre.sf-dump
.sf-dump-public{color:#795da3}pre.sf-dump
.sf-dump-protected{color:#795da3}pre.sf-dump
.sf-dump-private{color:#795da3}pre.sf-dump
.sf-dump-meta{color:#b729d9}pre.sf-dump
.sf-dump-key{color:#df5000}pre.sf-dump
.sf-dump-index{color:#a71d5d}array:1 [ "serialnumber" => "ASDQ13"]Sfdump("sf-dump-2124159715")
You need to use
return $request->all();
instead of
dd($request->all());
in your controller function.
return $request->all(); just return the response with your $request data.
Hope this helps you!
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.
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: '×',
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.