I am working with some CSS Backgrounds (http://css3pie.com/demos/gradient-patterns/) in an application and want to be able to scale the design with a slider. Here's a JSFiddle. I was able to scale X & Y separately on some like the Stripes and Picnic designs where I just had to play with background-size:50px 50px; like this:
//setup the variables based off the css which was set using dropdown
gridItems = $(document.activeElement).val().split("; ");
for (i = 0; i < gridItems.length -1; i++) {
gridSettings = gridItems[i].split(":");
if (gridSettings[0]=="background-size"){
gridSize = gridSettings[1].split(" ");
gridX = gridSize[0];
gridY = gridSize[1]
}
//on the action of the slide - update value
$('#gridXY-'+key).on("slide", function(slideEvt) {
gridXY = slideEvt.value;
$('.draggable-' + currentLayer).css("background-size", "calc("+ gridX +" * "+ gridXY +") calc("+ gridY +" * "+ gridXY +")");
});
Which can be set either numerically or using but when it gets to something like the Blue Print it has a lot more settings background-size:100px 100px, 100px 100px, 20px 20px, 20px 20px;
I am trying to do this right so that it can take a variable number of those, and can write something that could work, but the method I have in mind is really messy, hoping for some help scaling this that might be a little cleaner than what I would do.
I did find this:http://codepen.io/Erik/pen/JGnsB but he is using LESS to declare variables, if possible I would like to stay away from that.
UPDATE:
Here is a JSFiddle of it: http://jsfiddle.net/4L3d9qh2/
I added a function that should have let me update it, but for some reason the calc() function doesn't seem to be working to update the div style. After processing, it looks like this:
$('.draggable-0').css("background-size", calc(100px - 4) calc(100px - 4), calc(100px - 4) calc(100px - 4), calc(20px - 4) calc(20px - 4), calc(20px - 4) calc(20px - 4));
$.each(gridSizeArray, function( k, v ){
if (gridIncrement==1)
{
gridXY = "calc(" + v +" - " + value + ") ";
}else{
if(isOdd(gridIncrement)){
gridXY = gridXY + "calc(" + v +" - " + value + ") ";
}else{
gridXY = gridXY + "calc(" + v +" - " + value + "), ";
}
}
gridIncrement++
})
Here was the final code that works. Using .each() loop through and if it is even, add a comma, then remove the last comma at the end.
gridItems = $(document.activeElement).val().split("; ");
for (i = 0; i < gridItems.length -1; i++) {
gridSettings = gridItems[i].split(":");
if (gridSettings[0]=="background-size"){
gridSizeString = gridSettings[1].replace(/,/gi, '');
gridSizeArray = gridSizeString.split(" ");
}
$('[data-type="sliderLayer"][data-layer="'+currentLayer+'"][data-slide="'+currentSlide+'"]').css(gridSettings[0], gridSettings[1]);
}
$.each(gridSizeArray, function( k, v ){
if (gridIncrement==1)
{
gridXY = "calc(" + v +" + " + value + "px) ";
}else{
if(isOdd(gridIncrement)){
gridXY = gridXY + " calc(" + v +" + " + value + "px) ";
}else{
gridXY = gridXY + "calc(" + v +" + " + value + "px),";
}
}
gridIncrement++
})
if (isOdd(gridIncrement))
{
gridXY = gridXY.substring(0, gridXY.length - 1);
}
Related
I'm working on a leaflet js map atm.
There are some items that I want to apply a class to, depending on their inner text. Seems as though two circles at a certain size just overlap. Adding some CSS in that case so they're no longer overlapping.
//function searches for all <text> elements within svg tags for the queryText
// and then appends them with the appendText
function addClasserino() {
let elements = document.querySelectorAll('map-marker marker-bg-condition'); // get all circle elements as a NodeList
elements.forEach(el => { // go through each text element
if (el.innerText < 10) { // if the innerHTML matches the query HTML then
elements.addClass('updated'); // add the class
}
})
}
document.addEventListener("DOMContentLoaded", function(){
//pass in the search text and the appending text as arguments
addClasserino();
});
This is what I got so far. Doesn't seem to be working.
.map-marker.marker-bg-condition needs to be moved across a bit. Got the CSS here:
.map-marker.marker-bg-condition.updated{
margin-top: -19px;
margin-left: -19px;
}
With Leaflet JS, the zoom level changes and items are updated accordingly. This of my map showing all details at the world view, and then breaking down to state as you zoom in.
The unexpected behavior is that the css isn't applying and where bubbles are overlapping is because of this. This is the original code but I can't change it and get it to work even with an if statement.
getMarkerHtml: function(count, color) {
var size = this.getMarkerSize(count);
var hsize = (size / 2) - 6;
var font = count < 1000 ? Math.ceil(size / 3) : Math.ceil(size / 4);
if(count < 100) {
font = font + 3;
}
var cluster_classes = [
'map-marker',
'marker-bg-' + (Filters.colors.profile === color ? 'profile' : 'condition')
];
if(this.zoomLevel !== 'zip') {
size = size * 1.5;
if(petMapFilters.colors.profile !== color) {
hsize = size / 2;
}
}
if(this.zoomLevel === 'zip') {
var cluster_styles = [
'margin-left: -' + hsize + 80 + 'px;', NOTE: I tried this to offset on zip zoom bit it's not working END OF NOTE
'margin-top: -' + hsize + 80 +'px;',
'width: ' + size + 'px;',
'height: ' + size + 'px;',
'font-size: ' + font + 'px;'
];
} else {
var cluster_styles = [
'margin-left: -' + hsize + 'px;',
'margin-top: -' + hsize + 'px;',
'width: ' + size + 'px;',
'height: ' + size + 'px;',
'font-size: ' + font + 'px;'
];};
var div_style = [
'line-height: ' + (size - (size * 0.3)) + 'px;'
];
count = this.formatCount(count);
return '<div class="' + cluster_classes.join(' ') + '" tabindex="0" style="' + cluster_styles.join(' ') + '"><div style="' + div_style.join(' ') + '">' + count + '</div></div>';
},
Please let me know what I am doing wrong here as I am not able to identify this myself.
The issue at hand:
Thanks.
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);
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
Here I have some code which creates an image that hides another image in it.
I print out some rgb values to see the change (after implementing function chopToHide and function shift, but I don't understand by what calculation the numbers have changed by). This bit of code is part of a larger program to hide one image inside another (steganography).
This is the environment where I 'm working in: http://www.dukelearntoprogram.com/course1/example/index.php
var start = new SimpleImage("astrachan.jpg");
var hide = new SimpleImage("duvall.jpg");
print (start);
print(hide);
print ("width and height of astrachan picture");
print (start.getHeight(), start.getWidth());
print ("width and height of duvall picture")
print (hide.getHeight(), hide.getWidth());
var cropWidth = start.getWidth();
if (hide.getWidth() < cropWidth) {
cropWidth = hide.getWidth();
}
var cropHeight = start.getHeight();
if (hide.getHeight() < cropHeight) {
cropHeight = hide.getHeight();
}
start = crop(start,cropWidth, cropHeight);
hide = crop(hide,cropWidth, cropHeight);
print(start);
print(hide);
function crop(image, width, height){
var n = new SimpleImage(width,height);
for(var p of image.values()){
var x = p.getX();
var y = p.getY();
if (x < width && y < height){
var np = n.getPixel(x,y);
np.setRed(p.getRed());
np.setBlue(p.getBlue());
np.setGreen(p.getGreen());
}
}
return n;
}
//print (start);
//print(hide);
print ("cropped width and height of astrachan picture");
print (start.getHeight(), start.getWidth());
print ("cropped width and height of duvall picture")
print (hide.getHeight(), hide.getWidth());
function chopToHide(image){
for(var px of image.values()){
px.setRed(pixchange(px.getRed()));
px.setGreen(pixchange(px.getGreen()));
px.setBlue(pixchange(px.getBlue()));
}
return image;
}
function pixchange(pixval){
var x = Math.floor(pixval/16) * 16;
return x;
}
function shift(oldImage){
var newImage = new SimpleImage(oldImage.getWidth(), oldImage.getHeight());
for(var oldPixel of oldImage.values()){
var x = oldPixel.getX();
var y = oldPixel.getY();
var newPixel = newImage.getPixel(x, y);
newPixel.setRed( Math.floor(oldPixel.getRed()/16) );
newPixel.setGreen( Math.floor(oldPixel.getGreen()/16) );
newPixel.setBlue( Math.floor(oldPixel.getBlue()/16) );
}
return newImage;
}
print("before applying the chopToHide function to the image start:");
for(i = 1; i <= 100; i+=20 ){
var pixel = start.getPixel(i, i+5);
print("pixel at (" + pixel.getX() + "," + pixel.getY() + ")-> R= " +
pixel.getRed() + " : G= " + pixel.getGreen() + " : B= " + pixel.getBlue() );
}
//print (start);
start = chopToHide(start);
print("After applying the chopToHide function to the image start:");
for(i = 1; i <= 100; i+=20 ){
var pixel = start.getPixel(i, i+5);
print("pixel at (" + pixel.getX() + "," + pixel.getY() + ")-> R= " +
pixel.getRed() + " : G= " + pixel.getGreen() + " : B= " + pixel.getBlue() );
}
//print (start);
//print (hide);
print("Before applying the shift function to the image hide:");
for(i = 1; i <= 100; i+=20 ){
var pixel = hide.getPixel(i, i+5);
print("pixel at (" + pixel.getX() + "," + pixel.getY() + ")-> R= " +
pixel.getRed() + " : G= " + pixel.getGreen() + " : B= " + pixel.getBlue() );
}
hide = shift(hide);
print("After applying the shift function to the image hide:");
for(i = 1; i <= 100; i+=20 ){
var pixel = hide.getPixel(i, i+5);
print("pixel at (" + pixel.getX() + "," + pixel.getY() + ")-> R= "
+ pixel.getRed() + " : G= " + pixel.getGreen() + " : B= " +
pixel.getBlue() );
}
The idea this code is working towards is to reduce the colour range from 0..255 (8 bits, a "byte") per colour channel to 0..15 (4 bits, a "nybble") per colour channel on both pictures, then combine the two nybbles into one byte. The picture whose colours are in the high nybble will give the perceptible colour change (in increments of 16); the picture hiding in the low nybble will shade the colour of the main picture's pixels imperceptibly.
The formula should be:
steganoImageColour = (overtImageColour & 240) | (covertImageColour >> 4)
or equivalently (but not as fast):
steganoImageColour = (Math.floor(overtImageColour / 16) * 16) +
Math.floor(covertImageColour / 16)
To extract the covert image, you just take the low nybble and promote it to high:
reconstructedCovertImageColour = (steganoImageColour & 15) << 4
or equivalently,
reconstructedCovertImageColour = (steganoImageColour % 16) * 16
For example, if you have a green-yellow pixel in the overt image (173 255 47) and a light sky blue pixel in the covert image (135 206 250), the resulting pixel is (168 252 47), which is still very close to the original green-yellow, but one can reconstruct (128 192 240) from it, which is very close to the original light sky blue.
<div style="background-color: rgb(173,255,47)">overt (green-yellow)</div>
<div style="background-color: rgb(135,206,250)">covert (light sky blue)</div>
<div style="background-color: rgb(168,252,47)">stegano (close enough to green-yellow)</div>
<div style="background-color: rgb(128,192,240)">reconstructed covert (close enough to light sky blue)</div>
I want to make a small game, but I have some start up problems.
When I try to get the position of track or trackCont, it always returns x: 0, y: 0. Doesn't get right position moving the DIV with:
float: right;
display: block;
and even doesn't work using:
position: absolute;
left: 100px;
Here's the code I am using:
var Player = new Array();
var trackEntity;
function getPosition(elem){
xPos = 0;
yPos = 0;
while(elem){
xPos += (elem.offsetLeft + elem.clientLeft);
yPos += (elem.offsetTop + elem.clientTop);
elem = elem.offsetParent;
}
return {x: xPos, y: yPos};
}
window.onload = function(){
trackEntity = document.getElementById("trackCont");
for (i = 0; i < 4; i += 1){
Player[i] = new Object();
document.body.innerHTML += "<div id='p" + i + "' class='player'></div>";
Player[i].entity = document.getElementById("p" + i);
Player[i].entity.style.backgroundColor = "rgb("
+ Math.floor(Math.random() * 256) + ", "
+ Math.floor(Math.random() * 256) + ", "
+ Math.floor(Math.random() * 256) +
")";
Player[i].entity.style.left = (getPosition(trackEntity).x) + 20;
Player[i].entity.style.top = (getPosition(trackEntity).y) + 20;
}
}
http://jsfiddle.net/dh8uf6Lp/
You need to supply a unit to when assigning a value to css left.
Player[i].entity.style.left = (getPosition(trackEntity).x) + 20 +"px";
If you assign a value to a css dimension or position property it will not update when no unit is given.
It seems that when getPosition(trackEntity) is called it doesn't know where it is in the DOM. This is caused by
document.body.innerHTML += "<div id='p" + i + "' class='player'></div>";
This causes the browser to redraw all elements and trackEntity loses it reference.
Solution: do not insert html via innerHTML, but create the div and append it to the DOM.
Player[i].entity = document.createElement("div");
Player[i].entity.id = "p" + i;
//etc.
document.body.appendChild(Player[i].entity);
//Run position code.
http://jsfiddle.net/dh8uf6Lp/3/