How to create a tree structure in Javascript DOM? - javascript

This is going to sound too silly / too basic - sorry about that, but I experimented a lot and couldn't come to the right solution!
I'm using this following piece of code - which makes a row of text fields go up and down. Unfortunately, the up and down movement doesnt stop and carries on throughout the page! :)
function up(row) {
// need to stop somewhere
var prevRow = row.previousSibling;
if(prevRow != null) {
row.parentNode.insertBefore(row, prevRow);
}
};
function down(row) {
// need to stop somewhere as well
var nextRow = row.nextSibling;
row.parentNode.insertBefore(row, nextRow.nextSibling);
};
My generated html is a combination of xml and xsl. The XSL looks like this:
<xsl:for-each select=".../...">
<p>
<button type="button" onclick="up(this.parentNode)">Up</button>
<button type="button" onclick="down(this.parentNode)">Down</button>
<input>
...
...
...
</p>
</xsl:for-each>
As described above, this works, but the up and down movements dont stop. I tried enclosing the xsl:for-each in another p tag, and a div tag, but neither worked. I was trying to have the parent of these p tags as something other than the body tag.
Did I make myself clear?
Generated HTML added below:
<html>
<head>
<script>
function up(row) {
...
};
function down(row) {
...
};
</script>
</head>
<body>
<form name="edit_form" action="edit.php" method="POST">
...
<?xml version="1.0"?>
...
<p>
<button type="button" onclick="up(this.parentNode)">Up</button>
<button type="button" onclick="down(this.parentNode)">Down</button>
<input name="CRorder[record10354881]" type="text" value="0" disabled="" size="4"/>
<input name="CRpreference[record10354881]" type="text" value="10" disabled="" size="4"/>
<input name="CRlabel[record10354881]" type="text" value="label1"/><input name="CRvalue[record10354881]" type="text" value="22222222222"/></p>
<p><button type="button" onclick="up(this.parentNode)">Up</button>
<button type="button" onclick="down(this.parentNode)">Down</button>
<input name="CRorder[record10354882]" type="text" value="1" disabled="" size="4"/>
...
...
</form></body>
</html>

Based on your HTML, and assuming the ...s do not contain matched pairs of tags that will make the P a child, the P containing the Up/Down buttons (and other paraphinalea) will move up the list of Ps until it is the first child of the FORM tag. As this is directly adjacent to the BODY tag, this is, in effect, moving it all the way up the page.
Edit: OK, from your comment, if you have other siblings to the P tags that you don't to move them past, you'll need to mark them somehow and change your up/down functions to obey those limits. Something like...
...<tag id="upperLimit">...
function up(row) {
// need to stop somewhere
var prevRow = row.previousSibling;
if(prevRow != null && prevRow != document.getElementById("upperLimit")) {
row.parentNode.insertBefore(row, prevRow);
}
};
with a similar restriction on the lower limit.

Related

How would I go about creating this jump page?

Note: I'm a total novice at any coding. I'm just a dumb amature graphic designer. I've only ever created a page that lets me copy the
the most common phrases I had to leave in notes all day. I struggled
with it.
I'm trying to create this page that lets input something into a text field, and it applies it to defined URLS attached to buttons, that will bring me to those pages. Since I struggle to describe it, please see this visual: https://i.stack.imgur.com/ZplRK.jpg
I've tried co-opting some scripts for similar problems, but with no luck. (See below for examples before I edited them ). I included them to see if I was on the right track whatsoever. I know I'm gonna have an issue with multiple functions, probably?
<script type="javascript">
function goToPage(var url = '')
{
var initial = "http://example.com";
var extension = "html";
window.location(initial+url+extension);
}
</script>
<form name="something" action="#">
Label <input type="text" name="url" value="" onchange="goToPage(this.value)">
</form>
<SCRIPT type="javascript">
function goToPage(var url = '')
{
var initial = "https://cms.example.com/client/viewcasedetails";
var extension = "";
window.location(initial+url+extension);
}
</SCRIPT>
<TITLE>Redirect 1</TITLE>
<BASE HREF="https://cms.example.com/client/viewcasedetails">
</HEAD>
<BODY>
<P>
<FORM name="jump" action="#">
CMS ID:
<INPUT type="text" name="url" value="" onSubmit="goToPage(this.value)">
<INPUT type="submit" value="GO">
That's where I at. I'm just tired of typing the same long URLs all day at work, and messing up more than half the time. I have no clue what the solution is - Javascript? HTML? CSS? Just trying to seek the DIY answer before looking on how to hire someone to make it. Which I have no clue how to do either but that's another question for later.
Thanks for helping / apologies for possibly super dumb questions.
You could do something like the following:
// grab the input element
const input = document.getElementById("cmsId");
// grab all links that need to be updated accordingly
// when value inside input element changes
const links = document.querySelectorAll("a");
// create a handler that listens for changes when
// you type some text into the input element
input.addEventListener("input", (event) => {
// grab value inside input elemenet
const value = event.target.value;
// iterate through all links and update
// the inner text + href attribute accordingly
// NOTE: `baseUrl` for each link is stored in a
// `data-*` attribute
links.forEach((link) => {
const baseUrl = link.dataset.url;
const url = baseUrl + value;
link.innerText = url;
link.href = url;
});
});
<!-- Use a simple input element here, no need for a form -->
<div>CMS ID: <input id="cmsId" type="text" /></div>
<div>
<!-- No need to create buttons, simple anchor elements will work just fine -->
<a
id="main"
href="#"
target="_blank"
data-url="https://cmss.company.com/client/viewclientdetails/"
>
https://cmss.company.com/client/viewclientdetails/
</a>
</div>
<div>
<a
id="notes"
href="#"
target="_blank"
data-url="https://cmss.company.com/client/viewnotes/"
>
https://cmss.company.com/client/viewnotes/
</a>
</div>
<div>
<a
id="docs"
href="#"
target="_blank"
data-url="https://cmss.company.com/client/documentsall/"
>
https://cmss.company.com/client/documentsall/
</a>
</div>
<div>
<a
id="activity"
href="#"
target="_blank"
data-url="https://cmss.company.com/client/viewactivityledger/"
>
https://cmss.company.com/client/viewactivityledger/
</a>
</div>
In your code you are working with only the "main" button as I can see (as it goes to viewclientdetails). You are missing a "/" sign after var initial. So, assuming that you can implement the same functionality of the main button to the other buttons, here's what you can do:
<script type="text/javascript">
function goToPage(var url = '')
{
var initial = "https://cms.example.com/client/viewcasedetails/"; //I added the slash
var extension = "";
window.location(initial+url+extension);
}
</script>
<TITLE>Redirect 1</TITLE>
<BASE HREF="https://cms.example.com/client/viewcasedetails">
</HEAD>
<BODY>
<P>
<FORM name="jump" action="#">
CMS ID:
<INPUT type="text" name="url" value="" onSubmit="goToPage(this.value)">
<INPUT type="submit" value="GO"> //you need 4 buttons here
You cannot have an input type="submit" here, since you will need four buttons. Submit works like a form submission. Add four buttons, then for each button's onClick property add the desired redirect url. You will need to get the value for the input field using an ID tag.
An example of what I am trying to say is given below:
<script type="text/javascript">
function onMainButtonClicked()
{
var cmsid= document.getElementById("cmsID").value;
var initial = "https://cms.example.com/client/viewcasedetails/"; //I added the slash
var extension = "";
window.location(initial+cmsid+extension);
}
function onNotesButtonClicked()
{
...
}
function onDocsButtonClicked()
{
...
}
function onActivityButtonClicked()
{
...
}
</script>
<TITLE>Redirect 1</TITLE>
<BASE HREF="https://cms.example.com/client/viewcasedetails">
</HEAD>
<BODY>
<P>
<FORM name="jump" action="#">
CMS ID:
<INPUT type="text" id="cmsID" name="url" value="">
<button onclick="onMainButtonClicked()">Main</button>
<button onclick="onNotesButtonClicked()">Notes</button>
<button onclick="onDocsButtonClicked()">Docs</button>
<button onclick="onActivityButtonClicked()">Activity</button>
There are much better ways to implement this, but this is a very simple implementation.

How do i add custom code from a user inside the <head> tag

i created a form builder, however, i need to find a way to have the person add their own tracking codes when they publish the forms, these tracking codes go in the code.
<section class="tracking-codes">
<h2> Please enter all tracking codes in here: </h2>
<form>
<input type="text" id="code" placeholder="Facebook Pixel"> </input>
<button type="button" onclick="codes()"> Add Code </button
</form>
</section>
here is my js
function codes ()
{
var trackingCode = document.getElementById('code');
document.head.appendChild(trackingCode);
console.log(trackingCode);
}
at this point, it does append the id of code but only the part of
<input type="text" id="code" placeholder="Facebook Pixel">
and not the user input, how would i go about doing this?
I have also tried the .value at the end of making the var of trackingcodes but it doesnt work.
Instead of adding html to the head section, you should use a hidden field input. Add it like this:
function codes ()
{
var trackingCode = document.getElementById('code').value;
var element = document.createElement('input');
element.type = 'hidden';
element.id = 'tracking';
document.head.appendChild(element);
console.log(trackingCode);
}

display data in blank array javascript. <div>

So far I have been able to come up with something like this. And i have been able to send something to an array, but in the display, thats what i have not been able to achieve so far.
Hence i am asking, How do i display it?
<!doctype html>
<html>
<head>
<script type=text/javascript>
var array = [];
function add_element_to_array() {
array.push(document.getElementById("institution_name").value);
array.push(document.getElementById("degree_obtained").value);
array.push(document.getElementById("honors_acheieved").value);
document.getElementById("institution_name").value = "";
document.getElementById("degree_obtained").value = "";
document.getElementById("honors_acheieved").value = "";
}
function display_array()
{
// Display array
}
</script>
</head>
<title>Test Javascript</title>
<h1>Test JS</h1>
<body>
<form name="xform" id="xform" method="post" action="samris.php" /> Institution Name:
<input type="text" name="institution_name" id="institution_name" /> </br>
Degree Obtained:
<input type="text" name="degree_obtained" id="degree_obtained" />
</br>
Honors Achieved:
<input type="text" name="honors_acheieved" id="honors_acheieved" />
</br>
</p>
<input type="button" name="Add" id="add" value="add" onclick="add_element_to_array()" />
</form>
<div onload= display_array()>
</div>
</body>
</html>
To display array:
function display_array(){
var display = array.join('<br>');
this.innerHTML = display; // only works if you call it inline (except onload).
/* OR */
// works everywhere when you add an id to the div except onload (see explanation below).
document.getElementById('display').innerHTML = display;
}
/* ... in the HTML ... */
<div id="display"></div>
However you will still not able to display it in the div because of the onload=display_array().
When the div is being loaded, display_array() will be called. However when it is being loaded, array is still empty because nothing has been added to it yet by onclick=add_element_to_array().
To do that, you can call display_array() from within add_element_to_array() like so:
function add_element_to_array(){
/*
your code
*/
display_array();
}
Alternatively, you need to remove the onclick and replace by addEventListener in your <script>. However, you will need to move your <script> tag to the bottom of your <body> tag or otherwise implement a function similar to jQuery's ready().

How to dynamically generate html widgets using jQuery?

I have an interactive widget that I want to display on my page. However I also want to give the user the possibility to generate more instances of the same widget and to be able to interact with them simultaneously. As an example, let's say this is my widget:
<div id="my_widget">
<script type="text/javascript" src="jquery-1.5.1.js"></script>
<script>
$(document).ready(function() {
$("#up_one").click(function() {
$("#number").val(parseInt($("#number").val())+1);
});
});
</script>
<p>
<input type="submit" id="up_one" value="Up One!"/>
<input type="text" id="number" type="number" value="0" maxlength="2">
</p>
</body>
Now, to display this on my main page I use load(), as follows
$(document).ready(function() {
var i = 0;
$("#hello_submit").click(function() {
$("#hello_div").load("widget_test.html");
});
});
</script>
<div id="hello_div">
<p>
<input id="hello_submit" type="submit" value="New counter" />
</p>
</div>
But there are 2 problems with this. First I can only load the widget once, and second, it would allow the user to navigate directly to widget_test.html, which would defeat the purpose of all this. So I tried another method that involves turning the widget into a long string. To this string I add an index parameter which is used to dynamically generate id and class names, like this:
function BAString(){
this.getBas = function(value){
var bas = '<body><script>$(document).ready(function() {$("#up_one'+value+'").click(function() {\
$("#number'+value+'").val(parseInt($("#number'+value+'").val())+1);});}); </script> <p>\
<input type="submit" id="up_one'+value+'" value="Up One!"/>\
<input type="text" id="number'+value+'" type="number" value="0" maxlength="2"></p></body>';
return bas;
};
In my main page I then use this function:
$(document).ready(function() {
var i = 0;
$("#hello_submit").click(function() {
var b = new BAString();
$("#hello_div").append(b.getBas(i));
i++;
});
});
This second method seems to work great but I can see obvious problems with maintainability as my widget becomes more and more complex. So what is the ideal solution to be used in a case like this?
Well you can make it work with classes instead of Ids
that way you can add multiple widgets with the same function
$(document).ready(function() {
$(document.body).on( "click", ".up_one" ,function() {
$x = $(this).siblings('.number');
$x.val(parseInt($x.val())+1);
});
});
Here's a fiddle that works with just adding HTML
If you want to modify the widget in the future you could just load the external html instead of creating it

Adding and removing dom sections with javascript

I want to be able to add new sections (via the 'add' link) and remove them (via the 'x' button) like seen in the image.
The HTML for the image:
<fieldset>
<legend>Legend</legend>
<div id="section0">
<input type="text" name="text1" value="Text1" />
<input type="text" name="text2" value="Text2" size='40' />
<input type="button" value="x" style="width: 26px" /><br />
</div>
add<br />
</fieldset>
I guess I could add new sections as needed (i.e. section1, section2) and delete those sections according to which button was pressed. There would be a javascript function that would inject sections in the DOM everytime the 'add' link was clicked and another for deleting a section everytime the 'x' button was clicked.
Since I have so little experience in HTML and Javascript I have no idea if this is a good/bad solution. So, my question is exactly that: Is this the right way to do it or is there a simpler/better one? Thanks.
P.S.: Feel free to answer with some sample code
Here's one way to do it:
<script type="text/javascript">
function newrow() {
document.getElementById("customTable").innerHTML += "<tr><td><input type='text'></td><td><input type='text'></td><td><button onclick='del(this)'>X</button></td></tr>";
}
function del(field) {
field.parentNode.parentNode.outerHTML = "";
}
</script>
<body onload="newrow()">
<fieldset>
<legend>Legend</legend>
<table>
<tbody id="customTable">
</tbody>
</table>
<button onclick="newrow()">Add</button>
</fieldset>
</body>
You could add IDs to them if you wanted, or you could call them by their position document.getElementsByTagName("input")[x].value The inputs would start at 0, so the left one is 0, right is 1, add row: left is 2, right is 3, etc.
If you delete one, the sequence isn't messed up (it re-evaluates each time), which is better than hard-coded IDs.
I just answered a nearly identical question only a few minutes ago here using jQuery: https://stackoverflow.com/a/10038635/816620 if you want to see how it worked there.
If you want plain javascript, that can be done like this.
HTML:
<div id="section0">
<input type="text" name="text1" value="Text1" />
<input type="text" name="text2" value="Text2" size='40' />
<input type="button" value="x" style="width: 26px" /><br />
</div>
add<br />
Javascript:
function addSection(where) {
var main = document.getElementById("section0");
var cntr = (main.datacntr || 0) + 1;
main.datacntr = cntr;
var clone = main.cloneNode(true);
clone.id = "section" + cntr;
where.parentNode.insertBefore(clone, where);
}​
Working demo: http://jsfiddle.net/jfriend00/TaNFz/
http://pastebin.com/QBMEJ2pq is a slightly longer but robust answer.

Categories

Resources