Finding path using algorithm A* - javascript

hello i'd like to ask some javascript code in finding path using algorithm A*. the path will have source node and target node, and here's the example code
do{
var cursor = nodes.node1 //this is source node
for (var i in GexfJS.graph.edgeList) { // search all edgeList on graph
var _e = GexfJS.graph.edgeList[i] //each list has variable _e
var position = []; // where i put the pointer
if ( _e.source == cursor ) { //when some edge source is match from the cursor(source node/initial node)
var _n = GexfJS.graph.nodeList[_e.target]; // edge target from the node which match with the cursor
_str += 'Found '; // just give string if it's works
position.push(_e.target); // for pointer?
cursor = _e.target // go to the next node, but how can i move to previos node?
}
}
} while(cursor!=nodes.node2); //until find the target node
the problem is im using position.push and it is array but i can't implement the pointer, if its has move next or move previous when finding path to the target node. thanks

maybe you don't need push position.push(_e.target); , just let the cursor in to the end , after the cursor hasn't more target , you can initial the cursor to back to the first node and don't forget each node you visit has to be set to be true

i have the answer for this, initial the cursor from the first node until the target node and don't forget each node you visit has to be set to be true if the node has visited, then go back again try to finding the first edges from the nodes, if the node hasn't true go to the next node, if the node has true find other node. here's my example code
pathed={};
ketemu=false;
cursor1="";
if(path==true){
while(ketemu!=true){
var cursor = nodes.node1;
var lala = new Array();
var visit = new Array();
var j = 0;
for (var i in GexfJS.graph.edgeList) { // relasi yang dituju
var _e = GexfJS.graph.edgeList[i];
if ( _e.source == cursor ) {
var _n = GexfJS.graph.nodeList[_e.target];
if(pathed[_n.label] != true){
if(_e.target==nodes.node2){
cursor = _e.target;
cursor1 = _e.target;
lala[j] = cursor;
visit[j] = cursor;
j++;
ketemu=true;
break;
}
if(_e.target !=nodes.node2){
cursor = _e.target;
lala[j] = cursor;
visit[j] = cursor;
j++;
}
//alert(cursor);
//alert(lala[j]);
}
}
//else if(cursor1==_e.target){
//cursor = nodes.node1;
//alert(cursor);
//}
}
if(ketemu!=true){
i=0;
for(var j=lala.length-1;j>=0;j--){
var test = lala.length-1;
var ujung = lala[test];
var koyong = nodes.node1;
i++;
}
ujung = GexfJS.graph.nodeList[ujung];
pathed[ujung.label] = true;
cursor = koyong;
}
}
for(var k=0;k<visit.length;k++){
var visitednya = visit[k];
var _n = GexfJS.graph.nodeList[visitednya];
_str += '<li><div class="smallpill" style="background: ' + _n.color.base +'"></div>' + _n.label + '' + ( GexfJS.params.showEdgeWeight && _e.weight ? ' [' + _e.weight + ']' : '') + '</li>';
}
visit=[];
//end
}
thanks

Related

How to remove, order up, down elements in Javascript

I'm using JavaScript to remove, order up, order down a text row, it runs normally in IE, but not in Chrome or Firefox.
When I run, I received a message from console bug:
Uncaught TypeError: Failed to execute 'removeChild' on 'Node': parameter 1 is not of type 'Node'.
How to fix the error?
function dels(index) {
var frm = document.writeForm;
var opts = frm['ans' + index].value = ''; // eval("frm.ans_list" + index + ".options");
for (var i = 0; i < opts.length; i++) {
if (opts[i].selected) {
opts[i--].removeChild(true);
}
}
eval("frm.ans" + index + ".value = '' ");
setting_val(index);
}
function up_move(index) {
var frm = document.writeForm;
var opts = eval("frm.ans_list" + index + ".options"); // frm['ans' + index].value = '';
for (var i = 0; i < opts.length; i++) {
if (opts[i].selected && i > 0) {
tmp = opts[i].cloneNode(true);
opts[i].removeChild(true);
opts[i - 1].insertAdjacentElement("beforeBegin", tmp).selected = true;
}
}
setting_val(index);
}
**(UPDATED)**
function down_move(index)
{
var frm = document.writeForm;
var opts=frm["ans_list" + index].options // eval("frm.ans_list" + index + ".options"); // frm['ans' + index].value = '';
for (var i=opts.length-1; i>=0; i--) {
if (opts[i].selected && i<opts.length-1) {
tmp = opts[i].cloneNode(true);
opts[i].removeChild(true);
opts[i].insertAdjacentElement("afterEnd", tmp).selected = true;
}
}
setting_val(index);
}
<span class="bt_test_admin bg_type_01">Delete</span>
<span class="bt_test_admin bg_type_01">▲ Order</span>
<span class="bt_test_admin bg_type_01">▼ Order</span>
Wrong use of removeChild
if (opts[i].selected) {
opts[i--].removeChild(true);
}
The function is intended as:
ParentNode.removeChild(ChildNode);
// OR
ChildNode.parentNode.removeChild(ChildNode);
MDN Documentation on removeChild
Also, you can replace all your evals
eval("frm.ans" + index + ".value = '' ")
eval("frm.ans_list" + index + ".options")
It would be better written as
frm["ans" + index].value = ""
frm["ans_list" + index].options
Finally,
tmp = opts[i].cloneNode(true);
opts[i].removeChild(true);
opts[i].insertAdjacentElement("afterEnd", tmp).selected = true;
Cloning a node, appending the clone, and removing the original would be optimized as moving the original to its new location.
But, you try to remove the original, then insert the clone after the original. It's odd.
If I correctly understood what you try to do, this function could help you.
function reverse_options_order(select_element)
{
// we store the current value to restore it after reordering
const selected_value = select_element.value;
// document fragment will temporarily hold the children
const fragment = document.createDocumentFragment();
while (select_element.lastChild)
{
// last child become first child, effectively reversing the order
fragment.appendChild(select_element.lastChild);
}
// appending a fragment is equal to appending all its children
// the fragment will "merge" with the select_element seamlessly
select_element.appendChild(fragment);
select_element.value = selected_value;
}
You can use the same method to reverse any nodes order

JavaScript code to find text in an HTML body and highlight it FIX

I have this JavaScript function that takes a string and highlight it in the html page. I'm basically trying to simulate Ctrl-F with initial value string:
Function
<script type="text/javascript">
function highlight(word) {
var node = document.body;
for (node = node.firstChild; node; node = node.nextSibling) {
var n = node;
var match_pos = 0;
match_pos = n.nodeValue.indexOf(word);
var before = n.nodeValue.substr(0, match_pos);// split into a part before the match
var middle = n.nodeValue.substr(match_pos, word.length); // the matched word to preserve case
var after = document.createTextNode(n.nodeValue.substr(match_pos + word.length));// and the part after the match
var highlight_span = document.createElement("span");// create a span in the middle
highlight_span.style.backgroundColor = "yellow";
highlight_span.appendChild(document.createTextNode(middle));// insert word as textNode in new span
n.nodeValue = before; // Turn node data into before
n.parentNode.insertBefore(after, n.nextSibling); // insert after
n.parentNode.insertBefore(highlight_span, n.nextSibling); // insert new span
highlights.push(highlight_span);
highlight_span.id = "highlight_span" + highlights.length;
node = node.nextSibling; // Advance to next node or we get stuck in a loop because we created a span (child)
}
}
</script>
Basically, The sentence I give to the function as an argument is not highlighted. Knowing that I'm positive it exists.
This Loads the HTML page
#Html.Action("GetHtmlPage", "Upload", new { path = Model.documentPath })
Then, This Calls the funtion
#{
var str = Model.sentence["sentence"].AsString;
<script>highlight(#str)</script>
}
There was a problem with your loop. Something like this will work much better.
var highlights = []
function searchElement(elem, word){
var children = Array.prototype.slice.call(elem.childNodes);
for(var i=0; i<children.length; i++){
if(children[i].nodeType == Node.TEXT_NODE){
var n = children[i];
var match_pos = n.nodeValue.indexOf(word);
if(match_pos == -1){
continue;
}
var before = n.nodeValue.substr(0, match_pos);// split into a part before the match
var middle = n.nodeValue.substr(match_pos, word.length); // the matched word to preserve case
var after = document.createTextNode(n.nodeValue.substr(match_pos + word.length));// and the part after the match
var highlight_span = document.createElement("span");// create a span in the middle
highlight_span.style.backgroundColor = "yellow";
highlight_span.appendChild(document.createTextNode(middle));// insert word as textNode in new span
n.nodeValue = before; // Turn node data into before
n.parentNode.insertBefore(after, n.nextSibling); // insert after
n.parentNode.insertBefore(highlight_span, n.nextSibling); // insert new span
highlights.push(highlight_span);
highlight_span.id = "highlight_span" + highlights.length;
}else if(children[i].childNodes.length){
searchElement(children[i], word);
}
}
}
function highlight(word) {
searchElement(document.body, word)
}
highlight("Even more test");
test
<div>
More test
<span>Even more test</span>
</div>

Getting a error when click save and I am unable to create new number

When I click on save on my bootstrap modal button it tries to find next available number.
How ever if returns null throws error.
TypeError: matches is null
Question When click on save in bootstrap modal if no numbers found in textarea then will create a number. Currently if no findAvailableNumber function returns null unable to create a number
Codepen Example
$('#myLink').on('shown.bs.modal', function() {
var text = getSelectedText();
$('#title').val(text.trim());
$('#url').val('http://');
});
function getSelectedText() {
var textarea = document.getElementById("message");
var len = textarea.value.length;
var start = textarea.selectionStart;
var end = textarea.selectionEnd;
var sel = textarea.value.substring(start, end);
return sel;
}
function findAvailableNumber(textarea){
//Find lines with links
var matches = textarea.value.match(/(^|\n)\s*\[\d+\]:/g);
//Find corresponding numbers
var usedNumbers = matches.map(function(match){
return parseInt(match.match(/\d+/)[0]); }
);
//Find first unused number
var number = 1;
while(true){
if(usedNumbers.indexOf(number) === -1){
//Found unused number
return number;
}
number++;
}
return number;
}
$('#save-link').on('click', function(e) {
var textarea = document.getElementById("message");
var len = textarea.value.length;
var start = textarea.selectionStart;
var end = textarea.selectionEnd;
var sel = textarea.value.substring(start, end);
var counter = findAvailableNumber(textarea);
var replace = '[' + $('input#title').val() + ']' + '[' + counter + ']';
var id = '\n [' + counter + ']: ' + $('input#url').val();
if ($('#title').val().length > 0) {
textarea.value = textarea.value.substring(0,start) + replace +
textarea.value.substring(end,len) + id;
} else {
return false;
}
});
How links look in textarea when created.
[exmple-1][1] and [example-2][2]
[1]: http://www.example.com
[2]: http://www.example.com
You need to check to see if the <textarea> actually has a value within findAvailableNumber(). If not, return 1 to kick it off.
function findAvailableNumber(textarea){
var number = 1;
if(textarea.value){
//Find lines with links
var matches = textarea.value.match(/(^|\n)\s*\[\d+\]:/g);
//Find corresponding numbers
var usedNumbers = matches.map(function(match){
return parseInt(match.match(/\d+/)[0]); }
);
//Find first unused number
var number = 1;
while(true){
if(usedNumbers.indexOf(number) === -1){
//Found unused number
return number;
}
number++;
}
}
return number;
}
Here's an updated pen.

Locate Existing Numbers For Hyperlink In Textarea Set Next Avaibale One On Save / Click Modal

I am using CodeIgniter & jQuery and parsedown/markdown When I open my bootstrap modal, it allows me to create a new Reference-style link like on here.
I am trying to be able to find some how where it can find the next free number for my available in my textarea and when click save in model will set it.
I am fine [exmple-1][1] and [example-3][3]
[1]: http://www.example.com
[3]: http://www.example.com
And when I open my bootstrap modal and create a new hyperlink it will set and add the next available number
Here is the Codepen Example
Question: How can I when I create a new hyperlink in my bootstrap modal
and click save it can find the next available number set it. Because only 1 & 3 are set in example above next one should be 2 when click save in model
currently as you can see below I just use var counter = 1; and counter++; to be able to create numbers.
Script:
$('#myLink').on('shown.bs.modal', function() {
var text = getSelectedText();
$('#title').val(text.trim());
$('#url').val('http://');
});
function getSelectedText() {
var textarea = document.getElementById("message");
var len = textarea.value.length;
var start = textarea.selectionStart;
var end = textarea.selectionEnd;
var sel = textarea.value.substring(start, end);
return sel;
}
var counter = 1;
$('#save-link').on('click', function(e) {
var textarea = document.getElementById("message");
var len = textarea.value.length;
var start = textarea.selectionStart;
var end = textarea.selectionEnd;
var sel = textarea.value.substring(start, end);
var replace = '[' + $('input#title').val() + ']' + '[' + counter + ']';
var id = '\n [' + counter + ']: ' + $('input#url').val();
counter++;
if ($('#title').val().length > 0) {
textarea.value = textarea.value.substring(0,start) + replace +
textarea.value.substring(end,len) + ' \n' + id;
$('#myLink').modal('hide');
//$('#myLink form')[0].reset();
} else {
return false;
}
});
You can use a simple regex to find the used numbers in the textarea:
function findAvailableNumber(textarea){
//Find lines with links
var matches = textarea.value.match(/(^|\n)\s*\[\d+\]:/g);
//Find corresponding numbers
var usedNumbers = matches.map(function(match){
return parseInt(match.match(/\d+/)[0]); }
);
//Find first unused number
var number = 1;
while(true){
if(usedNumbers.indexOf(number) === -1){
//Found unused number
return number;
}
number++;
}
return number;
}
Add the function, remove the line var counter = 1; and replace counter++; with var counter = findAvailableNumber(textarea);
JSFiddle
As Barmar said: store your already generated numbers in an object or an array and check for the next non-existing number:
var existingNumbers = [1, 3];
function getNextNumber() {
var i = 1;
while (existingNumbers.indexOf(i) > - 1) {
i++;
}
existingNumbers.push(i);
return i;
}
Then get the next number with:
var number = getNextNumber();

What should i do in order to print level also in Breadth first search Algo.

What can be done in the below algo in order to print values level wise in binary tree.
BinarySearchTree.prototype.breadthFirstTraversal = function() {
console.log("Breadth First Traversal");
var q = []
q.push(this.root);//You don't need to write the root here, it will be written in the loop
while (q.length > 0)
{
var n = q.shift();
console.log(n.value); //Only write the value when you dequeue it
if (n.left !=null)
{
q.push(n.left);//enqueue the left child
}
if (n.right !=null)
{
q.push(n.right);//enque the right child
}
}
};
Just wanted to add this since it doesn't require the storage of the level of each corresponding node as in the solution above so it doesn't require you to add a property to your object. If you think about it the queue will have, at most, two different levels in it. So you only need one global marker to let you know if you are dealing with a new level and a flag to let you know if you should mark the new right or left node being pushed.
BinarySearchTree.prototype.breadthFirstTraversal = function() {
console.log("Breadth First Traversal");
var q = new Array();
q.push(this.root);
var printArray = [];
var printArray.push(this.root.value);
var newlevel = false;
var marker = 1;
var level = 0;
while(q.length > 0){
if(marker==1){
console.log("level: " + level);
console.log(printArray);
newlevel = true;
}
var n = q.shift();
printArray.shift();
marker -= 1;
//console.log(n.value);
if(n.left != null){
q.push(n.left);
printArray.push(n.left.value);
if(newlevel){
marker = q.length;
level+=1;
newlevel = false;
}
}
if(n.right != null){
q.push(n.right);
printArray.push(n.right.value);
if(newlevel){
marker = q.length;
level+=1;
newlevel = false;
}
}
}
};
Store level for each node, and print them only when level changes:
BinarySearchTree.prototype.breadthFirstTraversal = function() {
console.log("Breadth First Traversal");
var q = [];
var prevLevel = -1; // monitor level switch
var byLevel = []; // store node values for printing
this.root.level = 0; // set root level
q.push(this.root);//You don't need to write the root here, it will be written in the loop
byLevel.push(this.root.value);
while (q.length > 0)
{
var n = q.shift();
// Next level, print and reset
if (n.level > prevLevel) {
console.log(byLevel);
byLevel = [];
prevLevel = n.level;
}
if (n.left !=null)
{
n.left.level = n.level + 1;
q.push(n.left);//enqueue the left child
byLevel.push(n.left.value);
}
if (n.right !=null)
{
n.right.level = n.level + 1;
q.push(n.right);//enque the right child
byLevel.push(n.right.value);
}
}
if (byLevel.length > 0) {
console.log(byLevel);
}
};

Categories