Implementing Hashtags using Jquery - javascript

What I want to do is basically is that whenever I write anything that starts with a #, the color of the tagged string should change to some other color, say blue, immediately. And when I press space to end the string, the color should change back to black. I tried a logic like this on a contenteditable div:
if (# is pressed)
hashtagging = true
append "<span>" to div
if (space is pressed and hashtagging is true)
hashtagging = false
append "</span>" to div
This is not working as expected.

Something like this should do:
$(function() {
var hashtags = false;
$(document).on('keydown', '#myInputField', function (e) {
arrow = {
hashtag: 51,
space: 32
};
var input_field = $(this);
switch (e.which) {
case arrow.hashtag:
input_field.val(input_field.val() + "<span class='highlight'>");
hashtags = true;
break;
case arrow.space:
if(hashtags) {
input_field.val(input_field.val() + "</span>");
hashtags = false;
}
break;
}
});
});
Now this code checks on keydown if the hashtag or space is pressed and adds a span with a class for styling to it. Reason for checking for keydown instead of keyup is to add the tags before the actual input is added to the textfield. I used a text-field as input, but modify it with whatever you need.

Here's a working example, done by incorporating the solution given by Sondre with the solution by Mr_Green (Set the caret position always to end in contenteditable div) to place the caret at the end.
http://jsfiddle.net/344m4/1/
var hashTagList = [];
function logHashList(){
hashTagList = [];
$('.highlight').each(function(){
hashTagList.push(this.innerHTML);
});
for(var i=0;i<hashTagList.length;i++){
alert(hashTagList[i]);
}
if(hashTagList.length==0){
alert('You have not typed any hashtags');
}
}
$(function() {
var hashtags = false;
$(document).on('keydown', '#example-one', function (e) {
arrow = {
hashtag: 51,
space: 32
};
var input_field = $(this);
switch (e.which) {
case arrow.hashtag:
e.preventDefault();
input_field.html(input_field.html() + "<span class='highlight'>#");
placeCaretAtEnd(this);
hashtags = true;
break;
case arrow.space:
if(hashtags) {
e.preventDefault();
input_field.html(input_field.html() + "</span> ");
placeCaretAtEnd(this);
hashtags = false;
}
break;
}
});
});
function placeCaretAtEnd(el) {
el.focus();
if (typeof window.getSelection != "undefined" && typeof document.createRange != "undefined") {
var range = document.createRange();
range.selectNodeContents(el);
range.collapse(false);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (typeof document.body.createTextRange != "undefined") {
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.collapse(false);
textRange.select();
}
}

Related

Validate letters in real time and manipulate them

I've a div with contenteditable and I'm trying to manipulate the array of this div to check if each letter written inside it, is the same as the letter on another text, based on the index.
The validation is done, I can check it, my problem is that, I need to change the letter color to red, if the letter don't validate. And I'm having trouble inserting a span with the class that I want.
Anyone have a sugestion?
Code follows:
timer.addEventListener('secondsUpdated', function (e) {
$('#countdown .values').html(timer.getTimeValues().toString(['minutes', 'seconds']));
if ($('.true-textarea').contents().get(0)) {
var textResult = $(".true-textarea").contents().get(0).nodeValue;
var textSize = textResult().length - 1;
}
$(".true-textarea").on("keypress", function(e) {
var c = String.fromCharCode(e.which);
e.preventDefault();
$(".true-textarea").html("");
if (c != textFake[textSize]) {
$(".true-textarea").addClass("red-border");
cls = "color-red";
} else {
cls = "color-purple";
$(".true-textarea").removeClass("red-border");
}
console.log('result', textResult);
console.log('size', textSize)
res += "<span class='"+cls+"'>"+c+"</span>";
cls = "";
$(".true-textarea").html(res);
});
});
So after hours trying to figure this out I came up if this code.
Used some examples that I saw in around the internet, fixed some problems, and it's working with the following code:
function focusAtEnd(el) {
el.focus();
if (typeof window.getSelection != "undefined"
&& typeof document.createRange != "undefined") {
var range = document.createRange();
range.selectNodeContents(el);
range.collapse(false);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (typeof document.body.createTextRange != "undefined") {
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.collapse(false);
textRange.select();
}
}
$('.true-textarea').unbind();
$('.true-textarea').focus();
timer.start({countdown: true, startValues: {seconds: 60}});
$('#countdown .values').html(timer.getTimeValues().toString(['minutes', 'seconds']));
var res = "", cls = "";
textResult.on("keypress", function(e){
textResult.find('br').remove();
var c = String.fromCharCode(e.which);
e.preventDefault();
res = textResult.html();
textSize = textResult.text().length;
if (c === textFake[textSize]) {
cls = "color-purple";
} else {
cls = "color-red";
}
res += "<span class='"+cls+"'>"+c+"</span>";
var del = false;
var lastFocused;
cls = "";
textResult.html(res);
focusAtEnd($(this).get(0));
})

Get start and end of a selection using javascript

i have an html string like this:
<div id="div">Hi how are<span>you?</span> Fine</div>
The text will appear "Hi how are you? Fine".
I would like to select a part of the string using mouse and get the beginning and the end
of the selection looking from the full text string.
For example, if i select "you", i would like to obtain start=11 and end=14;
if i select "are you?", i would like to obtain start=7 and end=15.
I wrote this to obtain the selection:
function getSel() {
console.log(navigator.appCodeName);
if (window.getSelection) {
return window.getSelection();
} else if (document.getSelection) {
return document.getSelection();
} else if (document.selection) {
return document.selection.createRange().text;
}
}
And this code to obtain start and end, but it doesn't work:
$("#div").on('mouseup', function(e){
var text=getSel();
if(text.anchorNode === text.focusNode){
var n = {
node: text.anchorNode.parentNode.id,
start: text.anchorOffset,
end: text.focusOffset
}
//selection from right to left
if(n.start>=n.end) {
var tmp;
tmp=n.start;
n.start=n.end;
n.end=tmp;
}
}
else console.log("error in selection");
});
Your selector is wrong. $('#div') actually selects for any elements that have id='div'.
I have made an example of how it's done. If I am not mistaken of what you're trying to achieve.
function getSelectionText() {
var text = "";
if (window.getSelection) {
text = window.getSelection().toString();
} else if (document.selection && document.selection.type != "Control") {
text = document.selection.createRange().text;
}
return text;
}
$(function(){
$("#div").on('mouseup', function(e){
var thisText = $(this).text();
var selectedText = getSelectionText();
var start = thisText.indexOf(selectedText);
var end = start + selectedText.length;
if (start >= 0 && end >= 0){
console.log("start: " + start);
console.log("end: " + end);
}
});
});
Fiddle

Append input with defined text in textfield

What I'm trying to do is to append .com in textfield during user input. Textfield will be empty and .com will be shown during typing domain name. Here is my not working code:
HTML
Enter domain name: <input type="text" id="domain">
Javascript
$(document).ready(function(){
$("input").keypress(function(){
$("#domain").val(this.value + ".com");
});
});
Not working demo:
http://jsfiddle.net/UUzux/25/
Thanks in advance.
I thought this was a great question. For a sleek solution, you could use the following code taken from
Set keyboard caret position in html textbox
to manually set the caret position in the input field:
function setCaretPosition(elemId, caretPos) {
var el = document.getElementById(elemId);
el.value = el.value;
if (el !== null) {
if (el.createTextRange) {
var range = el.createTextRange();
range.move('character', caretPos);
range.select();
return true;
} else {
if (el.selectionStart || el.selectionStart === 0) {
el.focus();
el.setSelectionRange(caretPos, caretPos);
return true;
} else { // fail
el.focus();
return false;
}
}
}
}
And then you'd implement it as follows:
$("input").keyup(function () {
var val = $("#domain").val();
val = val.replace(/\..*/g, ''); // replace this with whatever regex you need to deny whatever input you want.
$("#domain").val(val + ".com");
var caretPos = val.length;
var elemId = "domain";
setCaretPosition(elemId, caretPos);
});
Which will take anything after any . character out of the string, replace it each time with '.com' (you can replace this regex to handle whatever you need), and then set the cursor position to right before the '.com'
JSFiddle Demo
Also, to enable editing in the middle of the string you'd have to get the caret position. There's a stackoverflow question here
Get cursor position (in characters) within a text Input field
With good examples. I modified one of the answers as follows:
getCaretPosition = function (elemId) {
var input = $('#' + elemId);
if (!input) return; // No (input) element found
if ('selectionStart' in input[0]) {
// Standard-compliant browsers
return input[0].selectionStart;
} else if (document.selection) {
// IE
input.focus();
var sel = document.selection.createRange();
var selLen = document.selection.createRange().text.length;
sel.moveStart('character', -input.value.length);
return sel.text.length - selLen;
}
}
And then your jQuery would look like this:
$("input").keyup(function () {
var val = $("#domain").val();
var elemId = "domain";
var caretPos = getCaretPosition(elemId);
val = val.replace(/\..*/g, '');
$("#domain").val(val + (val ? ".com" : ""));
setCaretPosition(elemId, caretPos);
});
Updated Fiddle with that implementation.
maybe this would help you.
http://jsfiddle.net/naeemshaikh27/UUzux/35/
$(document).ready(function(){
var prevText;
$("input").keyup(function(e){
var str=$("input").val().replace(".com", "");
str=str+'.com'
$("#domain").val( str );
});
});
well here is the updated one: http://jsfiddle.net/naeemshaikh27/UUzux/39/
But still looks aweful without caret moved
You could try this
$(document).ready(function () {
$("input").keyup(function (e) {
var kcode;
if (!e){
var e = window.event;
}
if (e.keyCode){
kcode = e.keyCode;
}
else if (e.which){
kcode = e.which;
}
if (kcode == 8 || kcode == 46){
return false;
}
this.value = this.value.replace('.com', '');
$("#domain").val(this.value + ".com");
var curpos = this.createTextRange();
curpos.collapse(true);
curpos.moveEnd('character', this.value.length - 4);
curpos.select();
});
});
I had to borrow some code from Joel on this post regarding disabling the backspace and delete keys. Just as he states in his post be careful using e.keyCode because not all browsers use it, some use e.Which.
JsFiddle Demo
Update: link to full list of key codes.

Can getSelection() be applied to just a certain element (not the whole document)?

I was testing out the getSelection() method, and I wanted my program to get the selected text in a certain paragraph of text and display it in a div tag. I used the following code:
var txt = document.getSelection();
document.getElementById("display").innerHTML = "The text you have selected is: " + txt + ".";
However, I want the program to only get selections made in the paragraph itself, not in the entire document. I tried using document.getElementById("id").getSelection(); but it didn't work.
How can I make it so getSelection() only applies to a certain element?
Here's one approach, tested only in Chromium 19 (Which supports textContent, for Internet Explorer innerText would have to be used instead):
function getSelectedText() {
if (window.getSelection) {
return window.getSelection().toString();
} else if (document.selection) {
return document.selection.createRange().text;
}
return '';
}
var b = document.getElementsByTagName('body')[0],
o = document.getElementById('output');
b.onmouseup = function(e){
var selText = getSelectedText(),
targetElem = e.target.tagName.toLowerCase();
if (selText && targetElem == 'p') {
o.textContent = 'You selected the text: "' + selText + '" from a ' + targetElem + ' element.';
}
};​
JS Fiddle demo.
getSelection() is only available as a method of window and document. If you want to get a Range representing just the portion of the user selection that lies within a particular node, here's a function to do that, using my Rangy library (the code to do without the library would be longer and is beyond my enthusiasm to write right now):
function getSelectedRangeWithin(el) {
var selectedRange = null;
var sel = rangy.getSelection();
var elRange = rangy.createRange();
elRange.selectNodeContents(el);
if (sel.rangeCount) {
selectedRange = sel.getRangeAt(0).intersection(elRange);
}
elRange.detach();
return selectedRange;
}
function getSelected() {
if(window.getSelection) { return window.getSelection(); }
else if(document.getSelection) { return document.getSelection(); }
else {
var selection = document.selection && document.selection.createRange();
if(selection.text) { return selection.text; }
return false;
}
return false;
}
written in coffeescript:
getSelected = ->
if window.getSelection
return window.getSelection()
else if document.getSelection
return document.getSelection()
else
selection = document.selection and document.selection.createRange()
return selection.text if selection.text
return false
false
delicious javascript

How do I keep my cursor/caret from moving inside of an input text element?

I'm trying to build a form that works in a manner similar to the Google Search page, as well as Gmail and several other pages (including the this page - see the "Tags" input on the Ask Question page). As text is input, a list of options will appear, and the user can use up and down arrows to select the option they want.
The problem I am having is that the up arrow puts the cursor/caret in position 0 of the field, and down puts it at the end. Is there an easy way of keeping it from moving to the beginning/end, or do I need to find the caret position before my function is run, and reposition it to that spot after?
This is the beginning of the function that runs when when text is entered in the input element (onkeyup).
var keycode = checkKeycode (event); // returns the keycode of the key pressed.
if (keycode == 38) { // up arrow
var selection = $(".optionsSelected").attr("id");
var selId = parseInt(selection.replace('briefOption', ''));
if (selId != 0) {
$(".optionsSelected").removeClass("optionsSelected");
var newSelId = selId - 1;
$("#briefOption"+newSelId).addClass("optionsSelected");
}
}
else if (keycode == 40) { // down arrow
var selection = $(".optionsSelected").attr("id");
var selId = parseInt(selection.replace('briefOption', ''));
if (selId != numAvEmps && numAvEmps != 0) {
$(".optionsSelected").removeClass("optionsSelected");
var newSelId = selId + 1;
$("#briefOption"+newSelId).addClass("optionsSelected");
}
}
else if (keycode == 27) { // Escape
$("#docDropDown").css("display","none");
}
else if (keycode == 9 || keycode == 13) { //tab or enter
/* Fill form */
}
Let me know if any more code would be useful. Thanks for the help.
You'd want to store the caret before and then when you're done doing things, set it back.
Something like this:
HTML body:
<input type="text" id="mytextbox" style="border: 1px solid black" />
Javascript:
function getCaretPosition(ctrl)
{
var caretPos = 0;
// IE
if (document.selection)
{
ctrl.focus ();
var sel = document.selection.createRange();
sel.moveStart ('character', -ctrl.value.length);
caretPos = sel.text.length;
}
// Firefox
else if (ctrl.selectionStart || ctrl.selectionStart == '0')
{
caretPos = ctrl.selectionStart;
}
return caretPos;
}
function setCaretPosition(ctrl, pos)
{
if(ctrl.setSelectionRange)
{
ctrl.focus();
ctrl.setSelectionRange(pos,pos);
}
else if (ctrl.createTextRange)
{
var range = ctrl.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
}
$(document).ready(function ()
{
$("#mytextbox").keydown(function (e)
{
// Up
if(e.which == 38)
{
var pos = getCaretPosition(this);
// Do stuff here that changes the value/caret?
setCaretPosition(this, pos);
}
// Down
else if(e.which == 40)
{
var pos = getCaretPosition(this);
// Do stuff here that changes the value/caret?
setCaretPosition(this, pos);
}
});
});
Just prevent the default action of the event. You can do this by returning false if you're using an event handler property rather than addEventListener/attachEvent, which would be the easiest way:
var input = document.getElementById("your_input");
var suppressKeypress = false;
input.onkeydown = function(evt) {
evt = evt || window.event;
var keyCode = evt.keyCode;
if (keyCode == 38) {
// Do your stuff here
suppressKeypress = true; // For Opera; see below
return false;
}
// Other cases here
};
// This bit is for Opera, which only allows you to suppress the default
// action of a keypress in the keypress event (not keydown)
input.onkeypress = function() {
if (suppressKeypress) {
suppressKeypress = false;
return false;
}
};

Categories

Resources