Store multiple data in javascript - javascript

I am trying to figure out a way on how to store data in some kind of list or array in javascript. I have three variables called id, left and top. All are in the function
id: index of an element that is passed to the function as parameter.
left: calculated within the function
top: calculated within the function
What I am looking for is each time I call the function with different id, the function should be able to calculate and store left and top and in some way store id,left and top so that I can access them in another function call.
Or can I use objects to use the values?
function:
function getCoordinates(id) {
scroll_value_Y = document.getElementById("svg_editor").scrollTop;
scroll_value_X = document.getElementById("svg_editor").scrollLeft;
offset_x = 298;
offset_y = 102;
var p = $('#' + id);
var offset = p.offset();
var left = Math.round(offset.left - offset_x + scroll_value_X);
var top = offset.top - offset_y + scroll_value_Y;
//something to store
}
use in another function call :
drawAggregate(getCoordinates(a1).left, getCoordinates(a1).top, getCoordinates(a2).left, getCoordinates(a2).top);
Or something like that. How can I implement this?

Yeah, just return an Object.
function getCoordinates(id) {
scroll_value_Y = document.getElementById("svg_editor").scrollTop;
scroll_value_X = document.getElementById("svg_editor").scrollLeft;
offset_x = 298;
offset_y = 102;
var p = $('#' + id);
var offset = p.offset();
var left = Math.round(offset.left - offset_x + scroll_value_X);
var top = offset.top - offset_y + scroll_value_Y;
// Here we create and return an object with two keys: left and top
return {
top: top,
left: left
}
}
And, in order to avoid computing the values twice, you could store the values in other objects a1Coords and a2Coords:
var a1Coords = getCoordinates(a1);
var a2Coords = getCoordinates(a2);
drawAggregate(a1Coords.left, a1Coords.top, a2Coords.left, a2Coords.top);
I assume that your coordinates change every time, so you don't actually want to store coordinates inside the getCoordinates function but only compute and return them.

Shure you can use objects.
You can just pass object into function, like this:
(function(){
function incId(data){
var id = data.id;
data.id = id++;
}
function checkId(data){
console.log(data.id);
}
var data = {id:0};
incId(data);
checkId(data);
}());

You can return an object:
function getCoordinates(id)
{
var scroll_value_Y = document.getElementById("svg_editor").scrollTop;
var scroll_value_X = document.getElementById("svg_editor").scrollLeft;
var offset_x = 298;
var offset_y = 102;
var p = $('#' + id);
var offset = p.offset();
return {
left: Math.round(offset.left - offset_x + scroll_value_X),
top : offset.top - offset_y + scroll_value_Y
};
}
var coords1 = getCoordinates(a1);
var coords2 = getCoordinates(a2);
drawAggregate(coords1.left, coords1.top, coords2.left, coords2.top);

Related

error with arrays in javascript

To fully understand this note this; `when the page loads it gets the area of the image (width * height) and creates all the x,y positions for all the positions in the area.
This works fine.
When I have another area from pos x,y and with also an area (width * height) should pop the positions from the first list so it can separate the two areas.
Little bug I noticed is I get little lines that are horizontal to the selected area and they don't extend far from that. I believe the reason is instead of making a clean square inside the image every line is offseted by a pixel or two.
Here's a video of the behaviour https://youtu.be/v1b6dEmfxQw
so since there's already an all positions list this code created a clone of the array and removes the positions.
var drop_boxes = $('.drop-box');
var area_grid = [];
var image_width = $('.img-class')[0].naturalWidth;
var image_height = $('.img-class')[0].naturalHeight;
drop_boxes.each(function() {
var position = $(this).position();
var width = $(this).width();
var height = $(this).height();
var positions_clone = positions.slice(0);
//console.log(positions_clone.length);
var top_offset = parseInt((position['top'] * image_width)/img_width);
var left_offset = parseInt((position['left'] * image_height)/img_height);
position['top'] = top_offset;
position['left'] = left_offset;
var width_offset = parseInt((width * image_width)/img_width);
var height_offset = parseInt((height * image_height)/img_height);
var width_counter = 0;
var height_counter = 0;
var area = width_offset * height_offset;
console.log(position);
console.log(width_offset);
console.log(height_offset);
if (position['top'] < image_height-1 && position['left'] < image_width) {
for (counter = 0; counter < area; counter++) {
var pos = [parseInt(position['left']+width_counter), parseInt(position['top']+height_counter)];
var index = positions.findIndex(function(item) {
// return result of comparing `data` with `item`
// This simple implementation assumes that all `item`s will be Arrays.
return pos.length === item.length && item.every(function(n, i) { return n === pos[i] });
});
//console.log(pos);
if (index > -1) {
positions_clone.splice(index, 1);
}
//area_grid.push(pos);
if (width_counter == width_offset) {
width_counter = 0;
height_counter += 1;
}
if (counter%100 == 0) {
var percentage = Math.round((counter/area)*100, 2);
console.log("Percentage: "+percentage+"%" + " "+counter);
}
width_counter += 1;
}
console.log(positions_clone.length);
console.log(area_grid.length);
areas[area_counter] = {'area': area_grid, 'positions': positions_clone};
parent.find('.area').text(area_counter);
area_counter += 1;
}
any clues in fixing it will be appreciated. I've showed how it behaves after commenting out certain parts of the code in the video.
Change
var index = positions.findIndex(function(item) {
to
var index = positions_clone.findIndex(function(item) {
Because after each splice, the indices of the original positions doesn't change but you are still using those indices to splice the clone.

JavaScript mouseover/mousemove cusor postion without clicking in input text box

I'm attempting to combine a JavaScript mechanism for auto placing the users cursor inside of an input box through the mouseover and mousemove listeners.
I have an almost perfect working example here: http://codepen.io/anon/pen/doxNLm?editors=101
var current_element = document.getElementById("hover");
current_element.onmousemove = function showCoords(evt) {
var form = document.forms.form_coords;
var parent_id = this.id;
form.parentId.value = parent_id;
form.pageXCoords.value = evt.pageX;
form.pageYCoords.value = evt.pageY;
form.layerXCoords.value = evt.layerX;
form.layerYCoords.value = evt.layerY;
function getTextWidth(text, font) {
// re-use canvas object for better performance
var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
var context = canvas.getContext("2d");
context.font = font;
var metrics = context.measureText(text);
return metrics.width;
};
var element_base_browser_styles = window.getDefaultComputedStyle(current_element);
var total_text_pixal_length = getTextWidth(current_element.value, element_base_browser_styles.fontFamily + " " + element_base_browser_styles.fontSize);
var add_char_pixal_lengths = 0;
var myStringArray = current_element.value.split('');
var arrayLength = myStringArray.length;
for (var i = 0; i <= arrayLength; i++) {
var get_char_value = getTextWidth(myStringArray[i], element_base_browser_styles.fontFamily + " " + element_base_browser_styles.fontSize);
add_char_pixal_lengths = add_char_pixal_lengths + (get_char_value) + 1.311111111111; //every char value is added together.
// console.log("Total: " + x);
if ((add_char_pixal_lengths)> (evt.layerX)) {
this.setSelectionRange(i, i);
add_char_pixal_lengths = 0;
break;
}
}
}
current_element.onmouseover = function() {
this.focus()
}
The problem I'm having is like Geosynchronous orbit; the cursor shifts out of place sometimes a few pixels (left or right). My calculation probably sucks, but I'm not sure canvas is really the best way to do the measurement? Is there a better way?
mousemove listener to receive element cursor coordinates from e.pageX
font style using window.getComputedStyles(input_element)
arr.split('') from input_element.text string: x = ['a','b','c']
'for loop' the array, generate a canvas and measure each characters width
add all char widths one by one until the value is greater than e.pageX
set the 'for loop' iterate as the setSelectionRange(i, i)
Any help or suggestions on making this better would be appreciated. Thanks!

Div positioning calculation explanation required

I have attached the screenshot below to explain what i am trying to do.
The yellow highlighted line is the script which is run to get the position of the div (The red box in the picture).
I have used this code to calculate the position.
function getPosition(element) {
var xPosition = 0;
var yPosition = 0;
var left = 0;
var top = 0;
var i = 0;
while (element) {
xPosition = (element.offsetLeft);
yPosition = (element.offsetTop);
console.log("TOP Pos: "+yPosition+"Left Pos: "+xPosition);
if (i == 1) {
left = xPosition;
top = yPosition;
}
element = element.offsetParent;
i++;
}
return {
x: left,
y: top
};
}
And here i have used this method
function ReadDivPos(selector) {
var _divPos = "";
var parentDoc = window;
while (parentDoc !== parentDoc.parent) {
parentDoc = parentDoc.parent;
}
parentDoc = parentDoc.document;
var parentDiv = parentDoc.getElementsByTagName('div');
var divs = [];
for (var i = 0; i < parentDiv.length; i++) {
if (parentDiv[i].className == "content") {
var pos = getPosition(parentDiv[i]);
var x = pos["x"];
var y = pos["y"];
console.log("Values+ Top: " + y + " Left: " + x);
var w = parentDiv[i].offsetWidth;
_divPos += x + "," + w + "," + y + "," + (x + w) + ","+window.screen.availWidth+"\\n";
}
}
console.log("Values+ x: " + _divPos);
return _divPos;
}
Interestingly i am getting three values and on the second attempt i am getting the correct values. Here is the screenshot showing all the three values.
The correct value is
TOP Pos: 185Left Pos: 197
which i got it in the second attempt. Can anyone explain me why i did not get the correct values in the first attempt or is there any efficient way to get these values. I have to get the parent node because this was the only way to access the div class='content' as script is placed before the div content so i have to read the parent nodes and then i am able to access the required div.
Please Note this is the copy of my original question(Div Positioning is calculated fine but need explanation how it is working). The guy asked me to accept his answer and then he will show how it is done but he never came back to me once i accepted his answer and unfortunately i have also forgot my userid so i am able to logon to my orignal account.
If someone just explain me why this is giving me correct positions in the second attempt. I am new to frontend development if i understand this concept then it will help in my future projects. Thanks in advance

Why do my values mutate inside the arrays?

I wrote a little test program, exploring my problem, and it works the way I expect it, printing "four, five, six".
var foo = function() {
console.log("just one more test")
var destination = new Array;
data = [ "four", "five" , "six" ]
var parent = [ 0, 1, 2 ];
var something;
parent.forEach(function(element) {
something = data[element];
destination.push(something);
})
destination.forEach(function (thing) {
console.log(thing);
})
}
foo();
But in my real code, when I push things on to my 'clickable' array, all of the entries mutate into the current value of the 'clicker' variable. There are 3 entries in my 'scheme_list', and they draw correctly, but as I try to build areas to click on, at each iteration of the loop "in the loop" prints the value just pushed on to the array for every instance. That is, the instances of 'clicker' already in the loop change to the current value of clicker. I'm scratching my head trying to understand the difference between my real code and my test code. Or, more to the point, how to fix my real code.
var layout_color_schemes = function(scheme_list) {
var canvas = document.getElementById('color_picker_canvas');
var ctx = canvas.getContext('2d');
var x_upper_left = 5;
var y_upper_left = 5;
var width = 200;
var height = 30;
var clickables = new Array;
var clicker = {};
clicker.rect = {};
clicker.rect.width = width;
clicker.rect.height = height;
scheme_list.forEach(function(row) {
var grad = ctx.createLinearGradient(0, 0, 100, 0);
var cscheme = jQuery.parseJSON(row.json);
cscheme.forEach(function(color_point) {
grad.addColorStop(color_point[0], 'rgb(' + color_point[1] + ','
+ color_point[2] + ',' + color_point[3] + ')');
})
ctx.fillStyle = grad;
ctx.fillRect(x_upper_left, y_upper_left, width, height);
clicker.rect.x = x_upper_left;
clicker.rect.y = y_upper_left;
clicker.scheme = cscheme;
clicker.name = row.name;
clickables.push(clicker);
printf("clickables size = %d", clickables.length)
for (index = 0; index < clickables.length; ++index) {
printf("Index is %d", index)
printf("in the loop %j", clickables[index])
}
ctx.fillStyle = 'black'
ctx.fillText(row.name, x_upper_left + width + 10, 5 + y_upper_left
+ (height / 2));
y_upper_left = y_upper_left + height + 10;
});
clickables.forEach(function(area) {
printf("before call clickable area = %j", area)
});
wire_clickables(clickables);
};
function wire_clickables(clickables) {
clickables.forEach(function(area) {
if (area.hasOwnProperty('rect')) {
printf("wiring a clickable %j", area);
$("#color_picker_canvas").mousemove(function(e) {
var inside = false;
var offsetX = e.pageX - $(this).position().left;
var offsetY = e.pageY - $(this).position().top;
if (area && contains(area.rect, offsetX, offsetY)) {
document.body.style.cursor = 'pointer'
}
else {
document.body.style.cursor = 'default'
}
})
}
})
}
function contains(rect, x, y) {
return (x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y
+ rect.height)
}
The clicker object exists outside of the loop, so all you are doing is pushing the same reference onto clickables. Instead, you want to push a copy of it. There are many ways to do this, but in your case this may be one of the simplest ways:
Replace
clickables.push(clicker);
with
clickables.push(JSON.parse(JSON.stringify(clicker));
Alternatively, move the clicker declaration and initialization inside the loop.

Use variables in other function jquery

function Main(BombPosTopr, BompPosLeftr){
if (CheckRight == false){
//$("#Main").prepend('<div class="Effect" style="absolute; top:' + BombPosTopr + 'px; left: '+ BombPosLeftr +'px;"></div>');
ArrayEffects.push(new EffectVoorBom(BombPosTopr,BombPosLeftr));
BombPosLeftr += 30;
}
};
this.explosionTime2 = setTimeout( function(){
**self2.removeEffect();**
}
}
function EffectBom(BombPosTopr, BompPosLeftr){
var self2 = this;
this.el = $('<div/>');
this.el.addClass('Effect');
this.el.css({position : 'absolute', top : BombPosTopr + 'px', left : BompPosLeftr+'px'});
$("#Main").prepend(this.el);
self2.removeEffect = function(){
**self2.el.remove();**
}
I have 2 functions and in my main I need to add Effects, so I put them in an array and use the object EffectBom.
Now the big problem is that I need to use self2.removeEffect() in my other function but it can't find it!
Thnx for reading - helping!
You need to change the scope of the variable. Add
var self2;
to the top of the file and change
var self2 = this;
to be
self2 = this;

Categories

Resources