Accessing created DOM elements - javascript

I have code to create another "row" (div with inputs) on a button click. I am creating new input elements and everything works fine, however, I can't find a way to access these new elements.
Example: I have input element (name_1 below). Then I create another input element (name_2 below), by using the javascript's createElement function.
<input type='text' id='name_1' name="name_1" />
<input type='text' id='name_2' name="name_2" />
Again, I create the element fine, but I want to be able to access the value of name_2 after it has been created and modified by the user. Example: document.getElementById('name_2');
This doesn't work. How do I make the DOM recognize the new element? Is it possible?
My code sample (utilizing jQuery):
function addName(){
var parentDiv = document.createElement("div");
$(parentDiv).attr( "id", "lp_" + id );
var col1 = document.createElement("div");
var input1 = $( 'input[name="lp_name_1"]').clone(true);
$(input1).attr( "name", "lp_name_" + id );
$(col1).attr( "class", "span-4" );
$(col1).append( input1 );
$(parentDiv).append( col1 );
$('#main_div').append(parentDiv);
}
I have used both jQuery and JavaScript selectors. Example: $('#lp_2').html() returns null. So does document.getElementById('lp_2');

You have to create the element AND add it to the DOM using functions such as appendChild. See here for details.
My guess is that you called createElement() but never added it to your DOM hierarchy.

If it's properly added to the dom tree you will be able to query it with document.getElementById. However browser bugs may cause troubles, so use a JavaScript toolkit like jQuery that works around browser bugs.

var input1 = $( 'input[name="lp_name_1"]').clone(true);
The code you have posted does not indicate any element with that name attribute. Immediately before this part, you create an element with an id attribute that is similar, but you would use $("#lp_1") to select that, and even that will fail to work until you insert it into the document, which you do not do until afterwards.

var input1 = $( 'input[name="lp_name_1"]').clone(true);
should be
var input1 = $( 'input[#name="lp_name_1"]').clone(true);
Try that first, check that input1 actually returns something (maybe a debug statement of a sort), to make sure that's not the problem.
Edit: just been told that this is only true for older versions of JQuery, so please disregard my advice.

Thank you so much for your answers. After walking away and coming back to my code, I noticed that I had made a mistake. I had two functions which added the line in different ways. I was "100% sure" that I was calling the right one (the code example I posted), but alas, I was not.
For those also experiencing problems, I would say all the answers I received are a great start and I had used them for debugging, they will ensure the correctness of your code.
My code example was 100% correct for what I was needing, I just needed to call it. (Duh!)
Thanks again for all your help,
-Jamie

Related

How to change InnerHtml to an attribute

Can some one show how I can change the InnerHTML of the titles class to be the same as the alt attribute. For the actual website jarretonions.co.za
Thanks
$(document).ready(function() {
$(".pic").on("click", function() {
$(".modal").show();
var srclong = $(this).attr("src");
var srcshort = srclong.split("_");
var srcextension= srclong.split(".");
$(".modal img").attr("src", srcshort[0]+'.'+srcextension[1]);
************is it something like this********
var title = $(this).attr("alt");
$(".modal span").InnerHTML= title;
OR
document.getElementByClassName('titles').innerHTML = title;
})
+
echo
"<div class='art'>
<img class='pic' src='img/".$row["name"]."_tnail.jpg'
alt='".$row["name"]." • ".$row["year"]." • ".$row["type"]."'
height='auto' width='100%'/>
<div class='modal'>
<img class='big'/>
<span class='titles'></span>
</div>
</div>"
;
Since you're using JQuery, you can select those elements using $(".title") and change them directly. Something like so:
$(document).ready(function() {
$(".pic").on("click", function() {
$(".title").text( $(this).attr("alt") );
})});
Here's a fiddle: https://jsfiddle.net/wmjtfLja/1/
Note that if you have more than one element of class .title, they will all change. So you may want to select the title element by id or by relative path from the clicked image.
Realizing in advance, the danger of providing an answer that is not (superficially) fully aligned with the question, I was struck by the comment from melpomene, whom I initially thought was refering to things not existing in jquery.
melpomene is 100% correct, since getElementByClassName does not exist.
The correct syntax is getElementsByClassName.
Having said that, helloworld is also correct (syntax errors aside), since loading jquery for every little task is really redundent, and one can manipulate by class with little more half a dozen lines of pure javascript.
But, getting elements by class has dangers, since the return is a 'live' array.
For example, with dylan's original question, getting by class is only useful to return the first instance (the array length is just a guide of how many elemnts it applies to). Therefore, for dylan to make changes as he proposed, each requires its own button. (which also means, michael that I believe you are incorrect when you say it will affect all elements with same class name - oth, you are fully correct in noting that one should inpsect for other values (or change the class name) when running loops on the attribute).
Consider the following (on the fly class change);
function otf_cls_change(cls_original,cls_replace){
var a=document.getElementsByClassName(cls_original);
l=a.length;
if (l==0){return 0;}
do {
a[0].setAttribute('class',cls_replace);
a=document.getElementsByClassName(cls_original);
l=a.length;
} while (l>0);
}
This is effective for changing class names on the fly.
But, if we modify the code and
//change this a[0].setAttribute('class',cls_replace); // to
a[0].innerHTML='this_html';
It will cause the browser to hit an endless loop.
Why? because the live array returned by ElementByClass will only process the first item (even if you try to loop the array).
Therefore, while changing the class on the fly is fun and very do-able, I'd strongly suggest that using it to change any attrib that is not specific to the class id is a bad idea.
Changing the class attrib in conjunction with another attrib is fine.
For example,
a[0].innerHTML='this_html'; //do this first
a[0].setAttribute('class',cls_replace); //then this
The above will work to loop class defined elements.
On a point of massive personal hypocrisy, I do get annoyed when people ask for pure javascript solutions, and then some wing nut chimes in with jquery. I guess I'm doing the opposite here, since evidently, the question was jquery related, and here I am throwing out pure javascript. Sorry bout that.
btw, dylan, good luck with it. glad you bit back on the negative comment. Too many people here are terrified of offending, and wind up get bullied.
hth,
Gary

Change Spotfire Document Properties value using javascript

I want to Change the value assigned to a Document Property in spot fire. Lets say i have created a new document property called "Test1" as a string and assign it a value "a". Is there are way to change this value using Javascript every time i load the spotfire dashboard ?
I'm unaware of a way to use JavaScript for this, but you can assign a string document property via custom expression (if it's a List Box) or run an IronPython script each time the value changes. So, you could set the expression to the current date, datetimenow() and then every time it's loaded the IronPython script would fire. However, I don't see why you'd need the property control for this.
I suppose it really depends on what you want the document property to be set to. Is it data from your tables? Output from complex code? These are all things to consider.
1) Create an input type property control using the Document Property you want to change.
2) Edit Html to assign parent element an id say "testInput". And add the script as shown below in the Edit HTML window.
<span id="testInput"><SpotfireControl id="7db34e6c423240f59fc99e6b80fa23ec" /></span>
<script>
$("#testInput input").val("after");
$("#testInput input").focus();
$("#testInput input").blur();
</script>
3) This script will change the document property value to "after" whenever you open a file.
As you comment seemed to suggest, something you can do is write this code in Python and attach the script to an action control, e.i. a Link or a Button. Something simple like: Document.Properties["Test1"] = newValue
or even: Document.Properties[changingProperty] = newValue
allowing the code to be more reusable.
Then you insert Javascript into the Text Area as well to the effect of: $("#VeryLongSpotfireControlID").click();
Which should simulate clicking on action control, which in turn triggers the Python script to update the value. Just be careful not to use this approach when it would result in reloading the text area HTML, as this will re-trigger the Javascript, thus creating an endless loop.
I believe I have found a possible solution/work-around for the issue, entirely based on pure JavaScript (since TIBCO removed jQuery starting from Spotfire X). The solution is to force a simulated Enter Keystroke while focusing the input box to trigger updating the Document Property. (No data function and R needed)
HTML (SpotfireControl Element is an single line input-box for a Doc. Prop.):
<div id="container"><SpotfireControl id="b8534f13dc62416db6d4eaab16030f5e" /></div>
JS (focus and blur might no longer be needed for this solution, but I'm still keeping them just in case):
const inputConfirmationEvent = new KeyboardEvent("keypress", {
    keyCode: 13,
    bubbles: true,
    cancelable: false
});
var elem = document.querySelector("#container input");
elem.value = "stringValue";
elem.blur();
elem.focus();
document.querySelector("#container input").dispatchEvent(inputConfirmationEvent);
Hope it helps someone.
Best,
Aaron

Jquery, cannot access css properties of dynamically generated element

I am using jQuery to append elements to a div, and all works fine.
var new_div = $('<div>My stuff</div>');
new_div.appendTo("#container");
However, I'd like the div to appear by fading in, instead of abruptly.
I notice though that I get an error when I try to access graphic properties on my dynamically generated element. So this, for example fails:
new_div.hide().fadeIn();
The console reports the following error:
TypeError: jQuery.curCSS is not a function
Do I understand this correctly, that this fails because current css properties are not defined for the dynamically generated element? Or what else can be goingg wrong?
Important edit
Additional checking and working on this pointed out to a complete misunderstanding from my part. This has nothing to do with the fact that the element was dynamically generated. I got the same thing by calling fadeIn() on whatever element.
I sincerely apologize!
I still didn't get, though, why this happens
Adding elements to the DOM takes some time, miliseconds maybe, but it's still a reason for jquery not be able to find the element.
This process might be even slower if the DOM is a large html page.
Write your code like this:
var new_div = $('<div>My stuff</div>');
new_div.appendTo("#container");
setTimeout( function(){
new_div.hide().fadeIn();
} , 150); // 100 could be also good
It might be enough time for jquery to catch the element.
I would add an id to keep track of all elements I'm creating (just my preference, but it makes it easier to code it).
var new_div = '<div id="myNewDiv1" style="display:none;">My Styff</div>'
$('body').append(new_div);
$('#myNewDiv1').fadeIn();
It does seem to be a compatibility question, although I wasn't able to figure out exactly why and how to fix it.
Adding this code fixes the problem though:
jQuery.curCSS = function(element, prop, val) {
return jQuery(element).css(prop, val);
};

JavaScript setAttribute on another element

I have a problem to set an attribute on another element.
I'm using PHP code with JS and HTML and it looks like:
<textarea name='$id' id='$id' class='regular-text' cols='60' rows='1' tabindex='2'"
. "onkeypress =\"javascript:document.getElementById('content').setAttribute('onkeypress', document.getElementById('so_observer_heading_count').innerHTML = document.getElementById('content').value.length)\">$value</textarea>
You must know I have 2 elements. The first('content') one I use for writing a text and in the other one('so_observer_heading_count') there shall be updated the number of signs from the first element.
So my question is, how can I set an attribute on another element.
I have already checked that the name is correct and when i change the content of the textarea on the 2. element I get the right amount from the first element. But I want only to change content in the first element to refresh the amount.
And I don't want to change the code of the first element! And don't be confused by the textarea, in future this shall be a label or something else.
First of all:
Don't use the inline-eventbindings. Always use "real" javascript, (this way you also prevent the problem of escaping your quotes) this is far more cleaner and more maintanable.
Also you code has another problem: You have an eventhandler "keypress" on the textarea, which binds on every "keypress" another attribute to your content-element. This is not very performant and most likey won't work properly. This code should be everything you need:
document.getElementById('content').addEventListener("keyup",function(){
var obs = document.getElementById('so_observer_heading_count');
obs.innerHTML = this.value.length;
});​
Here is a demo for you.
Edit: I changed the event from keypress to keyup to 1) count properly 2) take charakter deletion into account.
I'd say "setAttribute" won't work on a method. Try instead :
document.getElementById('content').onkeypress = function() { document.getElementById('so_observer_heading_count').innerHTML = document.getElementById('content').value.length };
Well, there are certainly more.. efficient ways of doing this, but the thing you forgot to do was escape your single quotes, so the js treats your event as a string, instead of parsing the end result:
<textarea name='$id' id='$id' class='regular-text' cols='60' rows='1' tabindex='2'"
. "onkeypress =\"document.getElementById('content').setAttribute('onkeypress', 'document.getElementById(\'so_observer_heading_count\').innerHTML = document.getElementById(\'content\').value.length;')\">$value</textarea>
Elsewise.. I would personally do this through an included js file that executes the above line on document load/ready, versus every time a key is pressed.
Update: slight edit so anything I removed from your above code was added back, incase you want to just straight-copy it in.

How do I use JavaScript to grow an HTML form?

I'm creating a simple web application with which a user may author a message with attached files.
multiple html file inputs with javascript link http://img38.imageshack.us/img38/4474/attachments.gif
That "attach additional files" link does not yet work. It should add an additional file input control to the form each time it's clicked.
I need a JavaScript method addanotherfileinput() to replace the clicked anchor:
attach additional files
With this new table row, file input, and anchor:
<input type="file" name="Attachment1" id="Attachment1" class="textinput" />
</td>
</tr>
<tr>
<td></td>
<td>
attach additional files
And also increment the number: Attachment2, Attachment3, Attachment4, etc.
How can I do this?
You could use the DOM to dynamically insert the file inputs
var myTd = /* Get the td from the dom */
var myFile = document.createElement('INPUT');
myFile.type = 'file'
myFile.name = 'files' + i; // i is a var stored somewhere
i++;
myTd.appendChild(myFile);
OR you can use this
http://developer.yahoo.com/yui/examples/uploader/uploader-simple-button.html
You probably don't want to replace the anchor, just insert something in front of it.
I use Prototype for things like this, because it irons out a lot of browser inconsistencies, particularly around forms and tables.
Using Prototype, it would look something like this:
function insertFileField(element, index) {
element.insert({
before: "<input type='file' name='Attachment" + index + " class='textinput'>"
});
}
// And where you're hooking up your `a` element (`onclick` is very outdated,
// best to use unubtrustive JavaScript)
$('attachlink').observe('click', function(event) {
event.stop();
insertFileField(this, this.up('form').select('input[type=file]').length + 1);
});
...the bit at the end finds the form containing the link, finds out how many inputs of type file there are, and adds one for the index.
There are other ways as well, via the Element constructor provided by Prototype, but text works quite well (in fact, it's usually much faster).
It would be similar, though slightly different, with jQuery, MooTools, YUI, Glow, or any of the several other JavaScript frameworks.
There might be a better way, but I did this client side by creating a set of HTML form elements and then hiding/showing the rows using JavaScript to update the CSS class.
EDIT: I'll leave this here as an alternate method but I like the idea of adding INPUT elements through the DOM better.

Categories