d3.js : Zoomable / Pannable on multiple circles based chart - path
Sorry if the title or my explanation are bad, probleme is not easy in french so in english ...
So, i try to make a chart like : Focus+Context via Brushing but, instead of having one path to show data, i've 500 circle.
For moment, Zoom and Pan dont work.
To my understanding of problem, i need to convert my 500 circle to one single path but i dont know how to do this, if it's the good solution or event if it's possible ..
Thanks for your help, here a fiddle (my first one): http://jsfiddle.net/Kazual/R96Kc/
And the code: (i give all the code, but this is only the pan effect that i need to fix, all data are random and dont mean anything, and use the 3 button on bottom right to update circle position)
function graphiqueCircle(x, y, w, h, trgDiv){
graphiqueCircle.C_INDICE_VIE = "Indice Vie";
graphiqueCircle.C_INDICE_SANTE = "Indice Sante";
graphiqueCircle.C_INDICE_INSTRUCTION = "Indice Instruction";
var indiceVie = false,
indiceSante = false,
indiceInstruction = false;
var margin = {top: y, right: 0, bottom: 0, left: x},
width = w,
height = h,
height2 = 20;
//
var x = d3.scale.linear()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var x2 = d3.scale.linear()
.range([0, width]);
var y2 = d3.scale.linear()
.range([height2, 0]);
//
var color = d3.scale.category10();
//
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var xAxis2 = d3.svg.axis()
.scale(x2)
.orient("bottom");
//
var brush = d3.svg.brush()
.x(x2)
.on("brush", brushed);
//
var area = d3.svg.area()
.interpolate("monotone")
.x(function(d) { return x(d.codeCom); })
.y0(height)
.y1(function(d) { return [0,1]; });
var area2 = d3.svg.area()
.interpolate("monotone")
.x(function(d) { return x2(d.codeCom); })
.y0(height2)
.y1(function(d) { return [0,1]; });
//
var svg = d3.select(trgDiv).append("svg").attr("class", "gMap")
.attr("width", width + 50 )
.attr("height", height + 50 + height2 +50);
//
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
//
var allCircles,
allCirclesContext,
theckBox,
axeX,
axeY,
_data;
//
var focus = svg.append("g")
.attr("transform", "translate(" + (margin.left + 10) + "," + margin.top + ")")
var context = svg.append("g")
.attr("transform", "translate(" + (margin.left + 10) + "," + (margin.top+height+height2+30) + ")")
//
_data = [
{codeCom:33001, communes:"obj1", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib1"},
{codeCom:33002, communes:"obj2", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib2"},
{codeCom:33003, communes:"obj3", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib3"},
{codeCom:33004, communes:"obj4", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib4"},
{codeCom:33005, communes:"obj5", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib5"},
{codeCom:33006, communes:"obj6", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib6"},
{codeCom:33007, communes:"obj7", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib7"},
{codeCom:33008, communes:"obj8", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib8"},
{codeCom:33009, communes:"obj9", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib9"}
]
_data.forEach(function(d) {
d.IDH4 = (d.IDH4 != "NULL") ? +d.IDH4 : 0;
d.indiceVie = (d.indiceVie != "NULL") ? +d.indiceVie : 0;
d.indiceSante = (d.indiceSante != "NULL") ? +d.indiceSante : 0;
d.indiceInstruction = (d.indiceInstruction != "NULL") ? +d.indiceInstruction : 0;
d.codeCom = (d.codeCom != "NULL") ? +d.codeCom : 0;
});
//
x.domain(d3.extent(_data.map(function(d) { return d.codeCom; })));
y.domain([0,1]);
x2.domain(x.domain());
y2.domain(y.domain());
//
allCircles = focus.append("g");
allCircles.attr("id", "allCicles")
.datum(_data)
.attr("clip-path", "url(#clip)")
.attr("d", area)
.selectAll(".dot")
.data(_data)
.enter().append("circle")
.attr("class", "dot")
.attr("id", function(d){ return d.communes; })
.attr("r", 3.5)
.attr("cx", function(d) { return x(d.codeCom); })
.attr("cy", function(d) { return 0; })
.style("fill", function(d) { return color(d.LIBSCOT); });
focus.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end")
.text("Communes");
focus.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("x", -6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Indice");
allCirclesContext = context.append("g");
allCirclesContext.attr("id", "allCirclesContext")
.datum(_data)
.attr("d", area2)
.selectAll(".dot")
.data(_data)
.enter().append("circle")
.attr("class", "dot")
.attr("id", function(d){ return d.communes; })
.attr("r", 2)
.attr("cx", function(d) { return x2(d.codeCom); })
.attr("cy", function(d) { return 0; })
.style("fill", function(d) { return color(d.LIBSCOT); });
context.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
//
context.append("g")
.attr("transform", function(d, i) { return "translate(0,-20)"; })
.style("fill", "blue")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("y", -6)
.attr("height", height2 + 7)
.style("fill-opacity", .2)
.style("visibility", "visible");
//
// LEGEND & CHEKBOX
var legend = focus.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
//
createTchekBox();
function createTchekBox(){
theckBox = focus.selectAll(".theckBox")
.data(["Indice Vie", "Indice Sante", "Indice Instruction"])
.enter().append("g")
.attr("class", "theckBox")
.attr("transform", function(d, i) { return "translate(0," + ((i * 20)+300) + ")"; });
theckBox.append("rect")
.attr("isClicked", "false")
.attr("id", function(d) { return d; })
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", "black")
.on("mouseover", function(){
d3.select(this).style("fill", "grey");
})
.on("mouseout", function(){
if(d3.select(this).attr("isClicked") == "false")
d3.select(this).style("fill", "black");
else
d3.select(this).style("fill", "red");
})
.on("click", function(){
if(d3.select(this).attr("isClicked") == "false"){
d3.select(this).style("fill", "red");
d3.select(this).attr("isClicked", "true");
}else{
d3.select(this).style("fill", "black");
d3.select(this).attr("isClicked", "false");
}
if(d3.select(this).attr("id") == "Indice Vie")
indiceVie = !indiceVie;
else if(d3.select(this).attr("id") == "Indice Sante")
indiceSante = !indiceSante;
else if(d3.select(this).attr("id") == "Indice Instruction")
indiceInstruction = !indiceInstruction;
//
onUpdate();
});
theckBox.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
}
function brushed() {
x.domain(brush.empty() ? x2.domain() : brush.extent());
focus.select("#allCicles").attr("d", area);
focus.select(".x.axis").call(xAxis);
}
function onUpdate(){
var data1,
data2,
data3;
//
if(indiceVie)
data1 = graphiqueCircle.C_INDICE_VIE;
else
data1 = null;
if(indiceSante)
data2 = graphiqueCircle.C_INDICE_SANTE;
else
data2 = null;
if(indiceInstruction)
data3 = graphiqueCircle.C_INDICE_INSTRUCTION;
else
data3 = null;
//
allCircles.selectAll(".dot").each(function(d, i){
d3.select(this).transition().duration(400).delay(i*1)
.attr("cy", function(d, i) {
var returnValue = 0;
var diviseur = 0;
if(data1 == graphiqueCircle.C_INDICE_VIE){
returnValue += y(d.indiceVie);
diviseur++;
}
if(data2 == graphiqueCircle.C_INDICE_SANTE){
returnValue += y(d.indiceSante);
diviseur++;
}
if(data3 == graphiqueCircle.C_INDICE_INSTRUCTION){
returnValue += y(d.indiceInstruction);
diviseur++;
}
if(diviseur == 0)
return 0;
return returnValue/diviseur;
});
});
allCirclesContext.selectAll(".dot").each(function(d, i){
d3.select(this).transition().duration(400).delay(i*1)
.attr("cy", function(d, i) {
var returnValue = 0;
var diviseur = 0;
if(data1 == graphiqueCircle.C_INDICE_VIE){
returnValue += y2(d.indiceVie);
diviseur++;
}
if(data2 == graphiqueCircle.C_INDICE_SANTE){
returnValue += y2(d.indiceSante);
diviseur++;
}
if(data3 == graphiqueCircle.C_INDICE_INSTRUCTION){
returnValue += y2(d.indiceInstruction);
diviseur++;
}
if(diviseur == 0)
return 0;
return returnValue/diviseur-20;
});
});
}
}
var _myGraphique = new graphiqueCircle(20, 20, 800, 400, ".div_iMap");
Related
Fixed number of rows per page using pdfmake.js
Defined an own table layouts using pdfmake.js. On print I want per page to contain 7 rows(fixed).I have tried adjusting the height and width of the table cell to contain 7 rows but however if the data in table cell increases the page accumulates with less/more no.of rows. //layout of the table: var tablelist={ style: 'tableExample', table: { dontBreakRows: true, widths: [ 20,55,55,55,55,55,55,55,55,55,55,55,55], headerRows: 1, body: body }, layout: { hLineWidth: function (i, node) { return (i === 0 || i === node.table.body.length) ? 1 : 1; }, vLineWidth: function (i, node) { return (i === 0 || i === node.table.widths.length) ? 1: 1; }, hLineColor: function (i, node) { return (i === 0 || i === node.table.body.length) ? 'gray' : 'gray'; }, vLineColor: function (i, node) { return (i === 0 || i === node.table.widths.length) ? 'gray' : 'gray'; }, }, } return tablelist; } //pushing the table header and other data to the table body $scope.makePrintTable = function(){ var headers = { col_1:{ text: 'Day', style: 'tableHeader',rowSpan: 1, alignment: 'center',margin: [0, 8, 0, 0] }, col_2:{ text: 'Date', style: 'tableHeader',rowSpan: 1, alignment: 'center',margin: [0, 8, 0, 0] }, col_3:{ text: '0600-0800', style: 'tableHeader',rowSpan: 1, alignment: 'center',margin: [0, 8, 0, 0] }, . . .//Similarly till col_13 col_13:{ text: '1700-1800', style: 'tableHeader',rowSpan: 1, alignment: 'center' ,margin: [0, 8, 0, 0]}, } body = []; var row = new Array(); for (var key in headers) { row.push( headers[key] ); } body.push(row); for ( var j=0 ; j< $scope.table.length; j++){ var tableEach={ }; tableEach= $scope.table[j]; /*This for Genarating Object variables*/ for (var i = 1; i < 3; i++) { window["obj"+i] = new Object(); } var row = new Array(); var slNoValue = tableEach.slNo; /*This is for slNo */ obj1["text"] = slNoValue; obj1["style"]= "cellswidth"; row.push(obj1); /*This is for Date */ var dateValue = new Date(tableEach.date); obj2["text"]= dateValue.getDate() + '-' + basicFormats.getMonthName(dateValue.getMonth() )+ '-' + dateValue.getFullYear()+','+ basicFormats.getDayName(dateValue.getDay()); obj2["style"]= "cellswidth"; row.push(obj2); /*This is for remaining columns (i ranges from 6 to 17 (time in 24hrs clock format) ) */ for(var i=6 ; i<=17 ; i++){ var obj={}; var hourValue = "hour_"+i+"_"+(i+1)+"_value"; var hourValueColor = "hour_"+i+"_"+(i+1)+"_"+"color_value"; hourValue = ( tableEach["hour_"+i] == undefined ? '':(tableEach["hour_"+i])); hourValueColor =(tableEach["hour_"+i+"_colour"] == undefined ? '#ffffff':(tableEach["hour_"+i+"_colour"])); obj["text"] = hourValue; obj["fillColor"] = hourValueColor; obj["style"] = "cellswidth"; row.push(obj); console.log(obj); } // if( j!= 0 && j % 7 == 0){ // pageBreak : 'before' // } } body.push(row); } }; //CSS for tablecells cellswidth : { fontSize: 10, // color:'gray', bold: true, alignment: 'center', margin: [0, 12.55, 0, 12.75], },
You can use pageBreak function for it: pageBreakBefore: function(currentNode, followingNodesOnPage, nodesOnNextPage, previousNodesOnPage) { //Here you can change the criteria according to your requirements if (currentNode.index % 7 === 0)) { return true; } return false; },
D3 Pie Chart too dented
I am getting as a result a badly rendered pie chart. Why is this happening? Am I doing smth wrong? What can I do to have a better border? I am corrently using v3.5.17. var w = 500, h = 500; //var data = [10, 80, 50, 60, 30, 42, 27, 77]; var max = d3.max(data); var min = d3.min(data); var color = d3.scale.ordinal().range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]); console.log(color(50)); var canvas = d3.select("#piegraphic").append("svg") .attr("width", w) .attr("height", h); var group = canvas.append("g") .attr("transform", "translate(200, 200)"); var r = 150; var arc = d3.svg.arc() .outerRadius(r - 10) .innerRadius(0); var arc2 = d3.svg.arc() .outerRadius(r + 10) .innerRadius(0); var pie = d3.layout.pie() .value(function (d) { return d.count; }); var arcs = group.selectAll(".arc") .data(pie(data)) .enter() .append("g") .attr("class", "arc"); var asdf = arcs.append("path") .attr("d", arc) .attr("fill", function (d) { return color(d.data); }) asdf.on("mouseover", function (d) { d3.select(this).transition().duration(200).attr("d", arc2); }); asdf.on("mouseout", function (d, i) { d3.select(this).transition().duration(200).attr("d", arc); }); var circle = group.append("circle") .attr({ "cx": 0, "cy": 0, "r": 140, "fill": "none", "stroke": "#fff", "stroke-width": 2 }); I tried other approaches but I always getting the same result I dont know what else I can try. Thanks in advance EDIT My data looks like this : [{count:106136313.3, label : "RR" },{count:136313.3, label : "RA" },{count:1061313.3, label : "TE" }]
series labels are one over another(overlapping)
the labels are one on another(overlapping) is there an option to arrange them correctly ? (my real data is dynamic, and number of series is also dynamic) example: http://jsfiddle.net/6kBQY/ $(function () { $('#container').highcharts({ chart: { }, xAxis: { categories: ['aa', 'bb', 'cc', 'dd', 'ee', 'ff'] }, plotOptions: { series: { dataLabels: { enabled: true, borderRadius: 5, backgroundColor: 'rgba(252, 255, 197, 0.7)', borderWidth: 1, borderColor: '#AAA', y: -6 } } }, series: [{ data: [10, 20, 30, 25, 15, 5] },{ data: [11, 22, 33, 20, 10, 0] }] }); });
You can use small workaround like here function StaggerDataLabels(series) { sc = series.length; if (sc < 2) return; for (s = 1; s < sc; s++) { var s1 = series[s - 1].points, s2 = series[s].points, l = s1.length, diff, h; for (i = 0; i < l; i++) { if (s1[i].dataLabel && s2[i].dataLabel) { diff = s1[i].dataLabel.y - s2[i].dataLabel.y; h = s1[i].dataLabel.height + 2; if (isLabelOnLabel(s1[i].dataLabel, s2[i].dataLabel)) { if (diff < 0) s1[i].dataLabel.translate(s1[i].dataLabel.translateX, s1[i].dataLabel.translateY - (h + diff)); else s2[i].dataLabel.translate(s2[i].dataLabel.translateX, s2[i].dataLabel.translateY - (h - diff)); } } } } } //compares two datalabels and returns true if they overlap function isLabelOnLabel(a, b) { var al = a.x - (a.width / 2); var ar = a.x + (a.width / 2); var bl = b.x - (b.width / 2); var br = b.x + (b.width / 2); var at = a.y; var ab = a.y + a.height; var bt = b.y; var bb = b.y + b.height; if (bl > ar || br < al) { return false; } //overlap not possible if (bt > ab || bb < at) { return false; } //overlap not possible if (bl > al && bl < ar) { return true; } if (br > al && br < ar) { return true; } if (bt > at && bt < ab) { return true; } if (bb > at && bb < ab) { return true; } return false; } http://jsfiddle.net/menXU/7/
code not working on server but working on localhost
Here I am using a code for getting pictures of user and his friends from facebook via app the code is working properly in localhost but not in server. Here is the whole functionality which i want: on a button click get the user info from facebook data show popup with drop down display pictures of the user 1st album display pictures of the frnds on selection onclick of any image , the selected image should be displayed in next div All the above functionalities are achieved on localhost and server but the 1st album images are not displayed properly and on click of any image is also not working // chk for login of user function Login(y) { picidgen = y; FB.login(function (response) { if (response.authResponse) { getUserInfo();//get user info sbsfbdemo();// open popup } else { console.log('User cancelled login or did not fully authorize.'); } }, { scope: 'email,user_photos,user_videos,read_friendlists,friends_photos', }); } function getUserInfo() { FB.api('/me?fields=name,albums,photos,friends', function (response) { var str = " Select Friends " + "<select name='frndlst2' onchange='frndsalbum()' id='frndlst2'>" str += "<option value='" + response.id + "'selected ='selected'>" + "me" + "</option>"; for (i = 0; i < response.friends.data.length; i++) str += "<option value='" + response.friends.data[i].id + "'>" + response.friends.data[i].name + "</option>" str += "</select>" str += " Select Album " + "<select name='frndlst1' onchange='getfrndsphotos()' id='frndlst1'>" for (x = 0; x < response.albums.data.length; x++) str += "<option value='" + response.albums.data[x].id + "'>" + response.albums.data[x].name + "</option>" str += "</select>"; document.getElementById("status").innerHTML = str; picid = response.albums.data[0].id; var c = response.albums.data[0].count; FB.api('/' + picid + '/photos?limit=400&offset=0', function (photos) { if (photos && photos.data && photos.data.length) { for (var j = 0; j < c; j++) { var photo = photos.data[j]; // photo.picture contain the link to picture var image = document.createElement('img'); image.style.border = "1px solid black"; image.style.margin = "10px"; image.style.cursor = "pointer"; image.src = photo.picture; //user photo is displayed in div(named picture) picsrc["a" + j] = photo.source; image.className = "a"; image.id = "a" + j; document.getElementById("picture").appendChild(image); } } $(".a").bind("click", function () { var photo = $(this).attr("id"); imagecrop = picsrc[photo]; $("#big-pic").find("img").attr("src", picsrc[photo]);// onclick of image it should be displayed in 2nd div(named big-pic) }); }); }); } function frndsalbum() { document.getElementById("frndlst1").options.length = 0; var f2 = document.getElementById("frndlst2"); ffrr = f2.options[f2.selectedIndex].value; FB.api('/' + ffrr + '?fields=albums', function (response) { var f1 = document.getElementById("frndlst1"); for (var i = 0; i < response.albums.data.length; i++) { var album = response.albums.data[i]; var option = document.createElement('option'); option.text = album.name; option.value = album.id; f1.appendChild(option); } document.getElementById("picture").innerHTML = ""; var picid = response.albums.data[0].id; var c = response.albums.data[0].count; //1st album lenth FB.api('/' + picid + '/photos?limit=400&offset=0', function (photos) { if (photos && photos.data && photos.data.length) { for (var j = 0; j < c; j++) { var photo = photos.data[j]; // photo.picture contain the link to picture var image = document.createElement('img'); image.style.border = "1px solid black"; image.style.margin = "10px"; image.style.cursor = "pointer"; image.src = photo.picture; picsrc["a" + j] = photo.source; image.className = "a"; image.id = "a" + j; document.getElementById("picture").appendChild(image); } } $(".a").bind("click", function () { var photo = $(this).attr("id"); imagecrop = picsrc[photo]; $("#big-pic").find("img").attr("src", picsrc[photo]); }); }); }); } function getfrndsphotos() { document.getElementById("picture").innerHTML = ""; var f1 = document.getElementById("frndlst1"); ffr = f1.options[f1.selectedIndex].value; FB.api('/' + ffr + '/photos?limit=400&offset=0', function (photos) { if (photos && photos.data && photos.data.length) { for (var j = 0; j < photos.data.length; j++) { var photo = photos.data[j]; // photo.picture contain the link to picture var image = document.createElement('img'); image.style.border = "1px solid black"; image.style.margin = "10px"; image.style.cursor = "pointer"; image.src = photo.picture; picsrc["a" + j] = photo.source; image.className = "a"; image.id = "a" + j; document.getElementById("picture").appendChild(image); } } $(".a").bind("click", function () { var photo = $(this).attr("id"); imagecrop = picsrc[photo]; $("#big-pic").find("img").attr("src", picsrc[photo]); }); }); }
ActionScript Unexpected Slashes, Parenthesis, and Squiggly-brackets?
This ActionScript code I have been working on for a few days now works 100% just fine in JavaScript, but when I try to compile it in ActionScript it says I have unexpected /, ), and } symbols. Is this syntax wrong and if so how should I fix it? I figured I could test it as Javascript for quicker testing using http://jsfiddle.net/ but now I'm like =( 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 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 '<font color="#' + colors[i % colors.length] + '">' + ch + '</font>'; }); }) } txt = rainbowify(txt); document.write(txt); }
Well, this is it: txt = txt.replace("'", "#"); if ((txt.indexOf("[rainbow]") > -1) && (txt.indexOf("[/rainbow]") > -1)) { var firstChar = txt.indexOf("[rainbow]") + 9; var lastChar = txt.indexOf("[/rainbow]"); 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("#", "'");