Ideas/Assistance with ActionScript Color Fading? - javascript

Here is a function I added to my Flash-based chat to rainbowify certain text within [rainbow] and [/rainbow] tags.
ChatUI.prototype.rainbowParse = function(txt) {
txt = txt;
if ((txt.indexOf("[rainbow]") > -1) && (txt.indexOf("[/rainbow]") > -1)) {
txt = txt.replace("'", "#").replace("'", "#");
var firstChar = txt.indexOf("[rainbow]") + 9;
var lastChar = txt.indexOf("[/rainbow]");
if (((lastChar - firstChar) > 100) || ((txt.split("[rainbow]").length - 1) > 3)) {
break;
}
while (lastChar <= txt.lastIndexOf("[/rainbow]")) {
var RAINBOWTEXT = '';
var i = firstChar;
while (i < lastChar) {
RAINBOWTEXT += txt.charAt(i);
i++
}
var text = RAINBOWTEXT;
var texty = '';
colors = new Array('ff00ff','ff00cc','ff0099','ff0066','ff0033','ff0000','ff3300','ff6600','ff9900','ffcc00','ffff00','ccff00','99ff00','66ff00','33ff00','00ff00','00ff33','00ff66','00ff99','00ffcc','00ffff','00ccff','0099ff','0066ff','0033ff','0000ff','3300ff','6600ff','9900ff','cc00ff');
i = 0;
while (i <= text.length) {
var t = text.charAt(i);
if (t != undefined) {
texty += "<font color=\"#" + colors[i % colors.length] + "\">" + t + "</font>";
i++;
}
}
texty = texty.replace("> <", "> <");
var REPLACEME = "[rainbow]" + RAINBOWTEXT + "[/rainbow]";
txt = txt.replace(REPLACEME, texty);
if (lastChar == txt.lastIndexOf("[/rainbow]")) {
break;
}
nextChar = lastChar + 10;
firstChar = txt.indexOf("[rainbow]", lastChar) + 9;
lastChar = txt.indexOf("[/rainbow]", lastChar);
}
txt = txt.replace("#", "&apos;");
}
return txt;
}
However, I don't like this way these rainbows look. The text's colors repeat themselves.
To see an example of what I mean, go to http://www.tektek.org/color/ and click "Rainbow" and preview with the repeat set to 1. Then preview with it set to 3 or higher.
I want my code to have a repeat of 1, but since the rainbow text length varies so much, I have no idea how to do this. I've Googled numerous rainbow text generators, trying to look at their code. It sucks. Please give me some ideas or assistance with this. :(

You need to divide the number of elements in your colors array by the number of characters in your rainbow string and apply each colour to that number of characters in your string. That way each color will be applied only once and in equal proportions regardless of the length of your string:
// Calculate the number of characters to apply each character to
var inc = Math.round(colors.length / txt.length);
// Empty string to store the modified rainbox text in
var str = "";
// Loop through each color and apply it to the correct number of characters
for (var i = 0; i < colors.length; i ++) {
str += "<font color='#'" + colors[i] + "'>"
+ txt.substr(i * inc, inc)
+ "</font>";
}
Edit:
Okay, I reread the question and looked again at the example you link to and I think a better solution would be to create a linear gradient in a Sprite using the drawing API and mask it using the text field containing the text which must have the rainbow effect applied to it:
import flash.text.TextField;
import flash.text.TextFormat;
import flash.display.Sprite;
import flash.display.GradientType;
import flash.text.TextFieldAutoSize;
import flash.geom.Matrix;
import flash.text.Font;
// You need to embed the font to use it as a mask
Font.registerFont(Arial);
var txt:String = "My Rainbow text";
// Removed some of your colors to save time formatting
var colors:Array = [0xff00ff, 0xff00cc, 0xff0099, 0xff0066, 0xff0033,
0xff0000, 0xff3300, 0xff6600, 0xff9900, 0xffcc00,
0xffff00, 0xccff00, 0x99ff00, 0x66ff00, 0x33ff00];
var alphas:Array = [];
var ratios:Array = [];
// Populate alphas and ratios arrays of the same length as colors array
for (var i:int = 0; i < colors.length; i ++)
{
alphas.push(1);
ratios.push(i * Math.round(255 / colors.length)); // Equal ratio for each color
}
// Create a text field
var field:TextField = new TextField();
field.text = txt;
field.autoSize = TextFieldAutoSize.LEFT;
field.setTextFormat(new TextFormat("Arial", 30, 0x0000000));
field.embedFonts = true;
// Create a gradient of the same dimensions as the text field
var matrix:Matrix = new Matrix();
matrix.createGradientBox(field.width, field.height);
var gradient:Sprite = new Sprite();
gradient.graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, matrix);
gradient.graphics.drawRect(0, 0, field.width, field.height);
gradient.graphics.endFill();
this.addChild(field);
this.addChild(gradient);
// Mask the gradient with the text field
gradient.mask = field;

Related

Randomly change uppercase / lower case in html text

I have a HTML text element ex: an H1 tag called VIDEOS. Is there any way to use JS to randomly manipulate the capitalization of the text? So for instance on one instance it loads the text as viDEoS, on another it loads ViDeos and so on.
Each letter essentially randomly changes between uppercase & lowercase
Possible solution.
var elem = document.getElementById('vid');
elem.textContent = elem.textContent.split('').map((v) =>
Math.round(Math.random()) ? v.toUpperCase() : v.toLowerCase()
).join('');
<h1 id='vid'>videos</h1>
$('.randomize').each(function() {
var _word = $(this).html();
var _arr = _word.split('');
var _store = '';
var _style = '';
$(this).html('');
for (var i = 0, len = _arr.length; i < len; i++) {
if((Math.floor(Math.random() * 2) + 1) === 1) {
_style = 'uppercase';
}
else {
_style = 'lowercase';
}
_store = _store + '<span style="text-transform: '+ _style +' ;">' + _arr[i] + '</span>';
}
$(this).html(_store);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1 class="randomize">Videos</h1>

detect natural line breaks javascript

When I type in a non-resizeable text area something like hello world, this is a demo and the text area is small enough, it will look like this:
hello world,
this is a demo
This is not caused by a \n or something.
How can I detect this natural line break in a text area?
A fiddle can be found here: http://jsfiddle.net/yx6B7/
As you can see, there is a line break, but javascript just says that it's one big line without any line-breaks in it.
Finally I found this script on the internet:
function ApplyLineBreaks(strTextAreaId) {
var oTextarea = document.getElementById(strTextAreaId);
if (oTextarea.wrap) {
oTextarea.setAttribute("wrap", "off");
}
else {
oTextarea.setAttribute("wrap", "off");
var newArea = oTextarea.cloneNode(true);
newArea.value = oTextarea.value;
oTextarea.parentNode.replaceChild(newArea, oTextarea);
oTextarea = newArea;
}
var strRawValue = oTextarea.value;
oTextarea.value = "";
var nEmptyWidth = oTextarea.scrollWidth;
var nLastWrappingIndex = -1;
for (var i = 0; i < strRawValue.length; i++) {
var curChar = strRawValue.charAt(i);
if (curChar == ' ' || curChar == '-' || curChar == '+')
nLastWrappingIndex = i;
oTextarea.value += curChar;
if (oTextarea.scrollWidth > nEmptyWidth) {
var buffer = "";
if (nLastWrappingIndex >= 0) {
for (var j = nLastWrappingIndex + 1; j < i; j++)
buffer += strRawValue.charAt(j);
nLastWrappingIndex = -1;
}
buffer += curChar;
oTextarea.value = oTextarea.value.substr(0, oTextarea.value.length - buffer.length);
oTextarea.value += "\n" + buffer;
}
}
oTextarea.setAttribute("wrap", "");
document.getElementById("pnlPreview").innerHTML = oTextarea.value.replace(new RegExp("\\n", "g"), "<br />");
}
Which is working fine.
This isn't a javascript problem.
Look at the word-wrap, white-space and overflow css properties.

Use CodeMirror for standalone syntax highlighting with line numbers

I use CodeMirror V. 3 for stand alone syntax highlighting (other parts of my project also uses the CodeMirror editor, so I don't want to use other standalone-syntax highlighting libraries like google-code-prettify).
I use the lib/runmode.js script as described in the CodeMirror: Mode Runner Demo to highlight code in a <pre>-tag. This works fine. Now I want to add line numbers on the left side of the code just like in the CodeMirror editor.
(The CodeMirror.runMode have an options argument, but this seems to work only with the tabsize. Any idea how I can add linenumbers to my code (like in google-code-prettify the css-class linenums)?)
I would hack Mode Runner like this
CodeMirror.runMode = function(string, modespec, callback, options) {
var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
var lineNumber = 1; // Line number
if (callback.nodeType == 1) {
var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
var node = callback, col = 0;
node.innerHTML = "";
callback = function(text, style) {
if (text == "\n") {
lineNumber++ ; //increment line number
var lineNum = document.createTextNode(lineNumber); //
node.appendChild(document.createElement("br"));
node.appendChild(lineNum); // append
col = 0;
return;
}
var content = "";
// replace tabs
for (var pos = 0;;) {
var lineNum = document.createTextNode(lineNumber + " ")
var idx = text.indexOf("\t", pos);
if (idx == -1) {
content += text.slice(pos);
col += text.length - pos;
break;
} else {
col += idx - pos;
content += text.slice(pos, idx);
var size = tabSize - col % tabSize;
col += size;
for (var i = 0; i < size; ++i) content += " ";
pos = idx + 1;
}
}
if (style) {
var sp = node.appendChild(document.createElement("span"));
sp.className = "cm-" + style.replace(/ +/g, " cm-");
sp.appendChild(document.createTextNode(content));
} else {
node.appendChild(document.createTextNode(content));
}
};
}
var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode);
for (var i = 0, e = lines.length; i < e; ++i) {
if (i) callback("\n");
var stream = new CodeMirror.StringStream(lines[i]);
while (!stream.eol()) {
var style = mode.token(stream, state);
callback(stream.current(), style, i, stream.start);
stream.start = stream.pos;
}
}
// add the first line
var outputDiv = document.getElementById("output");
var firstLine = document.createTextNode("1 ");
outputDiv.insertBefore(firstLine, outputDiv.firstChild);
};

Javascript/ActionScript do for each indexOf?

The screenshot below the code shows me issue. It only rainbowfies one instance of text.
How can I get this code to do each [rainbow]specified[/rainbow] text?
It's actually for ActionScript but it works in Javascript too so I've been testing on http://jsfiddle.net
var txt = "This is a [rainbow]test to show that I can[/rainbow] make whatever I want [rainbow]appear as a rainbow[/rainbow] because I am [rainbow]awesome[/rainbow].";
if ((txt.indexOf("[rainbow]") > -1) && (txt.indexOf("[/rainbow]") > -1)) {
var firstChar = txt.indexOf("[rainbow]") + 9;
var lastChar = txt.indexOf("[/rainbow]");
var RAINBOWTEXT = '';
var i = firstChar;
while (i < lastChar) {
RAINBOWTEXT += txt.charAt(i);
i++
}
var text = RAINBOWTEXT;
var texty = '';
colors = new Array('ff00ff', 'ff00cc', 'ff0099', 'ff0066', 'ff0033', 'ff0000', 'ff3300', 'ff6600', 'ff9900', 'ffcc00', 'ffff00', 'ccff00', '99ff00', '66ff00', '33ff00', '00ff00', '00ff33', '00ff66', '00ff99', '00ffcc', '00ffff', '00ccff', '0099ff', '0066ff', '0033ff', '0000ff', '3300ff', '6600ff', '9900ff', 'cc00ff');
var i = 0;
while (i <= text.length) {
var t = text.charAt(i);
if (t != undefined) {
texty += "<font color=\"#" + colors[i % colors.length] + "\">" + t + "</font>";
i++;
}
}
texty = texty.replace("> <", "> <");
var REPLACEME = "[rainbow]" + RAINBOWTEXT + "[/rainbow]";
txt = txt.replace(REPLACEME, texty);
document.write(txt);
}​
If we can make assumptions about no interleaving or nesting of [rainbow] tags, I'd just use a regular expression with a simple replacer callback:
var rainbowified = txt.replace(/\[rainbow\](.*?)\[\/rainbow\]/, function(textWithTags, textBetweenTheseTags) {
var text = textBetweenTheseTags;
....
for(var i = 0; i < text.length; ++i) {
// rainbowify each letter of text...
}
...
return textWithFontTags;
}
You can use this to get a new string with the transformation you want.
Also, the font tag is depricated; you should use span with color:#XXXXXX in the style attribute.
var colors = [
'f0f', 'f0c', 'f09', 'f06', 'f03', 'f00', 'f30', 'f60', 'f90', 'fc0',
'ff0', 'cf0', '9f0', '6f0', '3f0', '0f0', '0f3', '0f6', '0f9', '0fc',
'0ff', '0cf', '09f', '06f', '03f', '00f', '30f', '60f', '90f', 'c0f'
];
function rainbowify(text) {
return text.replace(/\[rainbow\](.*)\[\/rainbow\]/g, function(_, inner){
return inner.replace(/./g, function(ch, i){
return '<span style="color:#' + colors[i % colors.length] + ';">' + ch + '</span>';
});
})
}
Here's how I'd do it.
Make it a loop. .indexOf can take a starting point as the second parameter, so with starting the next iteration at lastChar+10 should work.
Apart from that, it might be easier to do it fully with regex and .replace:
return txt.replace(/\[rainbow\](.+?)\[\/rainbow\]/g, function(all, match, index, str) {
return createRGBrainbowArray(match.length).map(function(color, i) {
return '<span style="color:#'+color+'">'+match[i]+'</span>';
}).join("");
});
function createRGBrainbowArray(l) {
// should return an Array of length l with hexadecimal color strings,
// representing a nice rainbow
}

Long string pagination done right

I want to split a long text into smaller chunks, that will act as pages.
var longText = document.getElementById('content').innerHTML;
for (i=0; i<10; i++) {
var page = longText.substring(i*100,(i+1)*100);
document.write(page + "<br /><hr />");
}
See it here on jsfiddle.
This code splits the text, but in a stupid way, cutting also words in half.
It would be far better, for example, creating substrings ending at the last space in a certain number of characters (count 100 characters, then go back to the last space).
How would you achieve it?
Second shot
Third shot
I would use:
function paginate(longText, pageSize) {
var parts = longText.split(/[ \n\t]/g);
if (parts.length == 0)
return [];
var pages = [parts.unshift()];
for (var i = 0; i < parts.length; i += 1) {
var part = parts[i];
if (part.length + pages[pages.length - 1].length < pageSize) {
pages[pages.length - 1] += " " + part;
} else {
pages.push(part);
}
}
return parts;
}
For those looking for a working answer:
<div id="long-text">Lorem ipsum [...]</div>
<script>
var splitter = function(id) {
var longText = document.getElementById(id).innerHTML;
var pageLenght = 200;
var charsDone = 0;
var htmlBefore = "<p>";
var htmlAfter = "</p>";
while (charsDone <= longText.length && (pageLenght+charsDone)<longText.length) {
var pageBox = longText.substr(lastSpace,pageLenght);
var lastSpace = charsDone + pageBox.lastIndexOf(" ");
var page = longText.substring(charsDone,lastSpace);
document.write(htmlBefore + page + htmlAfter);
charsDone = lastSpace;
}
document.write(longText.substr(lastSpace,pageLenght));
}
splitter("#long-text");
You can easily use arrays instead of writing to document.
You will also want to set your html to your needs, do it in htmlBefore and htmlAfter.
See it in action here.

Categories

Resources