Here is the link to what i'm trying to do. I want to flip the blue bars to face to opposite way on the male side then I will fill in the female side as normal. This will create a tornado chart. I've been working on this for hours and I cant figure it out. I'm using Raphael JS.
http://math.mercyhurst.edu/~cmihna/DataViz/Butterfly.html
Just finished up reviewing your website's source code. No need for transforms, or anything of the such. Just some simple math added to your graph generating for-loop.
Your Code below
ind = 0
for (var key in gender) { // loop over all possible gender
for ( var i = 0; i < people.length; i++ ) { // loop over people
if (people[i][key] != 0) {
var barmale = paper.rect((w+leftPadding-rightPadding)/2,topPadding + vs*0 + i*vs, people[i][key],vs)
barmale.attr({'fill': '#0000A0', 'stroke-width':1})
var barfemale = paper.rect((w+leftPadding-rightPadding)/2, topPadding + vs*0 + i*vs, people2[i][key],-vs)
barfemale.attr({'fill': '#FFC0CB', 'stroke-width':1})
barmale.scale(1,-1)
//var dp = paper.circle(leftPadding + ind*hs + 0.5*hs, topPadding + vs*0.5 + i*vs, people[i][key])
//dp.attr({ 'fill': colors[ind] })
barmale.id = people[i][key] + " " + gender[key] + " people in this age range"
barmale.hover(hoverStart, hoverEnd)
barfemale.id = people[i][key] + " " + gender[key] + " people in this age range"
barfemale.hover(hoverStart, hoverEnd)
}
}
ind++
My Code Below
ind = 0
for (var key in gender) { // loop over all possible gender
for ( var i = 0; i < people.length; i++ ) { // loop over people
if (people[i][key] != 0) {
var barmale = paper.rect((w+leftPadding-rightPadding)/2 - people[i][key],topPadding + vs*0 + i*vs, people[i][key],vs)
barmale.attr({'fill': '#0000A0', 'stroke-width':1})
var barfemale = paper.rect((w+leftPadding-rightPadding)/2, topPadding + vs*0 + i*vs, people2[i][key],vs)
barfemale.attr({'fill': '#FFC0CB', 'stroke-width':1})
barmale.scale(1,-1)
//var dp = paper.circle(leftPadding + ind*hs + 0.5*hs, topPadding + vs*0.5 + i*vs, people[i][key])
//dp.attr({ 'fill': colors[ind] })
barmale.id = people[i][key] + " " + gender[key] + " people in this age range"
barmale.hover(hoverStart, hoverEnd)
barfemale.id = people2[i][key] + " " + gender[key] + " people in this age range"
barfemale.hover(hoverStart, hoverEnd)
}
}
ind++
You can see that I am subtracting the value of the Males from the placement on the graph. This causes the offset to "flip". Then, I modified the code a bit more the bring the female graph into the picture and properly label it.
Please let me know if any questions.
Proof below
Related
I am trying to the splice method but it is not working properly want to delete one user but it is deleting 2.
Also want to add the binary search button
this is the requirement for binary search
Replace the sequential access algorithm to operate on the arrays with a binary search algorithm.
To implement this, the array’s data must be sorted. You may refer to an online example available at Array.prototype.sort() to learn about sorting data in arrays.
function Display_Athlete() {
var text = "<hr/>";
for (let i = 0; i < athlete_name.length; i++) {
text += "Athlete No - " + (i + 1) + ", Athlete Name is " + athlete_name[i]
+ " and height is " + athlete_height[i] + "<br>";
}
document.getElementById("message").innerHTML = text;
}
//Created function to remove the user
function Remove_Athlete() {
var person = prompt("Enter the name to remove the Athlete");
for (let i = 0; i < athlete_name.length; i++) {
athlete_name.splice(person - 1, 1);
athlete_height.splice(person - 1, 1);
alert(" Athlete_name " + athlete_name + " Athlete_height " + athlete_height + " is removed ");
}
}
//Create the function to find the user
function Find_Athlete() {
var person = prompt("Enter the name to Find the Athlete");
var text = "";
for (let i = 0; i < athlete_name.length; i++) {
if (athlete_name[i] == person) {
text += "Athlete No - " + (i + 1) + ", Athlete Name is " + athlete_name[i]
+ " and height is " + athlete_height[i] + "<br>";
}
}
document.getElementById("message").innerHTML = text;
if (text == "")
alert(`${person} Invalid Athlete name`);
return "";
}
function Binary_Search(){
}
In this piece of code you can see a JSON request that fetches some data. I need some help to check certain opportunities of minimizing the code and getting iterations with FOR instead of many IFs. Also, it would be nice if you advise anything on the differentiation system (how to make elements differ from each other)
<script type="text/javascript">
function deleteRow0() {
$('p.row0').remove();
};
function deleteRow1() {
$('p.row1').remove();
};
function deleteRow2() {
$('p.row2').remove();
};
function deleteRow3() {
$('p.row3').remove();
};
function deleteRow4() {
$('p.row4').remove();
};
</script>
<script type="text/javascript">
function hello2() {
//GETTING JSON INFO
$.getJSON("https://rawgit.com/Varinetz/e6cbadec972e76a340c41a65fcc2a6b3/raw/90191826a3bac2ff0761040ed1d95c59f14eaf26/frontend_test_table.json", function(json) {
$('#table-cars').css("display", "grid");
for (let counter = 0; counter < json.length; counter++) {
$('#table-cars').append("<p class='row" + counter +" main-text'>" + json[counter].title + "<br/>" + "<span class='sub-text'>" + json[counter].description + "</span>" + "</p>"
+ "<p class='row" + counter +" main-text'>" + json[counter].year + "</p>"
+ "<p id='color" + [counter] + "' class='row" + counter +" main-text'>" + json[counter].color + "</p>"
+ "<p id='status" + [counter] + "' class='row" + counter +" main-text'>" + json[counter].status + "</p>"
+ "<p class='row" + counter +" main-text'>" + json[counter].price + " руб." + "</p>"
+ "<p class='row" + counter +" main-text'>" + "<button class='delete' onclick='deleteRow" + [counter] + "()'>Удалить</button>" + "</p>");
// COLOR TEXT REPLACEMENT
if ($('p#color0').text("red")){
$('p#color0').text("").append("<img src='red.png'>");
}
if ($('p#color1').text("white")) {
$('p#color1').text("").append("<img src='white.png'>");
}
if ($('p#color2').text("black")) {
$('p#color2').text("").append("<img src='black.png'>");
}
if ($('p#color3').text("green")) {
$('p#color3').text("").append("<img src='green.png'>");
}
if ($('p#color4').text("grey")) {
$('p#color4').text("").append("<img src='grey.png'>");
}
// STATUS TEXT REPLACEMENT
if ($('p#status0').text("pednding")) {
$('p#status0').text("").append("Ожидается");
}
if ($('p#status1').text("out_of_stock")) {
$('p#status1').text("").append("Нет в наличии");
}
if ($('p#status2').text("in_stock")) {
$('p#status2').text("").append("В наличии");
}
if ($('p#status3').text("out_of_stock")) {
$('p#status3').text("").append("Нет в наличии");
}
if ($('p#status4').text("in_stock")) {
$('p#status4').text("").append("В наличии");
}
}
});
}
</script>
I expect this to be something like:
1) Iteration: For each p.row(i) {
compare it to many color (json.color)};
2) Any suggestion on differentiation system (i.e. changes in the FOR section, so it gives something easier to work with, not just simple p.row(n)). Of course, if it is possible.
I'm not going to rewrite the entire script, but in principle it would be something like this:
for (i = 0; i < 5; i++) {
var colors = ["red", "white", "black", "green", "grey"];
if ($('p#color' + i).text() == colors[i]){
$('p#color' + i).text("").append("<img src='" + colors[i] + ".png'>");
}
}
#Evik Ghazarian has a quality solution for the Text Translation portion of your script. Since this is the accepted answer, he allowed me to copy his solution so that the answers would be together:
function getTranslate(input) {
var inputMap = {
"pednding": "Ожидается",
"out_of_stock": "Нет в наличии",
"in_stock": "В наличии"
}
var defaultCode = input;
return inputMap[input] || defaultCode;
}
for (let i = 0; i < 5 , i ++){
var text = $("p#status"+i).text();
$("p#status"+i).text("").append(getTranslate(text));
}
Dynamic Iteration Counters
#Barmar mentioned in the comments below that the for loops that set a max iteration via i < 5 should actually be rewritten dynamically. I'll leave it to the OP to decide the best way to do this, but a good example might be something like i < json.length as used in the OP's original for loop.
First of all your code won't work because you are setting the text rather than comparing it. Second, you don't need to compare: just set the img src to text. Like below:
REMEMBER THIS IS FOR COLOR TEXT REPLACEMENT PART OF YOUR QUESTION
for (let i = 0; i < 5 , i ++){
let color = $("p#color"+i).text() + ".png";
$("p#color"+i).text("").append("<img src=" + color + ">");
}
FOR TEXT TRANSLATION YOU CAN USE:
function getTranslate(input) {
var inputMap = {
"pednding": "Ожидается",
"out_of_stock": "Нет в наличии",
"in_stock": "В наличии"
}
var defaultCode = input;
return inputMap[input] || defaultCode;
}
for (let i = 0; i < 5 , i ++){
var text = $("p#status"+i).text();
$("p#status"+i).text("").append(getTranslate(text));
}
EDIT - I don't think I explained it very well the first time.
I have a lot of data - it's in an Array, with each item in the array being an object. In the system I am working in (a control system for A/V devices, which uses JavaScript as the programming language), I am generating buttons based on the length of the array. I want to be able to position a button, and essentially know the X and Y coordinates for each button in the array - with X and Y being Row/Column. (which I then translate to a X/Y pixel position on my UI.
My initial code, which is below, is within a for loop, and I manually calculated the button position. But this is tedious, as I use this same function to show off different groups/sizes of buttons.
Anywhere there is mirage.log = console.log.
The code below is part of a For Loop
button.element.style.position = 'absolute'; //Do to all Buttons.
if (i == 0) //First Item
{
button.element.style.left = btn_Info.startLeft + 'px'; button.element.style.top = btn_Info.startTop + 'px';
}
else if (i <= btn_Info.numRow-1) //First Column.
{
mirage.log('Setting Position of First Column');
button.element.style.left = btn_Info.startLeft + 'px'; button.element.style.top = (btn_Info.height + btn_Info.vOffset) * i + btn_Info.startTop + 'px';
}
else if (i > btn_Info.numRow - 1 && i <= btn_Info.numRow * 2 - 1)
{
mirage.log('Setting Second column ' + i);
button.element.style.left = btn_Info.startLeft + btn_Info.width + btn_Info.hOffset + 'px'; button.element.style.top = (btn_Info.height + btn_Info.vOffset) * (i-btn_Info.numRow) + btn_Info.startTop + 'px';
}
else
{
mirage.log('Setting Third column ' + i);
button.element.style.left = btn_Info.startLeft + ((btn_Info.width + btn_Info.hOffset)*2) + 'px'; button.element.style.top = (btn_Info.height + btn_Info.vOffset) * (i - (btn_Info.numRow*2)) + btn_Info.startTop + 'px';
}
Thanks in advance for the help - I have grabbed so many answers from this forum over the last year, you guys are awesome!
EDIT -
I was able to get some adjustment if I generate rows first then columns:
I was able to get a little close with the help of a friend, and be able to adjust for a 2 column layout by doing the following:
encoder = {
'buttonVals':{'width':125,'height':50,'numCols':2,'numRows':null;'vOffset':10,'hOffset':10}
var posLeft;
var posTop;
posLeft = (i % encoder.buttonVals.numCols) * (encoder.buttonVals.width + encoder.buttonVals.hOffset) + encoder.buttonVals.startLeft;
posTop = Math.floor(i / encoder.buttonVals.numCols) * (encoder.buttonVals.height + encoder.buttonVals.vOffset) + encoder.buttonVals.startTop;
After working on this for a bit - here is the code that I got to work. This prints out both the row position, and the column position.
testFunction = function(incRow, incCol){
var myFunc = {
'testLength':0,
'numRows':incRow,
'numCols':incCol,
'array':[],
};
myFunc.testLength = incRow * incCol;
for(var c=0, posCol = 0, posRow = 0; c < myFunc.testLength; c++)
{
var whichRow;
posRow = Math.floor(c/myFunc.numRows);
whichRow = Math.floor(c/myFunc.numRows) + c;
if (whichRow > myFunc.numRows)
{
whichRow = whichRow - (myFunc.numRows * posRow) - posRow;
if (whichRow === 0)
{
posCol = posCol + 1;
}
}
console.log(c + ' : ' + whichRow + ' : ' + posCol);
}
};
testFunction(6,4);
I created minor encrypt method to convert a small string based on distance between characters, but can't for the life of me figure out how to reverse it without knowing the distance between each character from the initial conversion. See image for example how it works imgur.com/Ine4sBo.png
I've already made the encrypt method here (Javascript):
var all = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.#-?").split('');
var position;
//var oKey = "P";
function encrypt() // Encrypt Fixed
{
var sEncode = ("HI-MOM").split('');
var oKey = "P";
for (var i = 0; i < sEncode.length; i++) {
if (all.indexOf(oKey) < all.indexOf(sEncode[i])) {
position = all.indexOf(sEncode[i]) - all.indexOf(oKey);
output.value += "oKey: " + oKey + " distance to sEncode[" + i + "]: " + sEncode[i] + " Count: " + position + " Final Char: " + all[position-1] + "\n";
oKey = sEncode[i];
}
else {
position = all.length - all.indexOf(oKey) + all.indexOf(sEncode[i]);
output.value += "oKey: " + oKey + " distance to sEncode[" + i + "]: " + sEncode[i] + " Count: " + position + " Final Char: " + all[position-1] + "\n";
oKey = sEncode[i];
}
}
}
However, it's the decrypt() method that's killing me.
From what I can tell, your encrypt function can be reduced to this:
var all = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.#-?").split('');
function encrypt(str)
{
var sEncode = str.split('');
var result = '';
var oKey = "P";
for(var i = 0; i < sEncode.length; i++)
{
result += all[(all.indexOf(sEncode[i]) - all.indexOf(oKey) + all.length - 1) % all.length];
oKey = sEncode[i];
}
return result;
}
(I got rid of the if clause by adding all.length either way, and removing it again with the remainder operator if necessary.)
From there, all you need to do is flip the operands (- all.indexOf(oKey) - 1 becomes + all.indexOf(oKey) + 1 (and since we have no more subtractions, adding all.length is no longer necessary)) and reverse the order (so oKey gets assigned the transformed value instead of the original one):
var all = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.#-?").split('');
function decrypt(str)
{
var sEncode = str.split('');
var result = '';
var oKey = "P";
for(var i = 0; i < sEncode.length; i++)
{
oKey = all[(all.indexOf(sEncode[i]) + all.indexOf(oKey) + 1) % all.length];
result += oKey;
}
return result;
}
Here is a demo of the current code: http://mobilocloud.com/schedule/
I have one js object that contains multiple arrays, each array has two time hashes (one start time and one end time / I've got them using getTime()). I want to compare all of the arrays contained in the object to check for all of the intersections between time ranges. I've got the script working but it only compares two arrays at a time (in the end I get groups of two overlapped events). I want to get groups of all overlapped events, not only by two.
Here is the actual code:
function _DetectOverlapedEvents(column) {
events;
groups;
sgroups;
todeoverlap[column] = new Array();
groups[column] = new Array();
sgroups[column] = new Array();
var $curid=0;
var $curevent= new Array();
if(events[column].length > 1){
$(events[column]).each(function(key, $secondevent) {
//alert("Comparing : " + $curevent["name"] + " and " + $secondevent["name"] + "\n" + $curevent["starthash"] + "<" +$secondevent["endhash"] + " = " + ($curevent["starthash"] < $secondevent["endhash"]) + "\n&&\n" + $curevent["endhash"] + ">" + $secondevent["starthash"] + " = " + ($curevent["endhash"] > $secondevent["starthash"]));
if($curevent.length<2) {
$curevent=$secondevent;
} else if(($curevent["starthash"] < $secondevent["endhash"]) && ($curevent["endhash"] > $secondevent["starthash"])) {
//alert("added " + $curevent["name"] + " and " + $secondevent["name"]);
toextend = {left: $curevent, right: $secondevent};
groups[column].push(toextend);
sgroups[column].push($curevent, $secondevent);
//console.log("groups: " + JSON.stringify(groups[column]));
$curid++;
}
$curevent = $secondevent;
});
}
//console.log(JSON.stringify(groups));
}