In RaphaelJS, how do I move around individual nodes in a path? - javascript

Is there an array containing those?
Also, is it also possible to add nodes in an existing path?

You need to edit the path. No, there's no array, just the path string. You can of course write higher level code that keeps tracks of nodes in arrays from which you generate path strings.
A simple implementation would be something like:
function Polygon (nodes) {
if (nodes instanceof Array) this.nodes = nodes;
else this.nodes = [];
}
Polygon.prototype.draw = function () {
var path = "M" + this.nodes[0][0] + "," + this.nodes[0][1];
for (var i=1; i<this.nodes.length; i++) {
path += "L" + this.nodes[i][0] + "," + this.nodes[i][1];
}
path += "Z";
return path;
}
Then you would do:
var p = new Polygon([[100,100],[100,200],[200,200],[200,100]]);
var pp = paper.path(p.draw());
// Modify node:
p.nodes[2] = [300,300];
pp.attr('path',p.draw());
// Add node:
p.nodes.push([250,150]);
pp.attr('path',p.draw());
Of course you can be more creative with the API you implement. For example, polygon.draw() can automatically update a linked Raphael Element. The code above is just a simple example of the basic idea.

Related

How to dynamically create a nested tree with depth 10 in JavaScript using a loop

I have a general tree class with: myTree = new Tree(string), appendChildNode(node), createChildNode(string), myTree.print() functions and myTree.name, myTree.children, etc attributes.
I know, I can create a tree depth (10) by hand like so:
// declare new tree
myTree = new Tree('Diagrams')
// adding nodes by hand here
myTree.createChildNode('A1').createChildNode('A2').createChildNode('A3').createChildNode('A4').createChildNode('A5').createChildNode('A6').createChildNode('A7').createChildNode('A8').createChildNode('A9').createChildNode('A10')
myTree.print()
How would I do that programmatically using a for loop? Expected result depth 10:
Diagrams
A1
A2
A3
A4
A5
A6
A7
A8
A9
A10
Sorry, if this is a question that was answered before, I just cannot come up with a proper query to search for a solution to this. I think I am missing a syntax in JS for doing that. Info: I took the following general tree implementation: https://github.com/beforesemicolon/tutorials-files/blob/master/tree-generic.js
Just loop, adding child to a node, and updating node to be the child and so on. Tested :-)
var myTree = new Tree('Diagrams')
var node = myTree;
var children = 'A1,A2,A3,A4,A5,A6,A7,A8,A9,A10'.split(",");
children.forEach(function(child) {
node = node.createChildNode(child)
})
myTree.print()
function Tree(tree_name) {
var children = [];
var name = tree_name
this.createChildNode = function(child_name) {
var child = new Tree(child_name);
children.push(child)
return child;
}
this.print = function(level) {
level = level || 0;
var space = ' '.repeat(level)
console.log(space + name)
children.forEach(function(child) {
child.print(level + 1);
})
}
}
let tree = new Tree("Diagrams"); // create the tree
let node = tree; // we need this variable so we can assign the current node to it in the loop
for(let i = 0; i < 10; i++) {
let name = "A" + (i + 1); // the name of the current node
node = node.createChildNode(name); // create the node with the given name and assign the newly created node so we can create the sub node in the next iteration
}
not tested
Just store previous child in a variable and append new node to it:
// declare new tree
myTree = new Tree('Diagrams')
let child = myTree;
for(let i = 1; i < 11; i++)
{
child = child.createChildNode('A' + i);
}
myTree.print();

Can't get objects inside of array

I have been trying to use JavaScript array to push my object by header
like this :
var tab_temp = new Y.TabView(
{ srcNode: '#' + tabId }
);
tabsArray['"' + type + "_" + subTypes + '"'] = tab_temp;
Let's type = "x" and subTypes = "y", so I was expecting the object when I write something like:
tabs["x_y"]
But there is problem with this. When I debug, I can see this array will hold an object "x_y" but length of the array is 0
I can't use push also because in that way I need to use index to get it back but it is tough since sequence might change.
Edit 1:
I am using this because I want to hold a couple of TabView objects. Otherwise I can't reach those object after they created. (AlloyUI). I was able to push those object inside of array. As you see "Baru_BARANG" include and object that start with: s
Edit 2:
Thanks for help, I fixed it. I used Object instead of Array for this:
var tabs = {}
tabs[x + "_" + y] = "z";
I get the value by tabs[x + "_" + y]
You really need to be reading more about working with objects in JavaScript.
Try here first.
var type = "x";
var subType = "y";
var tabsArray = {};
tabsArray[type + "_" + subType] = "z";
console.log("tabsArray = ");
console.log(tabsArray);
console.log("tabsArray['x_y'] = " + tabsArray["x_y"]); // output: z
// Including code added to question as a comment:
var tabsArray = [];
var x = "x";
var y = "y";
tabsArray[x + "_" + y] = "z";
console.log("tabsArray['x_y'] = " + tabsArray["x_y"]);
// tabsArray.length will still be 0. To set .length you can use:
for (var i = 0; i < tabsArray.length; i++) {
tabsArray.length = ++i;
};
console.log("tabsArray.length = " + tabsArray.length);
You are most likely instantiating tabsArray as an array, i.e. var tabsArray = [];. This results in the observed behavior.
Since you want to define the keys yourself, you should instantiate it as an object instead:
var tabsArray = {};
tabsArray['x_y'] = 'z';
More about working with objects in JavaScript.

Javascript string manipulation url

My problem is I am trying to extract certain things from the url. I am currently using
window.location.href.substr()
to grab something like "/localhost:123/list/chart=2/view=1"
What i have now, is using the index positioning to grab the chart and view value.
var chart = window.location.href.substr(-8);
var view = window.location.href.substr(-1);
But the problem comes in with I have 10 or more charts. The positioning is messed up. Is there a way where you can ask the code to get the string between "chart=" and the closest "/"?
var str = "/localhost:123/list/chart=2/view=1";
var data = str.match(/\/chart=([0-9]+)\/view=([0-9]+)/);
var chart = data[1];
var view = data[2];
Of course you may want to add in some validation checks before using the outcome of the match.
Inspired by Paul S. I have written a function version of my answer:
function getPathVal(name)
{
var path = window.location.pathname;
var regx = new RegExp('(?:/|&|\\?)'+name+'='+'([^/&,]+)');
var data = path.match(regx);
return data[1] || null;
}
getPathVal('chart');//2
Function should work for fetching params from standard get parameter syntax in a URI, or the syntax in your example URI
Here's a way using String.prototype.indexOf
function getPathVar(key) {
var str = window.location.pathname,
i = str.indexOf('/' + key + '=') + key.length + 2,
j = str.indexOf('/', i);
if (i === key.length + 1) return '';
return str.slice(i, j);
}
// assuming current path as described in question
getPathVar('chart');
You could split your string up, with "/" as delimiter and then loop through the resulting array to find the desired parameters. That way you can easily extract all parameters automatically:
var x = "/localhost:123/list/chart=2/view=1";
var res = {};
var spl = x.split("/");
for (var i = 0; i < spl.length; i++) {
var part = spl[i];
var index = part.indexOf("=");
if (index > 0) {
res[part.substring(0, index)] = part.substring(index + 1);
}
}
console.log(res);
// res = { chart: 2, view: 1}
FIDDLE

Raphaƫl - transformPath() to return lines instead of curves

Is it possible to get Raphael.transformPath() to return a path made of lines instead of a path made of curves?
var path = "M10,20L30,40";
var trans = "t100,100s2,2";
var trpath = Raphael.transformPath(path, trans);
console.log('trpath: ' + trpath);
will output:
trpath: M100,110C100,110,140,150,140,150
I need this path with only straight lines!
Weird, not sure why Raphael chooses to do this. But not too hard to get around:
If you consult the source for the .transformPath() method, you'll see that it is a composite of two other utility methods:
transformPath = R.transformPath = function (path, transform) {
return mapPath(path, toMatrix(path, transform));
}
Pretty straight-forward: .toMatrix() parses that transform string into a matrix, and mapPath applies that matrix to the path string.
For some reason, mapPath includes a call to the .path2curve() method, which is why you're having trouble. So we need to grab the source for that method and modify it:
var mapPathStraight = function (path, matrix) {
if (!matrix) {
return path;
}
var x, y, i, j, ii, jj, pathi;
//replace following line with .parsePathString(), which also parses path string into an array without adding curves
//path = path2curve(path);
path = Raphael.parsePathString(path);
for (i = 0, ii = path.length; i < ii; i++) {
pathi = path[i];
for (j = 1, jj = pathi.length; j < jj; j += 2) {
x = matrix.x(pathi[j], pathi[j + 1]);
y = matrix.y(pathi[j], pathi[j + 1]);
pathi[j] = x;
pathi[j + 1] = y;
}
}
return path;
};
Now we can achieve a straight line like so:
var trpath = mapPathStraight(path, Raphael.toMatrix(path, trans));
Which gives me an output of:
trpath: M100,110L140,150
Here's the jsFiddle

Chord Chart - Skip to key with a click

I have a chord chart app that basically can transpose a chord chart up and down throughout the keys, but now I would like to expand that app and allow someone to pick a key and automatically go to that key upon a click event using a function in javascript or jquery. Can someone help me figure this out? The logic seems simple enough, but I'm just not sure how to implement it. Here are my current functions that allow the user to transpose up and down...
var match;
var chords = ['C','C#','D','D#','E','F','F#','G','G#','A','A#','B','C','Db','D','Eb','E','F','Gb','G','Ab','A','Bb','B','C'];
var chords2 = ['C','Db','D','Eb','E','F','Gb','G','Ab','A','Bb','B','C','C#','D','D#','E','F','F#','G','G#','A','A#','C'];
var chordRegex = /(?:C#|D#|F#|G#|A#|Db|Eb|Gb|Ab|Bb|C|D|E|F|G|A|B)/g;
function transposeUp(x) {
$('.chord'+x).each(function(){ ///// initializes variables /////
var currentChord = $(this).text(); // gatheres each object
var output = "";
var parts = currentChord.split(chordRegex);
var index = 0;
/////////////////////////////////
while (match = chordRegex.exec(currentChord)){
var chordIndex = chords2.indexOf(match[0]);
output += parts[index++] + chords[chordIndex+1];
}
output += parts[index];
$(this).text(output);
});
}
function transposeDown(x){
$('.chord'+x).each(function(){
var currentChord = $(this).text(); // gatheres each object
var output = "";
var parts = currentChord.split(chordRegex);
var index = 0;
while (match = chordRegex.exec(currentChord)){
var chordIndex = chords2.indexOf(match[0],1);
//var chordIndex = $.inArray(match[0], chords, -1);
output += parts[index++] + chords2[chordIndex-1];
}
output += parts[index];
$(this).text(output);
});
}
Any help is appreciated. Answer will be accepted! Thank You
Is this all you want? a function that will create a click event?
$('[class^="chord"]').click(function() {
alert($(this).text() + ' clicked');
});
Based on your comment: Here is some pseudo-code to get you going in the right direction:
also store a transposed version of each chords array
when a note is clicked, find its element in the original chords array (using $(this).text() above to match the note name)
when a match is found, you can find its transposed version using the same array index

Categories