8

I have an input text field like this,

input {
  color: red
}
Name:
<input type="text" name="text" class="text" />

I want to apply different color for each letter in the input text field , If the user enters hai the each letter h,a,i the adjacent letter should have different color .Let me choose red and yellow. Is there is any way for that in jQuery, css?

Pranav C Balan
  • 113,687
  • 23
  • 165
  • 188

3 Answers3

15

http://jsfiddle.net/DerekL/Y8ySy/

$("body").prop("contentEditable", true).blur(function(){
    var chars = $(this).text().split("");
    this.innerHTML = "";
    $.each(chars, function(){
        $("<span>").text(this).css({
            color: "#"+(Math.random()*16777215|0).toString(16)  //just some random color
        }).appendTo("body");
    });
});

You can actually set the event to keypress if the user is only going to enter with a normal keyboard. I used blur here because keypress/keyup will break the code if the user is entering text with IME.

As Billy Mathews mentioned, one might want to have an input that can be submitted by form. Here is a solution:

<input type="hidden" id="hiddenEle">

var chars = $(this).text().split("");
$("#hiddenEle").val($(this).text());
this.innerHTML = "";

Just for fun

Here is one that won't change color: http://jsfiddle.net/DerekL/A7gL2/

Community
  • 1
  • 1
Derek 朕會功夫
  • 92,235
  • 44
  • 185
  • 247
2

Why not make the input's font invisible and have some javascript that dynamically changes some text placed over the input as you type? Something like this:

<div>
    Name:<input type="text" name="text" class="text" />
    <div class="colors"></div>
</div>

JavaScript:

$(document).ready(function(){
    $('.text').keyup(function(){
        var output="";
        var letters = $(this).val().split("");
        letters.forEach(function(letter){
            var color = "#"+(Math.random()*16777215|0).toString(16);
            //Stolen from Derek's answer ;)
            output += '<span style="color: ' + color + ';">' + letter + '</span>';
          $('div.colors').html(output);
        });
    });
});

Then you just gotta position the div over the input; et voila! Not tested.. but I am making a jsFiddle now! http://jsfiddle.net/pranavcbalan/54EY4/6/

Bill
  • 3,478
  • 23
  • 42
1

Update: Fixed the CTRL+A DEL problem. FIDDLE

var input = document.getElementById("input");
input.onkeydown = colorTheText;

function generateRandomColor() {
    var color = [];
    for (var i = 0; i < 3; i++) {
        color.push(Math.floor(Math.random()*250));
    }
    return color;
}

function rgbToHex(color) {
    var hex = [];
    for (var i = 0; i < 3; i++) {
        hex.push(color[i].toString(16));
        if (hex[i].length < 2) { hex[i] = "0" + hex[i]; }
    }
    return "#" + hex[0] + hex[1] + hex[2];
}

function setEndOfContenteditable(contentEditableElement) {
    var range,selection;
    if(document.createRange) {
        range = document.createRange();
        range.selectNodeContents(contentEditableElement);
        range.collapse(false);
        selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);
    }
}

var colors = [];
var inputLength = 0;
var ctrl = [];

function colorTheText(e) {
    if (e.keyCode == 8) {
        if (ctrl.indexOf(17) > -1 && ctrl.indexOf(65) > -1) {
            input.innerHTML = "";
            ctrl.length = 0;
        }
    } else {
        var text = input.innerText;
        if (text.length > inputLength) {
            inputLength++;
            colors.push(generateRandomColor());
        } else {
            inputLength--;
            colors.pop();
        }
        input.innerHTML = "";
        text = text.split("");
        for (var i = 0; i < text.length; i++) {
            if (colors[i]) {
                input.innerHTML += '<span style="color:' + rgbToHex(colors[i]) + '">' + text[i] + '</span>';
            }
        }
        setEndOfContenteditable(input);        
        if (e.keyCode == 17) {
            ctrl.length = 0;
            ctrl.push(17);
        }
        if (e.keyCode == 65) {
            if (ctrl[0] == 17 && ctrl.length == 1) {
                ctrl.push(65);
            }        
        }
    }
}


Even though the question is answered, I wanted to post my answer. Might come handy to future viewers.

In this one color change happens while typing, and it remembers the color order until the div is completely cleared.

And I know it's not perfect. Yet. Play with it.

FIDDLE

setEndOfContenteditable function taken from Nico Burn's answer.

var input = document.getElementById("input");
input.onkeydown = colorTheText;

function generateRandomColor() {
    var color = [];
    for (var i = 0; i < 3; i++) {
        color.push(Math.floor(Math.random()*250));
    }
    return color;
}

function rgbToHex(color) {
    var hex = [];
    for (var i = 0; i < 3; i++) {
        hex.push(color[i].toString(16));
        if (hex[i].length < 2) { hex[i] = "0" + hex[i]; }
    }
    return "#" + hex[0] + hex[1] + hex[2];
}

function setEndOfContenteditable(contentEditableElement) {
    var range,selection;
    if(document.createRange) {
        range = document.createRange();
        range.selectNodeContents(contentEditableElement);
        range.collapse(false);
        selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);
    }
}

var colors = [];
var inputLength = 0;

function colorTheText(e) {
    var text = input.innerText;
    if (text.length > inputLength) {
        inputLength++;
        colors.push(generateRandomColor());
    } else {
        inputLength--;
        colors.pop();
    }
    input.innerHTML = "";
    text = text.split("");
    for (var i = 0; i < text.length; i++) {
        if (colors[i]) {
            input.innerHTML += '<span style="color:' + rgbToHex(colors[i]) + '">' + text[i] + '</span>';
        }
    }
    setEndOfContenteditable(input);
}
Community
  • 1
  • 1
akinuri
  • 10,690
  • 10
  • 65
  • 102
  • I can't press `Ctrl+A delete` to delete the text. :( – Derek 朕會功夫 Feb 09 '14 at 05:40
  • And also you can do `"#"+(Math.random()*16777215|0).toString(16);` (since color is just a 8 byte integer) to get a random color with fast speed ;) – Derek 朕會功夫 Feb 09 '14 at 05:42
  • I know. That's why I said it's not perfect yet. I'll try to fix that later. Right. Well, I took those color functions from an old project of mine. Didn't want to write again. Lazy me =P – akinuri Feb 09 '14 at 05:43
  • `CTRL+A DEL` works now. Though I noticed another problem. Can't have line-breaks. I'll get to that later =) – akinuri Feb 09 '14 at 18:13
  • Nice work. One weird "bug" I found is that as the input gets longer, the speed (fps) becomes exponentially slower. (this reminds me of that boring BigO notation thing...O(n^2)..) – Derek 朕會功夫 Feb 09 '14 at 21:11
  • Just tested. You're right. Like, after 150th~ letter it slows. Well, then let's hope the user doesn't write an article with this :D Though it can be used with short texts. And damn. This thing is full of bugs. Just found another one. If you `CTRL+A` then cancel the selection, and later hit `del` it deletes the whole text. I gotta clear the `ctrl` array on selection cancelling >.> – akinuri Feb 09 '14 at 23:45
  • 1
    I just made one that won't lag and the color won't change. Can handle Ctrl+A, selections, text pasting... basically just like the normal text input: http://jsfiddle.net/DerekL/A7gL2/ – Derek 朕會功夫 Feb 10 '14 at 02:23
  • (Tested on Chrome and Firefox) – Derek 朕會功夫 Feb 10 '14 at 02:43
  • You did it! Just one feature away from perfect. Line-breaks. Also I'd like if you write this in pure JS sometime. I wanna know what's going on in there. Not that familiar with jQuery, and don't wanna go through the API now. – akinuri Feb 11 '14 at 14:43
  • Here is the exact same code but with only native methods: http://jsfiddle.net/DerekL/BY399/ (Oh boy, that was scary) – Derek 朕會功夫 Feb 12 '14 at 00:38
  • Haha. Thank you for the effort. Didn't go through your code yet, but noticed a bug. If you follow this `input -> enter(new line) -> CTRL+A DEL -> input` then it gets messy. Checked the jQuery version and it's bug free. It's only in the pure JS version. I think it makes a new line(tho it doesn't work), but caret position breaks or something. – akinuri Feb 12 '14 at 01:03
  • I tried to fix it: http://jsfiddle.net/DerekL/BY399/2/ (I blocked all `
    ` to prevent going into the next line) but the code just gets more messy now
    – Derek 朕會功夫 Feb 12 '14 at 02:41
  • Well done. I can handle this level of messy :) Btw, I noticed something. `CTRL DEL` deletes the whole text. Though I'm not sure to call this a bug. You could say it's a feature :D – akinuri Feb 12 '14 at 08:40
  • Yup. A bug? No it's a feature! – Derek 朕會功夫 Feb 12 '14 at 17:02