Multiple appendChild calls don't work - javascript

I read through several threads without find a clear answer.
I'm using a JavaScript library (Drinks.js) to put several widgets on my webpage.
The following code will add one single item to my div element pnlThermo:
function create(item) {
var thermo = Drinks.createElement('display');
thermo.setAttribute('id', item);
thermo.setAttribute('label', item);
Drinks.appendChild('pnlThermo', thermo);
}
Well, now I want to add several items to the same div element. No matter if I use a for cycle or call the function explicitly only the first item will be rendered. For example:
create('T1');
create('T2');
create('T3');
leads to show T1 only.
Perhaps I missed something, I'm quite new to JavaScript programming.
Thanks in advanced.

The reference manual ( http://goincompany.com/DTManual01.pdf ) says :
After you have created the HTML element, you have to append it to an
HTML container. In order to do this you have to use the appendChild
function, provided by the Drinks class. Drinks.appendChild('body',
gauge); 'body' is the id of the HTML container. If the parent is an
instrument, this function doesn't work. We have to use the appendChild
method of the instrument, but we'll see this later.
Seems to imply that the first parameter needs to be an HTML tagname, which makes little sense
but then the library is a little wierd IMHO.

Related

Applying a javascript function on a div

I want to put a variable on a div and to be applied and inherited by all the dojo widgets under this div.
Is this feasible ?
For example
<div shaper="Contextual">
<textarea ..../>
<select multiple data-dojo-type="dijit/form/MultiSelect">
....
</div>
I want the functionality supported by the shaper to be applied to all the widgets included in the div.
p.s.: "shaper" is a custom module created to do numeric shaping for Arabic numbers.
It's possible, but not out of the box.
You can write something like this:
require(["dojo/query", "dojo/domReady!"], function(query) {
query("[shaper]").forEach(function(shaper) {
});
});
This will query all elements with a shaper attribute and loop over it. Inside the loop, you will have to retrieve the value of the shaper attribute (for example Contextual), you can do that with the getAttribute() function, for example:
var shaperModule = shaper.getAttribute("shaper");
Now you have the name of the module to load, so you can write something like this inside the loop:
require([shaperModule], function(shaperModule) {
});
This will use AMD to retrieve the Contextual module. Now all that's left is to include the shaper functionality into all widgets inside your <div>.
First of all, with dijit/registry::findWidgets() you can retrieve all widgets inside a specific DOM node, you can use this to retrieve your dijit/form/MultiSelect widget in this case:
registry.findWidgets(shaper);
Then you can loop over the array of widgets that are found and use dojo/_base/lang::mixin() to extend an object with the contents of another object, for example:
registry.findWidgets(shaper).forEach(function(widget) {
lang.mixin(widget, shaperModule);
});
For example: http://jsfiddle.net/zLv7cvzt/
Though this might not work entirely (what if the module does not exist or what about widgets inside widgets, which dijit/registry::byId() does not detect), it does give you an idea of how to achieve it.
To answer your second question, if it's feasible or not, I would say that it depends. If you extend a widget with another widget like this, it could really end up with really weird things, because all widgets extend from dijit/_WidgetBase, which provides the widget lifecycle, you could mix both widgets their lifecycle.
Also, if you end up doing this and you get an error, it will be really hard to debug this if you're not familiar with the custom code.

Accessing Objects inside HTML Object with JS

I am creating an array of div tags inside the player table div. I'm getting all div tags with class .players. The divs with class name .players have input fieds and a link field inside. I want to be able to manipulate these (remove, add class, etc...)
What I thought would work would be something like:
$(divarray[j]+' .link').hide();
$(divarray[j]+' a').remove('.link');
But it's not working. Any thoughts? I'm sure it's something simple but it's my first time at JS :)
var divarray = $('#player-table > .players');
for( var j = 0; j < 10; j++){
$(divarray[j]).removeClass("players");
$(divarray[j]).addClass("selected_players");
$('#debug').append(divarray[j]);
$(divarray[j]+' a').hide();
}
First of all, you cannot just concatenate jQuery objects or DOM nodes with strings to create new selectors. jQuery provides methods for this kind of situations, where you already have an object or DOM node and want to find other related nodes.
Second, with jQuery there are much better ways to process a set of elements. Here is your code in more jQuery-like way. This is just an example, because I don't know the HTML structure. You have to adjust it so that it selects and applies to the correct elements.
$('#player-table > .players').slice(0,10) // gets the first 10 elements
.removeClass("players") // removes the class from all of them
.addClass("selected_players") // adds the class
.find('a').hide().end() // finds all descendant links and hides them
.appendTo('#debug'); // appends all elements to `#debug`
As you maybe see, there is only one semicolon at the last line. That means this whole code block is just one statement, but splitting it up over several lines increases readability.
It works because of the fluent interface, a concept which jQuery heavily makes use of. It lets you avoid creating jQuery objects over and over again, like you do ($(divarray[j])).
Another advantage is that you can work on the whole set of elements at once and don't have to iterate over every element explicitly like you have to do with "normal" DOM manipulation methods.
For learning JavaScript, I recommend the MDN JavaScript Guide.
jQuery has a couple of tutorials and a very good API documentation.
Read them thoroughly to understand the basics. You cannot expect to be able to use a tool without reading its instructions first.
Try this istructions
$(divarray[j]).find('.link').hide();
$(divarray[j]).find('a').remove('.link');
Try also
$(divarray[j]).find('.link:first').hide();
If you need to work only on the first element
Hope it helps

Rapid repeated traversing within a div

I have a number of divs, each of which contain an instance of a number of different items, each with their own unique classes and/or ids.
A lot of .js code applies to the elements within each of these parent divs, and my .js is getting bloated by the constant need to do things like:
// Stuff like this occurs 15-20 times for similar but different actions
$(this).parent().nextAll('.target').eq(0).find('.toggle').slideToggle();
$(this).next('.alert').html('Success');
In the context of the document, I see why this code is necessary. However, I feel that if I were only able to redefine the reference point as being the parent div instead of the whole document, I could replace the convoluted code above with the MUCH easier:
function keepingCodeWithinParentDiv(){
$('.toggle').slideToggle();
$('.alert').html('Success');
}
So, is there a way to say in Javascript: for this part nothing exists outside this div?
If you have a parent element (let's name it element) that you want to confine your jQuery selector operations to, you can just pass it as a context to any jQuery select:
$(".toggle", element).slideToggle();
See jQuery doc for more info.
If you show us your actual HTML and describe what you're trying to get, we could give more specific advice.

JQuery remove images

I'm curious if anyone knows why this piece of jQuery code doesn't remove the images?
var a = $('#tblMain').clone().remove('img');
The table is being selected. This is trying to take the table on the webpage and export to excel but I do not want the images to export.
Thank you,
Do it like this:
$("#tblMain").clone().find("img").remove();
EDIT: Okay, here's the problem:
selector: A selector expression that
filters the set of matched elements to
be removed.
http://api.jquery.com/remove/
The img in .remove('img') is to filter the set of items in the jquery object, NOT to find elements within the items themselves. In this case, the jquery object contains only one item, the cloned table. Therefore, .remove('img') removes nothing, since the jquery object does not contain any images (only images within items it contains).
I don't know what's happening behind the scenes, but you're referring to some variable called img whilst you most probably just want to select all img elements. In that case, you ought to use a selector as a string:
var a = $('#tblMain').clone().remove('img');
EDIT: .clone.remove does not seem to work indeed. I used this workaround which actually works:
.find('img').each(function() {$(this).remove()});

Complex jquery selection that also involves custom xml tags

I want to write a select something like...
#window_4 > content > p:eq(0)
I think I have this correct, but I have a few selectors that are all similar but I can't test them all at once.
Am I right in saying this is selecting an element, who is the fist p tag child of a content tag that is a child of a tag with id 'window_4'
If I have gotten this wrong, can you give me some pointers. Would love to be able to simplify this code, I have more code selecting the tag I am after then actually doing stuff with them.
Looks good to me, although you can make it a bit more readable by substituting p:eq(0) for p:first.
Edit for comment:
jQuery always returns an array of elements, no matter whether 0, 1 or many elements were found. On these elements, yes, you can perform JS functions, such as innerHTML. You can access each element returned by jQuery just as if you would any other array:
$(".red")[0].innerHTML = "Glen Crawford";
More info: http://groups.google.com/group/jquery-ui/browse_thread/thread/34551a757f139ae1/20111f82c2596426

Categories

Resources