How to left align objects in a group - javascript

I am new to fabric js. i am trying to left align all the objects in a group by using this function.
$rootScope.alignLeft = function () {
var activeObject = canvas.pages[canvas.activePageIndex].fabric.getActiveObject();
if (activeObject.type == "group") {
var items = activeObject._objects;
var left = activeObject.getLeft();
var top = activeObject.getTop();
console.log(activeObject);
canvas.pages[canvas.activePageIndex].fabric.remove(activeObject);
console.log(left);
console.log(top);
for (var i = 0; i < items.length; i++) {
canvas.pages[canvas.activePageIndex].fabric.add(items[i].set({left: activeObject.left}));
}
canvas.pages[canvas.activePageIndex].fabric.renderAll();
}
};
The problems that i am facing are
1)if i dont use .remove(activeGroup) it makes a duplicate of the objects in the group. I want to keep the activeGroup and somehow stop it from duplicating itself.
2) The items[i].set({left : activeObject.left} correctly sets the left alignment but the objects top value changes and i don't want that. i have tried to use items[i].set({left : activeObject.left,top:activeObject.top}); but failed to keep it constant.
How can i achieve this functionality?

How i was able to solve these problems. I am sure future newbie's to fabricjs like me will face these basic conceptual problems just like me.
Answers to points 1&2:
1) I used .remove(activeGroup) to remove it and made a new group and added items inside activeGroup into group.
2) Here are some links that really helped me understand the positioning system used in fabricjs stackOverflow link Github link
$rootScope.alignLeft = function(){
var activeObject = canvas.pages[canvas.activePageIndex].fabric.getActiveObject();
var group = new fabric.Group();
if(activeObject.type=="group"){
var items = activeObject._objects;
canvas.pages[canvas.activePageIndex].fabric.remove(activeObject);
for(var i = 0;i<items.length;i++){
var ObjTop = activeObject.top + items[i].top + activeObject.height/2 ;
items[i].set({left :activeObject.left,top:ObjTop});
group.addWithUpdate(activeObject.item(i));
}
canvas.pages[canvas.activePageIndex].fabric.add(group);
canvas.pages[canvas.activePageIndex].fabric.setActiveObject(group);
canvas.pages[canvas.activePageIndex].fabric.renderAll();
}
}

Related

Method push is not adding a value to a vector that previously had the same value

The goal of the code I'm going to present is to create a aux vector that will contain petri nets transitions, arcs and places. I'm dividing a petri net into several groups, each group is a transition with respective input arcs and places.
The issue is the following: After I put the info in the first position of the aux vector, I'm unable to put a place with the same id of the place of the previous group. For example, if I have a transition with place_id=1 and place_id=2, and the next transition have place_id=2 and place_id=3, the code doesn't write the value place_i=2 in the vector for the second group.
function conflict() {
var id = [];
var source = [];
var target = [];
var aux = [];
var cont = [];
var places = pnml.getElementsByTagName("place");
var arcs = pnml.getElementsByTagName("arc");
var transitions = pnml.getElementsByTagName("transition");
for (var i = 0; i < transitions.length; i++) {
target.push(transitions[i].getAttribute("id"));
aux.push([]);
for (var j = 0; j < arcs.length; j++) {
if (arcs[j].getAttribute("target") == transitions[i].getAttribute("id")) {
id.push(arcs[j].getAttribute("id"));
source.push(arcs[j].getAttribute("source"));
//console.log(arcs[j].getAttribute( "source" ));
}
}
//console.log(id);
//console.log(arcs);
//console.log(places);
aux[i].push(id, source, target);
//id.length=0;
target = [];
source = [];
id = [];
}
}
Image of the platform with console open
Thanks in advance
Without knowing a whole lot for the issue, try to change this
aux.push([]);
to this
aux[i]=[];
So that you initialize and fill using an index instead of a push and an index later, for consistency.
Let me know if it helps
EDIT:
Also this
aux[i].push(id, source, target);
to this (maybe? )
aux[i].push({ id: id, source:source, target:target});
You probably want to keep objects in aux, so you need to push an object, not 3 parameters like that

Add marking to JSViz Visualization in Spotfire

I am stuck on an issue where I need to add marking to D3 VennDiagram Visualization in Spotfire, I tried adding below code but it fails to execute marking:
Hi Team,
I am not able to add marking to VennDiagram or any other JSViz samples provided by TIBCO for D3.
You can download the DXP file from : https://drive.google.com/folderview?id=0B7rSzsao8vgUUlEyc0hWUk13WmM
I am using the following code to add marking, but it fails:
function markModel(markMode, rectangle) {
if (svg) {
// No point in continuing if we don't have an svg object
// Start collecting indexes of svg objects marked.
var indicesToMark = [];
var markData = {};
markData.markMode = markMode;
svgElem = svg[0][0];
var rpos = svgElem.createSVGRect();
rpos.x = rectangle.x;
rpos.y = rectangle.y;
rpos.height = rectangle.height; // + one to get the item under the click
rpos.width = rectangle.width; // + one to get the item under the click
var elements = svgElem.getIntersectionList(rpos, svgElem);
for (var index = 0; index < elements.length; index = index + 1) {
if (elements[index].id) {
indicesToMark.push(elements[index].id);
}
}
markData.indexSet = indicesToMark;
markIndices ( markData );
}
Please let me know your thoughts on this

search for element within element by tagname

After being stuck for a few hours on this problem, i think it is time for call for help on this.
Situation
I have a XML file which i need to filter and group. I've managed to filter it with the :Contains part. I've also determined the nodes on which i need to group (the getGroups function gives those back to me). Now i want to create a new XML with the filtered values and grouped by the returned keys.
Code
var XMLElement = document.createElement("DataElementsCalc");
jQuery(xml).find("DataElements " + topNodes + filter).each( function() {
var dataSetTemp = this.parentNode;
if(calculation1 != "")
{
var groupKeys = getGroups(dataSetTemp,calculation1);
var tempXML = XMLElement;
jQuery(groupKeys).each(function (key,value) {
var tempValue = 'a' + value.toLowerCase().replace(/\W/g, '');
if(tempXML.getElementsByTagName(tempValue).length > 0)
{
tempXML = tempXML.getElementsByTagName(tempValue);
}
else
{
var Node = document.createElement(tempValue);
tempXML.appendChild(Node);
tempXML = Node;
}
});
var Node = document.createElement("InfoSet");
var x = dataSetTemp.childNodes;
for (i=0; i < x.length; i++)
{
if(x[i].nodeType == 1)
{
var tempElement = document.createElement(x[i].nodeName);
tempElement.innerHTML = x[i].childNodes[0].nodeValue;
Node.appendChild(tempElement);
}
}
tempXML.appendChild(Node);
}
});
Explanation
As said in the situation, i already filtered the XML and have the groupNames from the getGroups function. There are a few other things i need to explain for this code:
tempValue is being build as a a + value.toLowerCase().replace(/\W/g, '');. This is being done because i possible get dates into the groupKeys. This way the node name is getting a working name (i received errors on other ways).
I want to create a new XML which is leveled by the groups. If a group already exists, i want to create a new element in it, not get a new group with the same name. (my problem at the moment).
Problem
As mentioned above, the groups aren't checked properly. Firstly: tempXML.getElementsByTagName(tempValue).length returns the error that the function tempXML.getElementsByTagName does not exists. Secondly: If i change this to document.getElemetsByTagName I get a lot of the same nodes in my XML file.
Effect
The grouping effect doesn't work as it should. I get OR an error, OR a lot of the same nodes in my DataElementsCalc.
Questions
How can i solve this? How do create nodes beneath specific nodes (for if there is a group A beneath group 1 as well as beneath group 2)?
Tried
Change tempXML to document on different places (all getElementsByTagName, at the same time or not). Looked for another way to create a XML which is easier to handle (haven't found one, yet)
As mentioned by myself in the comments of the question:
I also don't see anything in the source code for this (maybe this is the reason why it doesn't work??)
I tried to place the XMLElement into an existing element on my webpage (like this:
var XMLElement = document.createElement("DataElementsCalc");
jQuery('.basicData').append(XMLElement);
in which basicData is a class of an existing element).
Now i do get a list of all elements ordered on the groups i wanted.
Final version
var XMLElement = jQuery("<DataElementsCalc/>");
jQuery('.basicData').append(XMLElement);
jQuery(xml).find("DataElements " + topNodes + filter).each( function()
{
aantalElementsTotal++;
var dataSetTemp = this.parentNode;
if(calculation1 != "")
{
var groupKeys = getGroups(dataSetTemp,calculation1);
var tempXML = XMLElement;
var groupId = '';
jQuery(groupKeys).each(function (key,value) {
var tempValue = 'a' + value.toLowerCase().replace(/\W/g, '');
groupId += 'a' + value.toLowerCase().replace(/\W/g, '');
if(jQuery("#" + groupId).length > 0)
{
tempXML = jQuery("#" + groupId);
}
else
{
var Node = jQuery("<"+tempValue+"/>");
jQuery(Node).attr('id', groupId);
jQuery(tempXML).append(Node);
tempXML = Node;
}
});
var Node = jQuery("<InfoSet/>");
var x = dataSetTemp.childNodes;
for (i=0; i < x.length; i++)
{
if(x[i].nodeType == 1)
{
var tempElement = jQuery("<"+x[i].nodeName+"/>");
jQuery(tempElement).text(x[i].childNodes[0].nodeValue);
jQuery(Node).append(tempElement);
}
}
jQuery(tempXML).append(Node);
}
});

How to change the URL of an image tag on every click on the image using JavaScript?

I have an element displaying an image on an HTML page. This element's source is one of many different images in a JavaScript array.
I already have a script for looping through the images, creating a slideshow effect, but now I want to manually flick through the images with buttons.
This is my code so far, but I get no response when clicking the button.
function nextup()
{
imgs = [];
imgs[0] = "/snakelane/assets/images/thumb/_1.jpg"; imgs[10] = "/snakelane/assets/images/thumb/_19.jpg";
imgs[1] = "/snakelane/assets/images/thumb/_2.jpg"; imgs[11] = "/snakelane/assets/images/thumb/_20.jpg";
imgs[2] = "/snakelane/assets/images/thumb/_3.jpg"; imgs[12] = "/snakelane/assets/images/thumb/_21.jpg";
imgs[3] = "/snakelane/assets/images/thumb/_4.jpg"; imgs[13] = "/snakelane/assets/images/thumb/_22.jpg";
imgs[4] = "/snakelane/assets/images/thumb/_5.jpg"; imgs[14] = "/snakelane/assets/images/thumb/_23.jpg";
imgs[5] = "/snakelane/assets/images/thumb/_6.jpg"; imgs[15] = "/snakelane/assets/images/thumb/_24.jpg";
imgs[6] = "/snakelane/assets/images/thumb/_7.jpg"; imgs[16] = "/snakelane/assets/images/thumb/_25.jpg";
imgs[7] = "/snakelane/assets/images/thumb/_8.jpg"; imgs[17] = "/snakelane/assets/images/thumb/_26.jpg";
imgs[8] = "/snakelane/assets/images/thumb/_9.jpg"; imgs[18] = "/snakelane/assets/images/thumb/_27.jpg";
imgs[9] = "/snakelane/assets/images/thumb/_32.jpg"; imgs[19] = "/snakelane/assets/images/thumb/_28.jpg";
var pic = document.getElementById("picbox");
for(i =0; i < imgs.length; i++) {
var current = indexOf(pic.src);
var next = Math.round(current + 1);
pic.src = imgs[next];
}
}
Can anyone tell me what's wrong with my code or suggest a better way?
Multiple problems in the approach you had used. Have a look at the modified function below. Let me know if you need explanation with anything.
The following code will use an array containing image URLs and later assign in a sequential manner to an img tag on click. Enjoy!
Here you can try to see the output.
function nextup(){
//Initialized img array with 10 images, you can do it any way you want to.
var imgs = [];
for(i=0;i<10;i++){
imgs[i] = "http://lorempixel.com/output/cats-q-c-100-100-"+(i+1)+".jpg";
}
//Fetch the pic DOM element by ID
var pic = document.getElementById("picbox");
//Know what is position of currently assigned image in array.
var current = imgs.indexOf(pic.src);
var next = 0;
//Handle case if no image is present, the initial case.
if(current!=-1){
next = (current + 1)%(imgs.length);
}
//Assign the next src
pic.src = imgs[next];
}
//Scoped outside to call the function first time on load.
nextup();
I found the following problems in your code:
You tried to use indexOf without specifying the array in which the search has to be performed. Imagine s school principal asking someone to go find if John is present in the classroom without specifying a specific classroom.
For iterating through array you used a next variable which could have been a good idea if you needed an endless loop. But here since we are limited to 10 or 20 images we need to make sure that if the currently selected image is the last one, we find that next goes to 21 (assuming a total of 20 images.) and this would try to access a variable out of bounds.
Hence I've used the mod operator %.
For reference in JavaScript, 5%10 would return 5 , 15%10 would return 5 and so on. Read more about the mod operator HERE.

Occurrences and Arrays positions

Lets say I have this arrays:
likes = [4,6,42,72,7,4,42,56,6,24];
time = [1,2,3,4,5,6,7,8,9,10];
And when clicking in one of the bar charts I have, I'm forwarded to the current time, according to the array likes position.
this.click(function () {
var pos = result_likes.indexOf(this.bar.value);
var pos2 = result_time[pos];
setCurTime(pos2);
});
However when I have the same likes values, for instance number 4, there will be two positions of it, and the SetCurTime, will only forward me to the first time when "like=4 appears (timecode[0];)
How can I solve this and be forward to the right time position?
You need to embed meta data in the bar elements to solve this problem. For instance, you can use custom data attributes like such:
<div class="bar" data-index"5">4</div>
You would dynamically generate this of course, to create each bar with the proper index and value.
Then in your click handler would be:
this.click(function () {
var pos = this.bar.dataset.index;
var pos2 = result_time[pos];
setCurTime(pos2);
});
In light of you using the gRaphael library, perhaps you could crawl the bar elements to see which element it is within the chart, like this:
this.click(function(evt) {
var pos = 0;
var child = evt.currentTarget;
var type = child.nodeName;
while( (child = child.previousSibling) != null && type === child.nodeName)
pos++;
var pos2 = result_time[pos];
setCurTime(pos2);
});
Reposting comment here for any others who need a simliar solution:
var pos2 = result_time[this.bar.id];

Categories

Resources