<!DOCTYPE html>
<html ng-app="rainbowRoboApp">
<head>
<script data-require="angular.js@*" data-semver="1.3.5" src="https://code.angularjs.org/1.3.5/angular.js"></script>
<script data-require="underscore.js@*" data-semver="1.6.0" src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<script data-require="jquery@*" data-semver="2.1.1" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="basicController">
<label>input: (<span>{{ basicModels.mainInput.length }}</span>)</label>
<input type="text" ng-model="basicModels.mainInput" />
<label>output: (ingame chat)</label>
<input type="text" class="rainbow-output selectable" ng-model="basicModels.mainOutput" value="{{ basicModels.mainInput | rainbowify }}" />
<label>output: (bbcode)</label>
<input type="text" class="rainbow-output selectable" ng-model="basicModels.bbcodeOutput"/>
<p>Total Characters: {{ basicModels.maxChars }}</p>
<p>Characters left: {{ 80 - basicModels.maxChars }}</p>
<p>preview: <span class="lame-preview-attempt" ng-repeat="color in basicModels.previewTextArray"><b style="color: {{color.hash}}">{{color.char}}</b></span></p>
<div class="idnolol">
<div ng-repeat="color in basicModels.previewTextArray"><div class="block" style="width:{{100 / basicModels.previewTextArray.length}}%; background-color:{{color.hash}}"></div></div>
</div>
</body>
</html>
// Code goes here
var LL = LL || {};
function formatDigit(d) {
return (String(d).length == 1) ? "0" + d : "" + d;
}
LL.Rainbow = {
RGBToHash: function(r, g, b) {
var cA = [];
_.each(arguments, function(c) {
cA.push(formatDigit(this.bToHex(Math.abs(Number(c)))));
}, this);
return "#" + cA.join('');
},
objToRGBToHash: function(c) {
return this.RGBToHash(c.red, c.green, c.blue);
},
RGBToBrackets: function(r, g, b) {
var cA = [];
_.each(arguments, function(c) {
cA.push(formatDigit(this.bToHex(Math.abs(Number(c)))));
}, this);
return "[" + cA.join('') + "]";
},
objToRGBToBrackets: function(c) {
return this.RGBToBrackets(c.red, c.green, c.blue);
},
bToHex: _.memoize(function(b) {
return Number(b).toString(16);
}),
getPI120: _.memoize(function(m) {
var mu = typeof m === 'undefined' ? 1 : m;
return mu * Math.PI / 3;
}),
getSteppedFrequency: _.memoize(function(s) {
var step = typeof s === 'undefined' ? 0.21 : s;
return Math.PI * 2 / step;
}),
getFixedRainbow: function(cObj) {
if (typeof cObj === 'undefined' || typeof cObj !== 'object') throw "No Object passed.";
return function(i) {
if (typeof i === 'undefined') throw "No iterator passed.";
return {
red: Math.round(Math.sin(cObj.freq[0] * i + cObj.phase[0]) * cObj.width + cObj.center),
green: Math.round(Math.sin(cObj.freq[1] * i + cObj.phase[1]) * cObj.width + cObj.center),
blue: Math.round(Math.sin(cObj.freq[2] * i + cObj.phase[2]) * cObj.width + cObj.center)
};
};
},
createComponents: function(len, freq, phase, width, center) {
var cObj = {};
cObj.len = typeof len === 'undefined' ? 64 : len;
cObj.freq = typeof freq === 'undefined' ? this.getSteppedFrequency(cObj.len) : freq,
cObj.phase = typeof phase === 'undefined' ? [0, this.getPI120(2), this.getPI120(4)] : phase,
cObj.width = typeof width === 'undefined' ? 127 : width,
cObj.center = typeof center === 'undefined' ? 128 : center;
if (!(cObj.freq instanceof Array)) cObj.freq = new Array(cObj.freq, cObj.freq, cObj.freq);
if (!(cObj.phase instanceof Array)) cObj.phase = new Array(cObj.phase, cObj.phase, cObj.phase);
return cObj;
},
createRainbowArray: function(cObj) {
var rA = [],
fR = this.getFixedRainbow(cObj);
for (var i = 0; i < cObj.len; i++) {
rA.push(this.objToRGBToHash(fR(i)));
}
return rA;
},
createRainbowArrayForRobocraft: function(cObj) {
var rA = [],
fR = this.getFixedRainbow(cObj);
for (var i = 0; i < cObj.len; i++) {
rA.push(this.objToRGBToBrackets(fR(i)));
}
return rA;
},
createRainbowArrayForBBCode: function(cObj) {
var rA = [],
fR = this.getFixedRainbow(cObj);
for (var i = 0; i < cObj.len; i++) {
rA.push("[color="+this.objToRGBToHash(fR(i))+"]");
}
return rA;
}
};
var rainbowFy = function(str, phase, isBbcode) {
var newStr = "",
str = str,
phase = phase || [4, 0, 2],
rainbowArray;
if (!isBbcode){
rainbowArray = LL.Rainbow.createRainbowArrayForRobocraft(LL.Rainbow.createComponents(str.length, undefined, phase));
}
else {
rainbowArray = LL.Rainbow.createRainbowArrayForBBCode(LL.Rainbow.createComponents(str.length, undefined, phase));
}
for (var i = 0, max = str.length; i < max; i++) {
if (str.substr(i, 1) === " ") {
newStr += " ";
} else {
newStr += "" + rainbowArray[i] + str.substr(i, 1);
if(isBbcode) newStr += "[/color]"
}
}
return newStr;
};
var previewText = function(str) {
var len = str.length,
imlazyLeaveMeAlone = LL.Rainbow.createRainbowArray(LL.Rainbow.createComponents(len, undefined, [4, 0, 2]));
lamePreviewArray = [];
for (var i = 0; i < len; i++) {
lamePreviewArray.push({
char: str[i],
hash: imlazyLeaveMeAlone[i]
})
}
return lamePreviewArray;
}
LL.app = angular.module('rainbowRoboApp', [])
.controller('basicController', ['$scope',
function($scope) {
$scope.basicModels = {};
$scope.basicModels.mainInput = 'R A I N B O W S';
$scope.basicModels.maxChars = 0;
$scope.basicModels.previewTextArray = previewText('R A I N B O W S');
$scope.$watch('basicModels.mainInput', function() {
$scope.basicModels.mainOutput = rainbowFy($scope.basicModels.mainInput);
$scope.basicModels.bbcodeOutput = rainbowFy($scope.basicModels.mainInput, undefined, true);
$scope.basicModels.maxChars = rainbowFy($scope.basicModels.mainInput).length;
$scope.basicModels.previewTextArray = previewText($scope.basicModels.mainInput);
});
}
])
.filter('rainbowify', [
function() {
return function(input, $scope) {
return rainbowFy(input);
}
}
]);
$(document).on('click', '.selectable', function() {
this.setSelectionRange(0, this.value.length);
});
/* Styles go here */
input{ width: 100%; height:30px; }
.rainbow-output { width:100%; border: 1px solid #ccc;}
.lame-preview-attempt b{ font-size:24px; text-shadow: 0 0 2px rgba(0,0,0,0.3); }
.idnolol {display:block; width:100%; height:30px;}
.idnolol .block{display:inline; float: left; height: 30px;}