I'm creating a web app to create pixelmaps for large LED displays. The maps are basically large checkerboard patterns of various sizes with different constraints. I'm running into snags trying to draw arrows pointing in certain directions dependent on their position within a) the entire grid, and b) within smaller sub-sections of the map.
Upon loading the jsfiddle, you can scroll down and see a correct example. The arrows snake through the red/blue area of the map from left to right, going down one row at a time. Now if you select the second data flow option (the 2nd radio button from the left on the top row of radio buttons) you'll see the direction of the arrows change but the map doesn't draw correctly.
I need help getting this running efficiently. Nested loops within loops within loops seems slow. Plus I'm just in over my head and a bit confused. There's a working earlier version of the app at (http://www.blinkingthings.com) if you need a more complete picture of what I'm asking for.
I'd also appreciate any criticism of this javascript as it's not my expertise.
JS:
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var width=128;
var height=128;
var columns=16;
var rows=9;
var color1="#d9534f";//redish
var color2="#428bca";//bluish
var color4="#00FF00";//greenish
var color3="#FFFF00";//yellowish
var textcolor="#FFFFFF";
var datacolor="#FFFFFF";
var bordercolor ="#5cb85c";
var dataStartColor ="#5cb85c";
var infoBackgroundColor = "rgba(255,255,255,.01)";
var infoForegroundColor = "rgba(0,0,255,.1)";
var upArr = '\u2191';
var downArr = '\u2193';
var leftArr = '\u2190';
var rightArr = '\u2192';
var stopSign = '\uD83D\uDEAB';
var omega = '\u03A9';
var oddOrEven = "odd";
var colOddEven = "odd";
var dataFlow = "1";
var drawCoords = true;
var drawData = true;
var drawInfo = true;
var drawUser = false;
var counter = 1;
var xStart=0;
var yStart=0;
var resWidthLimit=1920;
var resHeightLimit=1080;
var colsLimit = Math.floor(resWidthLimit/width);
var rowsLimit = Math.floor(resHeightLimit/height);
var outputsHigh = Math.ceil(rows/rowsLimit);
var outputsWide = Math.ceil(columns/colsLimit);
var alphabet = "a b c d e f g h i j k l m n o p q r s t u v w x y z aa bb cc dd ee ff gg hh ii jj kk ll mm nn oo pp qq rr ss tt uu vv ww xx yy zz aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll mmm nnn ooo ppp qqq rrr sss ttt uuu vvv www xxx yyy zzz".split(" ");
var topEdge = false;
var bottomEdge = false;
var leftEdge = false;
var rightEdge = false;
var rowsOdd = false;
var columnsOdd = false;
var outTopEdge = false;
var outBottomEdge = false;
var outLeftEdge = false;
var outRightEdge = false;
var outRowsOdd = false;
var outColumnsOdd = false;
// references to the input-text elements
// used to let user change the rect width & height
var $width=document.getElementById('width');
var $height=document.getElementById('height');
var $rows=document.getElementById('rows');
var $columns=document.getElementById('columns');
var $resWidthLimit=document.getElementById('resWidthLimit');
var $resHeightLimit=document.getElementById('resHeightLimit');
var $tileSwap=document.getElementById('tileSwap');
var $wallSwap=document.getElementById('wallSwap');
var $outputSwap=document.getElementById('outputSwap');
var $tilePresets=document.getElementById('tilePresets');
var $outputPresets=document.getElementById('outputPresets');
var $colSlide=document.getElementById('colSlide');
var $rowSlide=document.getElementById('rowSlide');
var $radio1=document.getElementById('radio1');
var $radio2=document.getElementById('radio2');
var $radio3=document.getElementById('radio3');
var $radio4=document.getElementById('radio4');
var $radio5=document.getElementById('radio5');
var $radio6=document.getElementById('radio6');
var $radio7=document.getElementById('radio7');
var $radio8=document.getElementById('radio8');
var $drawcoords=document.getElementById('draw_coords_check');
var $drawdata=document.getElementById('draw_data_check');
var $drawinfo=document.getElementById('draw_info_check');
var $drawuser=document.getElementById('draw_user_check');
// set the initial input-text values to the width/height vars
$width.value=width;
$height.value=height;
$rows.value=rows;
$columns.value=columns;
$resWidthLimit.value=resWidthLimit;
$resHeightLimit.value=resHeightLimit;
$width.addEventListener("change", function(){
width=this.value; //.value converts input field int to string***
outputsWide = Math.ceil(columns/colsLimit);
colsLimit = Math.floor(resWidthLimit/width);
draw();
}, false);
$height.addEventListener("change", function(){
height=this.value; //.value converts input field int to string***
outputsHigh = Math.ceil(rows/rowsLimit);
rowsLimit = Math.floor(resHeightLimit/height);
draw();
}, false);
$rows.addEventListener("keyup", function(){
rows=this.value; //.value converts input field int to string***
outputsHigh = Math.ceil(rows/rowsLimit);
draw();
}, false);
$columns.addEventListener("keyup", function(){
columns=this.value; //.value converts input field int to string***
outputsWide = Math.ceil(columns/colsLimit);
draw();
}, false);
$resWidthLimit.addEventListener("keyup", function(){
resWidthLimit=this.value; //.value converts input field int to string***
colsLimit = Math.floor(resWidthLimit/width);
outputsWide = Math.ceil(columns/colsLimit);
setTimeout(function() { draw(); }, 500); //had to add small delay to prevent crashing. look into
}, false);
$resHeightLimit.addEventListener("keyup", function(){
resHeightLimit=this.value; //.value converts input field int to string***
rowsLimit = Math.floor(resHeightLimit/height);
outputsHigh = Math.ceil(rows/rowsLimit);
setTimeout(function() { draw(); }, 500); //had to add small delay to prevent crashing. look into
}, false);
$wallSwap.addEventListener("click", function(){
var temp = $('#columns').val();
$('#columns').val($('#rows').val());
$('#rows').val(temp);
columns=$('#columns').val();
rows=$('#rows').val();
outputsWide = Math.ceil(columns/colsLimit);
outputsHigh = Math.ceil(rows/rowsLimit);
draw();
}, false);
$tileSwap.addEventListener("click", function(){
var temp = $('#width').val();
$('#width').val($('#height').val());
$('#height').val(temp);
width=$('#width').val();
height=$('#height').val();
outputsWide = Math.ceil(columns/colsLimit);
colsLimit = Math.floor(resWidthLimit/width);
outputsHigh = Math.ceil(rows/rowsLimit);
rowsLimit = Math.floor(resHeightLimit/height);
draw();
}, false);
$outputSwap.addEventListener("click", function(){
var temp = $('#resWidthLimit').val();
$('#resWidthLimit').val($('#resHeightLimit').val());
$('#resHeightLimit').val(temp);
resWidthLimit=$('#resWidthLimit').val();
resHeightLimit=$('#resHeightLimit').val();
colsLimit = Math.floor(resWidthLimit/width);
rowsLimit = Math.floor(resHeightLimit/height);
draw();
}, false);
$tilePresets.addEventListener("click", function(){
width=$('#width').val();
height=$('#height').val();
outputsHigh = Math.ceil(rows/rowsLimit);
rowsLimit = Math.floor(resHeightLimit/height);
outputsWide = Math.ceil(columns/colsLimit);
colsLimit = Math.floor(resWidthLimit/width);
draw();
}, false);
$outputPresets.addEventListener("click", function(){
resWidthLimit=$('#resWidthLimit').val();
resHeightLimit=$('#resHeightLimit').val();
rowsLimit = Math.floor(resHeightLimit/height);
colsLimit = Math.floor(resWidthLimit/width);
draw();
}, false);
$radio1.addEventListener("click", function(){
dataFlow=this.value; //.value converts input field int to string***
draw();
}, false);
$radio2.addEventListener("click", function(){
dataFlow=this.value; //.value converts input field int to string***
draw();
}, false);
$radio3.addEventListener("click", function(){
dataFlow=this.value; //.value converts input field int to string***
draw();
}, false);
$radio4.addEventListener("click", function(){
dataFlow=this.value; //.value converts input field int to string***
draw();
}, false);
$radio5.addEventListener("click", function(){
dataFlow=this.value; //.value converts input field int to string***
draw();
}, false);
$radio6.addEventListener("click", function(){
dataFlow=this.value; //.value converts input field int to string***
draw();
}, false);
$radio7.addEventListener("click", function(){
dataFlow=this.value; //.value converts input field int to string***
draw();
}, false);
$radio8.addEventListener("click", function(){
dataFlow=this.value; //.value converts input field int to string***
draw();
}, false);
$drawcoords.addEventListener("change", function(){
drawCoords = !drawCoords; //flips boolean of drawCoords t/f
draw();
}, false);
$drawdata.addEventListener("change", function(){
drawData = !drawData; //flips boolean of drawData t/f
draw();
}, false);
$drawinfo.addEventListener("change", function(){
drawInfo = !drawInfo; //flips boolean of drawInfo t/f
draw();
}, false);
$drawuser.addEventListener("change", function(){
drawUser = !drawUser; //flips boolean of drawUser t/f
draw();
}, false);
draw();//inital draw
function draw(){
clearAll();
tilesByOutput();
}//end draw()
function clearAll(){
ctx.canvas.width = +width * +columns; //set entire canvas width
ctx.canvas.height = +height * +rows; //set entire canvas height
ctx.clearRect(0,0,canvas.width,canvas.height); //clear out entirety of canvas
xStart=0; //reset x coord to 0 (default)
yStart=0; //reset y coord to 0 (default)
}
function allTiles(){
for (var j = 0; j < rows; j++){ //for every row under limit
for (var i = 0; i < columns; i++) { //for every column under limit
(i % 2) !=1 ? colOddEven = "odd" : colOddEven = "even"; //every other coloumn
if ((j % 2) !=1){ //for every other row
oddOrEven = "odd";
(i % 2) != 1 ? ctx.fillStyle=red : ctx.fillStyle=blue;//start alternating patter with color option 1
} else {
oddOrEven = "even";
//start alternating patter with color option 2
(i % 2) != 1 ? ctx.fillStyle=blue : ctx.fillStyle=red;
} //end if/else
ctx.fillRect(xStart,yStart,width,height); //draw single tile
console.log("Single Tile Drawn at : (" + xStart + ", " + yStart + ")");
xStart = +xStart + +width; //shift starting coords for next column
}//end columns for
xStart = 0; //reset x coord to 0 (default) for begining of next row
yStart = +yStart + +height; //shift starting coords for next row
}//end rows for
}//end allTiles
function tilesByOutput(){
for (var l=0; l<=outputsWide; l++){//for each necessary output (width)
//console.log("Output Width = " + l);
for(var k=0; k<=outputsHigh; k++){//for each necessary output (height)
xStart = +colsLimit*l * +width;//0 on first loop, moves to right edge of output after
yStart = +rowsLimit*k * +height;//0 on first loop, moves to bottom edge of output after
for (var j = rowsLimit*k; (j < rowsLimit*(k+1)); j++){ //for every row wihtin current output's limit
for (var i = colsLimit*l; (i < colsLimit*(l+1) ); i++) { //for every column within current output's limit
if (i>columns-1) //previous loops are running too many times, this safeguards them.
{
continue;
} else if (j>rows-1){
continue;
}//end of for loop safeguard
var xLimit = i-(colsLimit*l);
var yLimit = j-(rowsLimit*k);
i == columns-1 ? rightEdge = true : rightEdge = false;
i == 0 ? leftEdge = true : leftEdge = false;
j == rows-1 ? bottomEdge = true : bottomEdge = false;
j == 0 ? topEdge = true : topEdge = false;
(i % 2) != 1 ? columnsOdd = true : columnsOdd = false;
(j % 2) != 1 ? rowsOdd = true : rowsOdd = false;
xLimit == colsLimit-1 ? outRightEdge = true : outRightEdge = false;
xLimit == 0 ? outLeftEdge = true : outLeftEdge = false;
yLimit == rowsLimit-1 ? outBottomEdge = true : outBottomEdge = false;
yLimit == 0 ? outTopEdge = true : outTopEdge = false;
(xLimit % 2) != 1 ? outColumnsOdd = true : outColumnsOdd = false;
(yLimit % 2) != 1 ? outRowsOdd = true : outRowsOdd = false;
(i % 2) !=1 ? colOddEven = "odd" : colOddEven = "even"; //every other coloumn odd or even (for data arrows)
//Step 1 : Figure out background color for current tile.
(l % 2) !=1 ? ( //if output x coord (l) is odd combo 1 : even combo 2
(k % 2) !=1 ? ( //if output y coord is odd (k) combo 1 : even combo 2
(outRowsOdd) ? ( //for every other row //rows: every other row in current output alternate between c1/c2
oddOrEven = "odd",
(outColumnsOdd) ? ctx.fillStyle=color1 : ctx.fillStyle=color2//columns: odds c1 : evens c2 (first row, first column is color1)
) : ( //middle j next row
oddOrEven = "even",
(outColumnsOdd) ? ctx.fillStyle=color2 : ctx.fillStyle=color1//columns: odds c2 : evens c1
) //end j end of rows for output v1
) : ( //middle k end of combo 1, begin combo 2 //output columns:
(outRowsOdd) ? ( //for every other row //rows: every other row in current output alternate between c3/c4
oddOrEven = "odd",
(outColumnsOdd) ? ctx.fillStyle= color3: ctx.fillStyle=color4//columns: odds c3 : evens c4
) : (//middle j //rows: next row
oddOrEven = "even",
(outColumnsOdd) ? ctx.fillStyle=color4 : ctx.fillStyle=color3//columns: odds c4 : evens c3
) //end j //rows:
)//end k //output columns:
) : ( //middle l //output rows:
//end output color alternation 1
(k % 2) !=1 ? ( //if output y coord is odd (k) alternate output colorcombos (red/blue or green/yellow)
(outRowsOdd) ? ( //for every other row
oddOrEven = "odd",
(outColumnsOdd) ? ctx.fillStyle=color3 : ctx.fillStyle=color4//start alternating patter with color option 1
) : ( //middle j
oddOrEven = "even",
//start alternating patter with color option 2
(outColumnsOdd) ? ctx.fillStyle=color4 : ctx.fillStyle=color3
) //end j
) : ( //middle k
(outRowsOdd) !=1 ? ( //for every other row
oddOrEven = "odd",
(outColumnsOdd) ? ctx.fillStyle= color1: ctx.fillStyle=color2//start alternating patter with color option 1
) : ( //middle j
oddOrEven = "even",
//start alternating patter with color option 2
(outColumnsOdd) ? ctx.fillStyle=color2 : ctx.fillStyle=color1
) //end j
)//end k
)//end l
ctx.fillRect(xStart,yStart,width,height); //draw single tile
counter++;
//alert(yLimit + " ," + xLimit);
//draw alphanumeric coordinates
if (drawCoords){ //check drawCoords checkbox. no check = no coords
var alphaX = xStart;
var alphaY = yStart;
ctx.fillStyle=textcolor;
if (+width < 35 || +height < 35){ //tile size check
ctx.font = "8px Helvetica";
alphaX = xStart+4;
alphaY = yStart+15;
} else if (+width < 54 || +height < 54){ //tile size check
ctx.font = "10px Helvetica";
alphaX = xStart+6;
alphaY = yStart+15;
} else if (+width < 64 || +height < 64){ //tile size check
ctx.font = "14px Helvetica";
alphaX = xStart+6;
alphaY = yStart+20;
} else if (+width < 110 || +height < 110){ //tile size check
ctx.font = "24px Helvetica";
alphaX = xStart+6;
alphaY = yStart+30;
} else {
ctx.font = "30px Helvetica";
alphaX = xStart+10;
alphaY = yStart+40;
}//end size check
ctx.fillText(alphabet[xLimit].toUpperCase() + (yLimit+1),alphaX,alphaY); //draw alpha then number
}
//ARROW DIRECTION DETERMINATION
//draw data flow (default for starting top left with horizontal rows.
var arrow = downArr; //default direction
switch (dataFlow){
case "1"://dataFlow=1
//(j % 2) != 1 ? arrow = rightArr : arrow = leftArr; //even/odd row check
i == columns-1 ? ( //last column of entire map
(outRowsOdd) ? arrow = downArr : //output row odd
(columns == (colsLimit*l)+1 && i == columns-1) ? //only 1 column of rightmost output?
arrow = downArr : arrow = leftArr//far right column + single : far right column part of bigger output
) : ( //everything but last column of entire map
(outRowsOdd) ?
(arrow = rightArr, xLimit == colsLimit-1 ? arrow = downArr : arrow = rightArr )//odd rows default to right, last column of output down, otherwise right.
: xLimit == 0 ? arrow = downArr /*even+left edge*/
: arrow = leftArr/*even*/
);//far right edge check
break;
case "2"://dataFlow=2
i == columns-1 ? ( //last column of entire map
(outRowsOdd) ? arrow = downArr : //output row odd
(columns == (colsLimit*l)+1 && i == columns-1) ? //only 1 column of rightmost output?
arrow = downArr : arrow = downArr//far right column + single : far right column part of bigger output
) : ( //everything but last column of entire map
(outRowsOdd) ?
(arrow = leftArr, xLimit == colsLimit-1 ? arrow = leftArr : arrow = leftArr )//odd rows default to right, last column of output down, otherwise right.
: xLimit == 0 ? arrow = downArr /*even+left edge*/
: arrow = rightArr/*even*/
);//far right edge check
break;
}
//ARROW COLOR DETERMINATION
if (drawData){ //check drawData checkbox. no check = no data path
ctx.fillStyle=datacolor;
if (dataFlow == 1){ //check which data case and tile being drawn to change first tile in data chain's arrow to green
if (yLimit== 0 && xLimit== 0){ //if top left
ctx.fillStyle = dataStartColor;
}
if (rowsOdd) {//if odd row
if (yLimit==rowsLimit-1 || j==rows-1){//if odd bottom of section or entire map
if(xLimit==colsLimit-1||xLimit==columns-1||i==columns-1){//if last column of section or entire map
arrow = stopSign;
}//end right edge check
else if (columns == colsLimit+1 && i == columns-1 ){//if theres only one column on next section
arrow = stopSign;
}//end check for single extra column
}//end bottom edge check
} else {//if even row
if (yLimit==rowsLimit-1 || j==rows-1){//if even bottom of section or entire map
if (xLimit == 0 || i == 0){ //if first column of section or entire map
arrow = stopSign;
}//end left edge check
}//end bottom edge check
}//end current row odd even check
} else {
}
if (+width < 35 || +height < 35){ //tile size check
ctx.font = "8px Helvetica";
ctx.fillText(arrow,xStart+20,yStart+10); //small
} else if (+width < 54 || +height < 54){ //tile size check
ctx.font = "10px Helvetica";
ctx.fillText(arrow,xStart+25,yStart+15); //med
} else if (+width < 64 || +height < 64){ //tile size check
ctx.font = "14px Helvetica";
ctx.fillText(arrow,xStart+30,yStart+20); //med
} else if (+width < 110 || +height < 110){ //tile size check
ctx.font = "24px Helvetica";
ctx.fillText(arrow,xStart+40,yStart+30); //med
} else {
ctx.font = "30px Helvetica";
ctx.fillText(arrow,xStart+80,yStart+40); //large
}//end size check
}//end of data draw check
// #### Draw Info
if (drawInfo) { //draw info tile if checkbox checkes
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
tileCount = (+columns * +rows);
var hRes = (+width * +columns);
var vRes = (+height * +rows);
var tPix = (hRes*vRes);
var info1 = "Total Resolution : "+hRes+" x "+vRes+". Total tiles : " +tileCount+ ". ("+numberWithCommas(tPix)+") pixels";
var info2 = "Single Tile Resolution : "+width+" x "+height;
var info3 = "Maximum Output Resolution : "+resWidthLimit+" x "+resHeightLimit+". Max tiles per output : "+(colsLimit*rowsLimit)+" tiles.";
var info4 = "Required Outputs : "+outputsWide*outputsHigh;
var info5 ="";
if (drawUser){
var info5 = $('#userText').val();
}
var rectHeight = 200;
var rectWidth = 600;
var rectX = leftMarg;
var rectY = topMarg;
var topMarg = (vRes/2)-(rectHeight/2);
var leftMarg = (hRes/2)-(rectWidth/2);
ctx.fillStyle =infoBackgroundColor;
ctx.fillRect(leftMarg,topMarg,rectWidth,rectHeight);
ctx.fillStyle=infoForegroundColor;
ctx.font = "12px Lucida Console";
ctx.textAlign="center";
ctx.font = "14px Lucida Console";
ctx.fillText(info5,rectX+(rectWidth/2),rectY+(rectHeight/2)-14);
ctx.font = "12px Lucida Console";
rectY = rectY+14;//new line
ctx.fillText(info1,rectX+(rectWidth/2),rectY+(rectHeight/2)-12);
rectY = rectY+14;//new line
ctx.fillText(info3,rectX+(rectWidth/2),rectY+(rectHeight/2)-12);
rectY = rectY+14;//new line
ctx.fillText(info2,rectX+(rectWidth/2),rectY+(rectHeight/2)-12);
rectY = rectY+14;//new line
ctx.fillText(info4,rectX+(rectWidth/2),rectY+(rectHeight/2)-12);
ctx.textAlign="left";//reset text alignment for tile coords
}
console.log("################################");
console.log("# Begin Drawing Tile " + alphabet[xLimit] + (+yLimit+1));
console.log("# Tile Unique # " + counter + ", First Pixel (top-left) : (" + xStart + ", " + yStart + ")");
console.log("# Odd or Even : " + oddOrEven);
console.log("# xLimit is : " + xLimit);
console.log("# yLimit is : " + yLimit);
console.log("# Tile Coords (x, y) (i, j) : (" + i + ", " + j +")");
console.log("# Columns : " + columns);
console.log("# Rows : " + rows);
console.log("# rowsLimit is : " + rowsLimit);
console.log("# colsLimit is : " + colsLimit);
console.log("# Output Coords (x, y) : (" + (l+1) + ", " + (k+1) + ")");
console.log("# Outputs high : " + outputsHigh);
console.log("# Outputs wide : " + outputsWide);
console.log("# Total Outputs Needed : " + outputsHigh*outputsWide);
console.log("# Top Edge : " + topEdge);
console.log("# Bottome Edge : " + bottomEdge);
console.log("# Left Edge : " + leftEdge);
console.log("# Right Edge : " + rightEdge);
console.log("# yLimit is : " + yLimit);
console.log("# Output Top Edge : " + outTopEdge);
console.log("# Output Bottom Edge : " + outBottomEdge);
console.log("# Output Left Edge : " + outLeftEdge);
console.log("# Output Right Edge : " + outRightEdge);
console.log("# Map Column is Odd? : " + columnsOdd);
console.log("# Map Row is Odd? : " + rowsOdd);
console.log("# Output Column is Odd? : " + outColumnsOdd);
console.log("# Output Row is Odd? : " + outRowsOdd);
xStart = +xStart + +width; //shift starting coords for next column
}//end columns for
xStart = +colsLimit*l * +width; //reset x coord to left most side of current output for next row
yStart = +yStart + +height; //shift starting coords for next row
}//end rows for
}//end outputs high check(k)
}//end outputs wide check(l)
}//end tilesByOutput
//jQuery
$('.pixelPerfButton').click(function(){
var $this = $(this);
$this.toggleClass('btn-danger').toggleClass('btn-primary');
$('#canvas').toggleClass('pixelPerf');
if($this.hasClass('btn-danger')){
$this.text('Pixel Perfect Preview : On');
} else {
$this.text('Pixel Perfect Preview : Off');
}
});
$('ul#tilePresets li').click(function(){
var $this = $(this);
var preWidth= $this.text().substr(0, $this.text().indexOf('x'));
var preHeight= $this.text().substr($this.text().indexOf("x") + 1);
$('#width').val(preWidth);
$('#height').val(preHeight);
});
$('ul#outputPresets li').click(function(){
var $this = $(this);
var preResWidth= $this.text().substr(0, $this.text().indexOf('x'));
var preResHeight= $this.text().substr($this.text().indexOf("x") + 1);
$('#resWidthLimit').val(preResWidth);
$('#resHeightLimit').val(preResHeight);
});
//col slider
$('#colSlide').slider({
tooltip: 'show',
min: 1,
max: 120,
value: $('#columns').val()
});
var originalVal;
$('#colSlide').slider().on('slideStart', function(ev){
originalVal = $('#colSlide').data('slider').getValue();
});
$('#colSlide').slider().on('slideStop', function(ev){
var newVal = $('#colSlide').data('slider').getValue();
if(originalVal != newVal) {
$('#columns').val($(this).val());
}
columns=$('#columns').val(); //.value converts input field int to string***
outputsWide = Math.ceil(columns/colsLimit);
draw();
});
//row slider
$('#rowSlide').slider({
tooltip: 'show',
min: 1,
max: 60,
value: $('#rows').val()
});
var originalVal2;
$('#rowSlide').slider().on('slideStart', function(ev){
originalVal2 = $('#rowSlide').data('slider').getValue();
});
$('#rowSlide').slider().on('slideStop', function(ev){
var newVal = $('#rowSlide').data('slider').getValue();
if(originalVal2 != newVal) {
$('#rows').val($(this).val());
}
rows=$('#rows').val(); //.value converts input field int to string***
outputsHigh = Math.ceil(rows/rowsLimit);
draw();
});
});//main function
JS Fiddle link : http://jsfiddle.net/ganLf56k/