Passing invalid value to data variable - javascript

Sorry for my bad english,
Hi, I'm beginer in Vue and I have iussue, which can't to solve.
I load data about art from API (just a list of dicts), and then I making multi array (list of lists), when I save raw response.data, and my multi array in data variable of vue instanse I'm getting the similar data, but i don't change sourse list:
In raw variable fields offsetX and offsetY must must not exist. And field height is broken too.
That fields also passing in raw variable, and I don't know why.
Code of my app:
$(document).ready(function () {
var app = new Vue({
el: '#app',
data: {
raw: null,
info: null,
art_width: 252,
window_width: null,
window_height: null,
},
mounted() {
this.window_width = window.innerWidth
this.window_height = window.innerHeight
axios({
method: 'get',
url: '/content/art',
contentType: 'application/json'
})
.then(function (response) {
app.raw = response.data.items.slice();
// If i delete create_array from app, raw variable is normal
app.info = create_array(app.raw)
});
window.addEventListener('resize', () => {
if (app.raw !== null){
app.info = create_array(app.raw)
this.window_width = window.innerWidth
this.window_height = window.innerHeight
}
});
},
computed: {
arts_in_line () {
return parseInt((this.window_width - 24*2) / (this.art_width+10));
},
center_div_width () {
return this.arts_in_line * (this.art_width + 10)
}
}
})
});
function create_array(info) {
// Gets number of arts in line
arts_in_line = parseInt((window.innerWidth - 24*2) / (252+10));
// For return
var multi_array = [];
// Create mulri array
for (var index = 0; index < info.length; index = index + arts_in_line) {
multi_array.push(info.slice(index, index+arts_in_line));
}
// Save vertical offsets
var top_offset = []
for (var row = 0; row < multi_array.length; row ++) {
for (var col = 0; col < multi_array[row].length; col ++) {
// scale of art
let scale = 252 / multi_array[row][col]['width'];
// Calculation new height and offsetX/Y values
if (row == 0) {
top_offset[col] = parseInt(multi_array[row][col]['height'] * scale) + 10;
multi_array[row][col]['offsetY'] = 0;
multi_array[row][col]['offsetX'] = (252+10) * col + 'px';
multi_array[row][col]['height'] = multi_array[row][col]['height'] * scale + 'px';
multi_array[row][col]['width'] = 252 + 'px';
}
else {
multi_array[row][col]['offsetY'] = top_offset[col] + 'px';
top_offset[col] = top_offset[col] + parseInt(multi_array[row][col]['height'] * scale) + 10;
multi_array[row][col]['offsetX'] = (252+10) * col + 'px';
multi_array[row][col]['height'] = multi_array[row][col]['height'] * scale + 'px';
multi_array[row][col]['width'] = 252 + 'px';
}
}
}
return multi_array;
}

Instead of doing
// Create mulri array
for (var index = 0; index < info.length; index = index + arts_in_line) {
multi_array.push(info.slice(index, index+arts_in_line));
}
you can simply just create a new array multi_array and loop through info adding what you want to multi_array.
For example
var multi_array = [];
// Save vertical offsets
var top_offset = []
for (var row = 0; row < info.length; row ++) {
for (var col = 0; col < info[row].length; col ++) {
let scale = 252 / parseInt(info[row][col]['width']);
const temp = {
id: info[row][col]['id'],
// Additional values you want
height: (parseInt(multi_array[row][col]['height']) * scale) + 'px'
}
multi_array[row][col] = temp
}
}
return multi_array;
This way you can add and exclude any key you want in your new array.

Related

Paint by number Illustrator script

I am from supercoloring and we decided to convert our vector illustrations in color to color by number worksheets. Our input files are color and outline images in svg format.
Outline version (like a coloring page) + Color version
outline version and
color version
What we want to get is the following
result
We would like that a color palette is generated under the outline version of the image based on the color data from the color version of the image. Moreover, numbers corresponding to this palette are placed inside each color space of the outlined version.
I understand that no script in the world would do this properly, but at least I am striving to reduce the time spent by the editor (person) to put these numbers manually in the Illustrator. I understand that our color vector images may have too many colors and shades so we need somehow to limit the result colors of the palette ( to fuse them into large groups of basic colors).
I searched all over the stackoverflow solutions and found some ingenious like Paint with numbers with Adobe Illustrator Javascript and
I'm looking to create an automated numbering system for custom paint by number kits in photoshop (Kudos to Yuri Khristich). However, they are not exactly adapted to our needs.
Most of scripts on the web generate outlined images from color version, but the quality is compromised. We have already a proper outline version that we want to use as a base for color by number worksheet.
Here is the script to make a 'color palette' for selected artwork.
And here, as you know, is the script to add color names to all filled areas.
So I took the two script, made a couple of minimal tweaks and get almost the result you want. All you need after the scripts is to copy the layer with numbers and 'palette' from a colored artwork to a outline version.
Script #1
// Modified version
// https://stackoverflow.com/questions/75344674/paint-by-number-illustrator-script
// Original:
// https://productivista.com/make-a-list-of-colors-from-your-selection/
/*
Date: July, 2020
Author: Katja Bjerrum, email: katja#productivista.com, www.productivista.com
============================================================================
NOTICE:
This script is provided "as is" without warranty of any kind.
Free to use, not for sale.
============================================================================
Released under the MIT license.
http://opensource.org/licenses/mit-license.php
============================================================================
*/
//#target illustrator
var doc = app.activeDocument;
var myLayer = doc.activeLayer;
app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;
var swGrps = doc.swatchGroups;
var mainSwGr = doc.swatchGroups[0];
var sel = doc.selection;
var actionSet = 'CreateSwatchGroup';
var actionName = 'ColourGroup';
var actionPath = Folder.myDocuments + '/Adobe Scripts/';
if (!Folder(actionPath).exists) Folder(actionPath).create();
//app.doScript("Colorgroup", "ToSwatchScript"); // Action, that creates swatch group
var actionDoc =
[ '/version 3',
'/name [' + actionSet.length + ' ' + ascii2Hex(actionSet) + ']',
'/isOpen 1',
'/actionCount 1',
'/action-1 {',
'/name [' + actionName.length + ' ' + ascii2Hex(actionName) + ']',
' /keyIndex 0',
' /colorIndex 0',
' /isOpen 1',
' /eventCount 1',
' /event-1 {',
' /useRulersIn1stQuadrant 0',
' /internalName (ai_plugin_swatches)',
' /localizedName [ 8',
' 5377617463686573',
' ]',
' /isOpen 0',
' /isOn 1',
' /hasDialog 1',
' /showDialog 1',
' /parameterCount 1',
' /parameter-1 {',
' /key 1835363957',
' /showInPalette 4294967295',
' /type (enumerated)',
' /name [ 15',
' 4e657720436f6c6f722047726f7570',
' ]',
' /value 17',
' }',
' }',
'}'].join('');
createAction(actionDoc, actionName, actionPath);
app.redraw();
app.doScript (actionName, actionSet);
app.redraw();
app.unloadAction(actionSet, '');
var convMM = 2.8346456692; // initialization of the variable to convert points to mm
var colorgroup = doc.swatchGroups[doc.swatchGroups.length - 1]; // Choose the last swatch group
var stY = -200; //
var stX = 20;
var recW = 25;
var recH = 25;
var offX = recW / 5;
var offY = recH / 4;
var textoffY = recH / 4;
var rows = 4;
var cols = 4;
var black = new GrayColor();
black.gray = 80;
var white = new GrayColor() ;
white.gray = 0;
var noStroke = doc.swatches[0].color;
if (swGrps.length <=1){
alert ("Please create swatch group from your selection");
}
else if (sel <= 0){
//docRef.placedItems[0].selected == false;
alert ("Please make a selection");
delSwatchGr(colorgroup); //delete swatch group
}
else{
swatchGroupList(colorgroup, stY, stX);//create corlor list
// delSwatchGr(colorgroup);//delete swatch group
}
//Function, that creates color list
function swatchGroupList(swatchGroup, stY, stX) {
// Groups everything in the list
var mainGroup = myLayer.groupItems.add();
mainGroup.name = "Colors";
mainGroup.moveToBeginning(myLayer);
//Name of the color list
var nameText = myLayer.textFrames.add();
nameText.contents = swatchGroup.name; // the name of the swatch group
nameText.position = [stX, stY + recH];
var nameStyle = nameText.textRange.characterAttributes;
nameStyle.size = 12;//size in punkt
//nameStyle.textFont = textFonts.getByName("Avenir-Book");//the font
nameStyle.capitalization = FontCapsOption.ALLCAPS;//ALL CAPITALS
var swatches = swatchGroup.getAllSwatches();
var swatchArray = [];
for (i = swatches.length-1; i>=0; i--) {
var mySwatch = swatches[i];
mySwatch.name = i + 1;
var subGroup = createSwatchGroup(mySwatch, textoffY);
swatchArray.push(subGroup);
}
nameText.moveToEnd(mainGroup);
var myGroup = swatchArray;
var maxW = maxWidth(myGroup);
for (var j = 0; j < myGroup.length; j++) {
var mySubGroup = myGroup[j];
mySubGroup.moveToBeginning(mainGroup);
}
for (var i = 0; i < mainGroup.groupItems.length; i++) {
var mySubGroup = mainGroup.groupItems[i];
if (mainGroup.groupItems.length > 7) {
rows = 7;
var c = i%rows;
var r = Math.floor(i/rows);
mySubGroup.position = [stX + r * (maxW + 10), stY - c * (recH + offY)];
}
else {
rows = 7;
var c = i % rows;
var r = Math.floor(i / rows);
mySubGroup.position = [stX, stY - c * (recH + offY)];
}
}
// textSwatch.moveToBeginning(SubGroup);
// path_ref.moveToBeginning(SubGroup);
// SubGroup.position = [stX + c * 140, stY - r * (path_ref.height + offY)];
subGroup.moveToBeginning(mainGroup);
}
function lightColor(c){
if(c.typename)
{
switch(c.typename)
{
case "CMYKColor":
return (c.black>=10 || c.cyan>10 || c.magenta>10 || c.yellow > 10) ? true : false;
case "RGBColor":
return (c.red<230 || c.green<230 || c.blue<230) ? true : false;
case "GrayColor":
return c.gray >= 10 ? true : false;
case "SpotColor":
return lightColor(c.spot.color);
//return false;
}
}
}
function fitItem(item, itemW, itemH, diff) {
var oldWidth = item.width
var oldHeight = item.height
if (item.width > item.height) {
// landscape, scale height using ratio from width
item.width = itemW - diff.deltaX
var ratioW = item.width / oldWidth
item.height = oldHeight * ratioW
} else {
// portrait, scale width using ratio from height
item.height = itemH - diff.deltaY
var ratioH = item.height / oldHeight
item.width = oldWidth * ratioH
}
}
function itemBoundsDiff(item) {
var itemVB = item.visibleBounds
var itemVW = itemVB[2] - itemVB[0] // right - left
var itemVH = itemVB[1] - itemVB[3] // top - bottom
var itemGB = item.geometricBounds
var itemGW = itemGB[2] - itemGB[0] // right - left
var itemGH = itemGB[1] - itemGB[3] // top - bottom
var deltaX = itemVW - itemGW
var deltaY = itemVH - itemGH
var diff = { deltaX: deltaX, deltaY: deltaY }
return diff
}
function delSwatchGr(swGr){
var swGrSws = swGr.getAllSwatches();
for (var j = 0; j < swGrSws.length; j++){
var sw = swGrSws[j];
sw.color = new CMYKColor();
}
swGr.remove();
}
//Function finds the max group width
function maxWidth(myGroup) {
var maxFound = 0;
for (var j = 0; j < myGroup.length; j++) {
var GrWidth = myGroup[j].width;
//var Widthmax = GrWidth.width;
maxFound = Math.max(maxFound, GrWidth);
}
return maxFound;
}
function createSwatchGroup(sw, myOffset) {
//Is "MyForm" path exists?
try{
var path_ref_ori = app.activeDocument.pathItems.getByName("MyForm" || "myform" || "MYFORM");
}
catch(e) {
var path_ref_ori = false;
}
if (path_ref_ori) {
myPath = path_ref_ori.duplicate();
var boundsDiff = itemBoundsDiff(myPath);
fitItem(myPath, recW, recH, boundsDiff);
myPath.name = "NewForm";
myPath.position = [0, 0];
}
else {
var myPath = createMyPath()
}
myPath.fillColor = sw.color;
myPath.stroked = true;
myPath.strokeWidth = 0.3;
myPath.strokeColor = lightColor(myPath.fillColor) ? noStroke : black;
var textSwatch = myLayer.textFrames.add(); //swatch text
textSwatch.contents = sw.name;
textSwatch.position = [myPath.width + 1.3 * convMM, -myOffset];
var textSwStyle = textSwatch.textRange.characterAttributes;
textSwStyle.size = 10; //size in punkt
//textSwStyle.textFont = textFonts.getByName("MyriadPro-Semibold"); //the font
var SubGroup = myLayer.groupItems.add(); //groups path and text
SubGroup.name = sw.name;
SubGroup.position = [0, 0];
textSwatch.moveToBeginning(SubGroup);
myPath.moveToBeginning(SubGroup);
return SubGroup;
}
function createMyPath(){
//Is "MyForm" path exists?
try{
var path_ref_ori = app.activeDocument.pathItems.getByName("MyForm" || "myform" || "MYFORM");
}
catch(e) {
var path_ref_ori = false;
}
if (path_ref_ori) {
path_ref = path_ref_ori.duplicate();
var boundsDiff = itemBoundsDiff(path_ref);
fitItem(path_ref, recW, recH, boundsDiff);
path_ref.name = "NewForm";
path_ref.position = [0, 0];
}
else {
var path_ref = myLayer.pathItems.rectangle(0, 0, recW, recH); //swatch path item
}
return path_ref
};
function createAction(str, set, path) {
var f = new File('' + path + '/' + set + '.aia');
f.open('w');
f.write(str);
f.close();
app.loadAction(f);
f.remove();
};
function ascii2Hex(hex) {
return hex.replace(/./g, function (a) { return a.charCodeAt(0).toString(16) });
};
Input (after select the artwork and run the script):
Result (added the global swatches and the 'color palette' at the bottom):
Script #2
// Based on:
// https://stackoverflow.com/questions/73705368/paint-with-numbers-with-adobe-illustrator-javascript
var doc = app.activeDocument,
lays = doc.layers,
WORK_LAY = lays.add(),
NUM_LAY = lays.add(),
i = lays.length - 1,
lay;
// main working loop
for (; i > 1; i--) {
//process each layer
lay = lays[i];
lay.name = lay.name + " Num:" + (i - 1); // i-1 as 2 layers beed added.
process(lay.pathItems, false);
process(lay.compoundPathItems, true); // if any
}
//clean up
NUM_LAY.name = "Numbers";
WORK_LAY.remove();
function process(items, isCompound) {
var j = 0,
b, xy, s, p, op;
for (; j < items.length; j++) {
// process each pathItem
op = items[j];
try { color = op.fillColor.spot.name } catch(e) { continue } // <-- HERE
// add stroke
if (isCompound) {
// strokeComPath(op);
} else {
// !op.closed && op.closed = true;
// op.filled = false;
// op.stroked = true;
};
b = getCenterBounds(op);
xy = [b[0] + (b[2] - b[0]) / 2, b[1] + (b[3] - b[1]) / 2];
s = (
Math.min(op.height, op.width) < 20 ||
(op.area && Math.abs(op.area) < 150)
) ? 20 : 40; // adjust font size for small area paths.
add_nums(color, xy, s); // <--- HERE
}
}
function getMinVisibleSize(b) {
var s = Math.min(b[2] - b[0], b[1] - b[3]);
return Math.abs(s);
}
function getGeometricCenter(p) {
var b = p.geometricBounds;
return [(b[0] + b[2]) / 2, (b[1] + b[3]) / 2];
}
// returns square of distance between p1 and p2
function getDist2(p1, p2) {
return Math.pow(p1[0] + p2[0], 2) + Math.pow(p1[1] + p2[1], 2);
}
// returns visibleBounds of a path in a compoundPath p
// which is closest to center of the original path op
function findBestBounds(op, p) {
var opc = getGeometricCenter(op);
var idx = 0,
d;
var minD = getDist2(opc, getGeometricCenter(p.pathItems[0]));
for (var i = 0, iEnd = p.pathItems.length; i < iEnd; i++) {
d = getDist2(opc, getGeometricCenter(p.pathItems[i]));
if (d < minD) {
minD = d;
idx = i;
}
}
return p.pathItems[idx].visibleBounds;
}
function applyOffset(op, checkBounds) {
var p = op.duplicate(WORK_LAY, ElementPlacement.PLACEATBEGINNING),
// offset value the small the better, but meantime more slow.
offset = function() {
var minsize = Math.min(p.width, p.height);
if (minsize >= 50) {
return '-1'
} else if (20 < minsize && minsize < 50) {
return '-0.5'
} else {
return '-0.2' // 0.2 * 2 (both side ) * 50 (Times) = 20
}
},
xmlstring = '<LiveEffect name="Adobe Offset Path"><Dict data="I jntp 2 R mlim 4 R ofst #offset"/></LiveEffect>'
.replace('#offset', offset()),
TIMES = 100; // if shapes are too large, should increase the value.
if (checkBounds) {
// check its size only if it needs, because it's too slow
while (TIMES-- && getMinVisibleSize(p.visibleBounds) > 3) p.applyEffect(xmlstring);
} else {
while (TIMES--) p.applyEffect(xmlstring);
}
return p;
}
function getCenterBounds(op) {
var originalMinSize = getMinVisibleSize(op.visibleBounds);
var p = applyOffset(op, false);
if (getMinVisibleSize(p.visibleBounds) > originalMinSize) {
// in some cases, path p becomes larger for some unknown reason
p.remove();
p = applyOffset(op, true);
}
var b = p.visibleBounds;
if (getMinVisibleSize(b) > 10) {
activeDocument.selection = [p];
executeMenuCommand("expandStyle");
p = activeDocument.selection[0];
if (p.typename == "CompoundPathItem") {
b = findBestBounds(op, p);
}
}
p.remove();
return b;
}
function add_nums(n, xy, s) {
var txt = NUM_LAY.textFrames.add();
txt.contents = n;
txt.textRange.justification = Justification.CENTER;
txt.textRange.characterAttributes.size = s;
txt.position = [xy[0] - txt.width / 2, xy[1] + txt.height / 2];
}
function strokeComPath(compoundPath) {
var p = compoundPath.pathItems,
l = p.length,
i = 0;
for (; i < l; i++) {
// !p[i].closed && p[i].closed = true;
// p[i].stroked = true;
// p[i].filled = false;
}
};
Result (added the layer with numbers after run the script):
Final outlined version with numbers and the 'color palette'
Note: you have to ungroup and unmask the color artwork before you run the Script #2.
Here is the results for the rest examples:
As you can see the 'final' artwork still need a quite amount of additional manual work: to move or remove extra numbers.
And it makes sense to reduce the number of colors in original color artworks (perhaps it's possible to do with a script to some extent, as well).

Nested for loop incrementation producing inconsistent result

I'm trying to use the variable of the current iteration of the loop in the nested loop.
However when I execute the following code the loop incorrectly starts at f = 6, and then it correctly iterates over the nested loop.
I've removed all the other code and then it works normally. However I have no clue what could possibly be interfering with the loop. There probably is a reason for it and I wish you guys could help me figure this out - and probably learn something more about why this behaviour occurs the way it does.
for (var f = 0; f < 6; f++) {
var JSONURL = "http://blabla.com/json";
$.ajax( JSONURL, {
dataType: "json"
})
.done(function(json) {
for (var i = 0; i < json.timeslots.length; i++) {
var StartHour = json.timeslots[i].begintijd.split(":")[0];
var StartMinute = json.timeslots[i].begintijd.split(":")[1];
var EndHour = json.timeslots[i].eindtijd.split(":")[0];
var EndMinute = json.timeslots[i].eindtijd.split(":")[1];
//Calculate top distance of block in pixels
if (StartHour < 20) {
var TopDistance = ((parseInt(StartHour) - 9) * 240) + (parseInt(StartMinute) * 4);
}
//Calculate height of block in pixels
var BlockHeight = ((((parseInt(EndHour) * 60) + (parseInt(EndMinute))) - ((parseInt(StartHour) * 60) + (parseInt(StartMinute)))) * 4) - 2.5;
//Generate HTML for blocks
var html_first = '<div data-ix="show-pop-up" class="w-clearfix time-block event-block" style="height:'+BlockHeight+'px; top:'+TopDistance+'px; background-color:'+json.timeslots[i].achtergrondkleur+';">';
if (json.timeslots[i].afbeelding.length > 0) {
var html_mid = '<div class="avatar" style="background-image:url('+json.timeslots[i].afbeelding+');"></div>';
}
else {
html_mid = "";
}
var html_last = '<h4 class="card-title">'+json.timeslots[i].naam+'</h4><div class="time-indication">'+json.timeslots[i].begintijd+'</div><div class="speaker-description">'+json.timeslots[i].functie+'</div><div class="hidden-content"><div class="pop-up-wrapper" style="background-color:'+json.timeslots[i].achtergrondkleur+';"><div class="w-clearfix pop-up-header-background"><div data-ix="hide-pop-up" class="close-icon" id="PopupClose"></div><h3 class="white pop-up-title">'+json.timeslots[i].naam+'</h3><div class="pop-up-subtitle">'+json.timeslots[i].functie+'</div></div><div class="w-clearfix pop-up-body"><div class="pop-up-avatar" style="background-image:url('+json.timeslots[i].afbeelding+');"></div><div class="w-clearfix"><div class="pop-up-card-detail-wrap"><div class="time-label">Begint om</div><div class="pop-up-time-text">'+json.timeslots[i].begintijd+'</div></div><div class="pop-up-card-detail-wrap"><div class="time-label">Eindigt om</div><div class="pop-up-time-text">'+json.timeslots[i].eindtijd+'</div></div><div class="pop-up-card-detail-wrap"><div class="time-label">plek</div><div class="pop-up-time-text">Zaal 1</div></div></div><p class="pop-up-paragraph">'+json.timeslots[i].beschrijving_lang+'</p></div><div class="pop-up-footer">Meer over deze spreker</div></div></div></div>';
var html = html_first+html_mid+html_last;
var TargetDiv = "#Locatie"+f+"Column";
alert("Parent loop increment: "+f);
alert("Child loop increment: "+i);
$(TargetDiv).append(html);
}
});
}
It starts at f = 6 because your callback doesn't get called until after f equals 6
What you may do is something to the effect of:
for (var f = 0; f < 6; f++) {
var JSONURL = "http://blabla.com/json";
$.ajax( JSONURL, {
dataType: "json"
})
.done(handleResponse.bind(null, f));
}
function handleResponse(f, json) {
for (var i = 0; i < json.timeslots.length; i++) {
var StartHour = json.timeslots[i].begintijd.split(":")[0];
var StartMinute = json.timeslots[i].begintijd.split(":")[1];
var EndHour = json.timeslots[i].eindtijd.split(":")[0];
var EndMinute = json.timeslots[i].eindtijd.split(":")[1];
//Calculate top distance of block in pixels
if (StartHour < 20) {
var TopDistance = ((parseInt(StartHour) - 9) * 240) + (parseInt(StartMinute) * 4);
}
//Calculate height of block in pixels
var BlockHeight = ((((parseInt(EndHour) * 60) + (parseInt(EndMinute))) - ((parseInt(StartHour) * 60) + (parseInt(StartMinute)))) * 4) - 2.5;
//Generate HTML for blocks
var html_first = '<div data-ix="show-pop-up" class="w-clearfix time-block event-block" style="height:'+BlockHeight+'px; top:'+TopDistance+'px; background-color:'+json.timeslots[i].achtergrondkleur+';">';
if (json.timeslots[i].afbeelding.length > 0) {
var html_mid = '<div class="avatar" style="background-image:url('+json.timeslots[i].afbeelding+');"></div>';
}
else {
html_mid = "";
}
var html_last = '<h4 class="card-title">'+json.timeslots[i].naam+'</h4><div class="time-indication">'+json.timeslots[i].begintijd+'</div><div class="speaker-description">'+json.timeslots[i].functie+'</div><div class="hidden-content"><div class="pop-up-wrapper" style="background-color:'+json.timeslots[i].achtergrondkleur+';"><div class="w-clearfix pop-up-header-background"><div data-ix="hide-pop-up" class="close-icon" id="PopupClose"></div><h3 class="white pop-up-title">'+json.timeslots[i].naam+'</h3><div class="pop-up-subtitle">'+json.timeslots[i].functie+'</div></div><div class="w-clearfix pop-up-body"><div class="pop-up-avatar" style="background-image:url('+json.timeslots[i].afbeelding+');"></div><div class="w-clearfix"><div class="pop-up-card-detail-wrap"><div class="time-label">Begint om</div><div class="pop-up-time-text">'+json.timeslots[i].begintijd+'</div></div><div class="pop-up-card-detail-wrap"><div class="time-label">Eindigt om</div><div class="pop-up-time-text">'+json.timeslots[i].eindtijd+'</div></div><div class="pop-up-card-detail-wrap"><div class="time-label">plek</div><div class="pop-up-time-text">Zaal 1</div></div></div><p class="pop-up-paragraph">'+json.timeslots[i].beschrijving_lang+'</p></div><div class="pop-up-footer">Meer over deze spreker</div></div></div></div>';
var html = html_first+html_mid+html_last;
var TargetDiv = "#Locatie"+f+"Column";
alert("Parent loop increment: "+f);
alert("Child loop increment: "+i);
$(TargetDiv).append(html);
}
}
What this does is call handleResponse by passing in the value of f at the time that the loop is run.
The problem is not the nested loop, but the asynchronous call inside the loop. To resolve this issue you can use an immediately-invoked-anonymous-function to pass the correct value to your function, like so :
for (var f = 0; f < 6; f++) {
(function(foo) {
//ajax call
//your ajax call will now have the correct number
})(f);
}

Using jspdf.debug.js Wrap table head in pdf when

I am using jspdf.debug.js for generation html table in pdf format.
The table heading is not wrapping properly, shown like this:
image of the distorted heading jspdf.debug.js
below is the code that prints out the thead. though it doesn't wrap long text in next line
jsPDFAPI.printHeaderRow = function (lineNumber, new_page) {
if (!this.tableHeaderRow) {
throw 'Property tableHeaderRow does not exist.';
}
var tableHeaderCell,
tmpArray,
i,
ln;
this.printingHeaderRow = true;
if (headerFunction !== undefined) {
var position = headerFunction(this, pages);
setLastCellPosition(position[0], position[1], position[2], position[3], -1);
}
this.setFontStyle('bold');
var tempHeaderConf = [];
for (i = 0, ln = this.tableHeaderRow.length; i < ln; i += 1) {
this.setFillColor(248,218,194);
//this.maxWidth(10);
//this.setWidth(10);
// console.log("width"+this.width);
/*changed neeraj color of table heading*/
//this.setFillColor(200,200,200);
tableHeaderCell = this.tableHeaderRow[i];
if (new_page) {
tableHeaderCell[1] = this.margins && this.margins.top || 0;
tempHeaderConf.push(tableHeaderCell);
}
tmpArray = [].concat(tableHeaderCell);
this.cell.apply(this, tmpArray.concat(lineNumber));
}
if (tempHeaderConf.length > 0){
this.setTableHeaderRow(tempHeaderConf);
}
this.setFontStyle('normal');
this.printingHeaderRow = false;
};
})(jsPDF.API);
code for the same if fiddle
https://jsfiddle.net/neerajsonar/afas07Lf/
I am using jsPDF version 1.0.272
In jsPDFAPI.table = function (x,y, data, headers, config) (Around line 2833)
after if (printHeaders) {
clause, I added true as the last parameter to the call to calculateLineHeight():
var lineHeight = this.calculateLineHeight(headerNames, columnWidths, headerPrompts.length?headerPrompts:headerNames,true);
Next, in the for loop, I removed the String() from the last parameter:
tableHeaderConfigs.push([x, y, columnWidths[header], lineHeight, (headerPrompts.length ? headerPrompts[i] : header)]);
In the for loop after the //Construct the data rows comment, I added false as the last parameter to calculateLineHeight():
lineHeight = this.calculateLineHeight(headerNames, columnWidths, model,false);
I added another parameter, isHeader, to the calculateLineHeight function:
jsPDFAPI.calculateLineHeight = function (headerNames, columnWidths, model, isHeader)
Then I modified the function:
jsPDFAPI.calculateLineHeight = function (headerNames, columnWidths, model, isHeader) {
var header, lineHeight = 0;
for (var j = 0; j < headerNames.length; j++) {
header = headerNames[j];
if(isHeader){
model[j] = this.splitTextToSize(String(model[j]), columnWidths[model[j].toLowerCase().replace(/\s+/g, '')] - padding);
var h = this.internal.getLineHeight() * model[j].length + padding;
}else{
model[header] = this.splitTextToSize(String(model[header]), columnWidths[header] - padding);
var h = this.internal.getLineHeight() * model[header].length + padding;
}
if (h > lineHeight)
lineHeight = h;
}
return lineHeight;
};
And if you want to unbold the table headings, go to function
jsPDFAPI.printHeaderRow = function (lineNumber, new_page) and comment the line this.setFontStyle('bold');

Detect coherent neighbors / neighborhood in 2d array

Im having an arbitrary 2d array and each field has an id and a teamid (here illustrated as colors 1).
I want for every neighborhood an array with the ids
in it.
A neighborhood consists of fields with neighbors with the same teamid horizontally and vertically (not diagonally)
e.g.:
This is what i have:
array[0][0] = {id:1,teamId:1}
array[1][0] = {id:2,teamId:1}
array[2][0] = {id:3,teamId:0}
array[3][0] = {id:4,teamId:2}
array[4][0] = {id:5,teamId:2}
array[5][0] = {id:6,teamId:0}
array[0][1] = {id:7,teamId:1}
array[1][1] = {id:8,teamId:1}
array[2][1] = {id:9,teamId:1}
array[3][1] = {id:10,teamId:2}
array[4][1] = {id:11,teamId:2}
array[5][1] = {id:12,teamId:0}
//and so on..
This is what i want:
neighborhood[1] = [1,2,7,8,9,13,14]
neighborhood[2] = [4,5,10,11]
neighborhood[3] = [16,22,23,24,29,30]
neighborhood[4] = [25,31,32,37,38]
neighborhood[5] = [35,41]
I am not searching for the images, but for the array
neighborhood
thanks in advance!
You can use the logic from dots and block games. A block belongs to a player if he has surrounded it with the walls. So, you need for each cell also 4 walls except for the outer cells. To test if a cell is closed you can use 4 class variables:
var Block = function() {
this.isclosed=0;
this.left=0;
this.top=0;
this.right=0;
this.bottom=0;
return this;
}
Block.prototype = {
isClosed : function () {
if (this.isclosed==true) {
return false;
} else if (this.left && this.top && this.right && this.bottom) {
this.isclosed=true;
return true;
} else {
return this.left && this.top && this.right && this.bottom;
}
}
}
You can try my implementations of dots and blocks game # https://dotsgame.codeplex.com/.
The method for solving this issue is refered as Connected Component Labelling
A similar question was asked once before from which i have my solution:
// matrix dimensions
var row_count = 20;
var col_count = 20;
var numOfTeams = 2;
// the input matrix
var m = [];
// the labels, 0 means unlabeled
var label = [];
var source = document.getElementById("source");
for (var i = 0; i < row_count; i++) {
var row = source.insertRow(0);
m[i] = [];
label[i] = [];
for (var j = 0; j < col_count; j++) {
//m[i][j] = Math.round(Math.random());
m[i][j] = getRandomInt(0, numOfTeams + 1);
label[i][j] = 0;
var cell1 = row.insertCell(0);
cell1.innerHTML = m[i][j];
}
}
// direction vectors
var dx = [1, 0, -1, 0];
var dy = [0, 1, 0, -1];
function dfs(x, y, current_label, team) {
if (x < 0 || x == row_count) return; // out of bounds
if (y < 0 || y == col_count) return; // out of bounds
if (label[x][y] || team != m[x][y]) return; // already labeled or not marked with 1 in m
// mark the current cell
label[x][y] = current_label;
// recursively mark the neighbors
for (var direction = 0; direction < 4; ++direction) {
dfs(x + dx[direction], y + dy[direction], current_label, team);
}
}
function find_components() {
var component = 0;
for (var i = 0; i < row_count; ++i) {
for (var j = 0; j < col_count; ++j) {
if (!label[i][j] && m[i][j]) dfs(i, j, ++component, m[i][j]);
}
}
}
find_components();
var result = document.getElementById("result");
for (var i in label) {
var string = ""
var row = result.insertRow(0);
for (var j in label[i]) {
string += label[i][j] + " "
var cell1 = row.insertCell(0);
cell1.innerHTML = label[i][j];
}
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
table tr td {
min-width: 14px
}
<div style="float:left">
<table id="source"></table>
</div>
<div style="float:right">
<table id="result"></table>
</div>

Resizing all widgets in gridster.js

I am working on a project with Gridster.js and I have a user option that lets them choose how many columns they want. It is not finished (obviously) but I am working on a function that resizes all of the boxes when a column number is picked.
My problem is what when they are resized, the space in the grid is not optimized and I am trying to find an algorithm that will do it without overlapping the widgets (the resize: false option is apparently overridden when trying to change the position of widgets.
I am going to keep working on it, but I would love some help on this as I seem to be banging my head against the wall with this problem. Thanks in advance.
// Set column number and resize/move widgets
$(".edit-column-option").click(function() {
$("#edit-modal").foundation('reveal', 'close');
var findColumnNumber = this.innerHTML.split("");
var columnNumber = parseInt(findColumnNumber[0]);
var options = gridster.options;
var resize = options.resize;
var dimensionX = gridster.cols;
var dimensionY = gridster.rows;
console.log("Columns: " + dimensionX);
console.log("Rows: " + dimensionY);
resize.max_size = [(Math.floor(dimensionX / columnNumber)), (Math.floor(dimensionX / columnNumber))];
resize.min_size = [2, 2];
options.max_size_x = Math.floor(dimensionX / columnNumber);
options.min_size_x = 2;
options.max_size_y = options.max_size_x;
options.min_size_y = options.max_size_x;
var resize_axes = options.max_size_x;
console.log(gridster);
var arr = localStorage.getObject('cloudWidgetArray');
$(gridster.$widgets).each(function(i) {
setTimeout(function() {
var a = gridster.$widgets.eq(i).height() - gridster.$widgets.eq(i).find('.title').height();
gridster.$widgets.eq(i).find('.title').next('div').height(a.toString());
gridster.$widgets.eq(i).find('.title').next('div').css('opacity','1');
refreshThis(gridster.$widgets.eq(i).data('li'));
serialize();
}, 200);
gridster.resize_widget(gridster.$widgets.eq(i), resize_axes, resize_axes, function() {
});
console.log("Widget grid data: " + gridster.$widgets.eq(i).size_y);
});
for(var i = 1; i < arr.length; i++) {
for (var a = 1; a <= dimensionY; a++) {
for (var b = 1; a <= dimensionX; b++) {
if (gridster.can_move_to(arr[i]), a, b, a) {
if (gridster.is_occupied(a, b)) {
console.log("Can't move.");
break;
}
else {
var new_wdg = {
size_x: options.max_size_x,
size_y: options.max_size_x,
row: a,
col: arr[i].col - 1
};
gridster.mutate_widget_in_gridmap(gridster.$widgets.eq(i), arr[i], new_wdg);
i++;
a = 1;
b = 1;
console.log(arr[i]);
break;
}
}
}
}
}
});

Categories

Resources