How can I use Object Oriented Javascript to interact with HTML Objects - javascript

I am very new to object orientated javascript, with experience writing gui's in python and java. I am trying to create html tables that I can place in locations throughout a webpage. Each html table would have two css layouts that control if it is selected or not. I can write all of the interaction if I only have one table. It gets confusing when I have multiple tables. I am wondering how to place these tables throughout a blank webpage and then access the tables individually. I think I am having trouble understanding how inheritance and hierarchy works in javascript/html.
NOTE: I am not asking how to make a table. I am trying to dynamically create multiple tables and place them throughout a webpage. Then access their css independently and change it (move them to different locations or change the way the look, independently of the other tables).

Assuming you want to make changes in real-time and you're willing to use a library like jQuery, simply append the table(s) to the document and give each one a unique CSS id. Wherever your table generation code is taking place, just keep a counter and set the id to something like "mytable+counter_val".
From there you can reference each table and use jQuery methods to adjust the CSS to your liking.
A brief example:
var container_id = "#the_parent";
for (var i = 0; i < 10; ++i) {
var table_id = "mytable_" + i;
var table_code = "<table id=" + table_id + "></table>";
$(container_id).append(table_code);
}
// set border on table 7 (indexing at 0)
$("#mytable_6").css("border", "5px solid red");
// move table 5 (indexing at 0)
$("#mytable_4").css("top", "300px");
// animate table 2 (indexing at 0)
$("#mytable_1").animate({left : 300, top: 125}, 2000);
If you have the difference between selected and unselected separated into a single class, you can just add/remove that class:
// table 2 is now displayed as being selected
$("#mytable_1").addClass("selected");
// table 2 is now displayed as being unselected
$("#mytable_1").removeClass("selected");
See the jQuery docs for more information: http://docs.jquery.com/Main_Page

i don't understand the need of oop principles in your problem. why do you need inheritance and hierarchy for generating couple of elements and then alter some of their props?
if i understood corectly, you would want to keep track of each table you create so you can later change it's css props.
if you want to use js as an object oriented language, i would write a class definition for a table object :
var Table = function(innerHTML,container){
this.innerHTML = innerHTML;
this.container = container;
}
//static member
Table.TABLES = [];//global reference to all the tables created
Table.prototype = {
init : function(){
this.dom = document.createElement('table');
this.dom.innerHTML = this.innerHTML;
this.container.append(this.dom);
Table.TABLES.add(this);
},
setCssProp : function(name,value){
this.dom.style.setProperty(name,value);
}
}
and then all you have to do is create a new table and initiate it :
(new Table(table_content_here)).init();,
and later on you can reference it by accesing the TABLES in Table class :
for (var i in Table.TABLES)
Table.TABLES[i].setCssProp(cssName,cssValue);
i know that you know how to create tables, i was just suggesting that you keep a global reference to the ones you create to have acces to them later.

Related

Dynamically insert id into table element

I’m working on what I thought would be a simple project but is something I’m struggling with. I’m wondering if someone could review what I’m trying to do and give me some pointers on how to proceed.
The concept here is fairly simple...I thought - identify each table in an html file based on the "table" element, count the number of rows in each table and if the table has more than 10 rows, dynamically create a unique id for the table.
I know how to do all this (for the most part) but it doesn’t respond how I anticipate.
Here’s my initial javascript code attempt to dynamically create and insert the unique table id’s:
/* This function dynamically sets a unique id to each table found in the html page: */
function set_table_id(){
var num_tables = document.getElementsByTagName("table"); //determine the number of “table” nodes in the html
//alert("set_table_id function: The total number of table elements are: " + num_tables.length);
if (num_tables) { //if one or more table nodes are found…
var id_name = "dataTbl_"; // create the prepend string for table id value
var n = 1;
var i;
//for each table node found…
for (i=0; i < num_tables.length; i++) {
var id_name_new = id_name + n; //create the next unique table id from the prepend string
n++;
num_tables[i].id = id_name_new; //apply the latest table id to the current table
//this will be the call to the function to apply the datatables javascript to each table that has more than 10 rows:
//num_tables[i].dataTable();
}
}
}
When I run the above js code there are no errors when I review the Inspect Element Console, but the unique id’s never get inserted into the table elements.
This should run through the html code, identify each table and dynamically apply (insert) a unique id to each table but it's not.
Any help is greatly appreciated.
This jQuery selector will find all tables that have 10 or more <tr> children and apply the ID and DataTables to each.
$(document).ready(function() {
$("table > tbody > tr:nth-child(10)").closest("table").each(function(index) {
var tableId = "dataTbl_" + (index + 1); //index is zero-based, so add 1
$(this).attr("id", tableId); //set the ID attribute
$(this).dataTable();
}
);
});
Heres is a JSFiddle, based on the on in your comment, which demonstrates it:
https://jsfiddle.net/5cgbdLzt/2/
Within that fiddle, I added a button that will alert the IDs to you, where you can see clearly that the ID of the table with fewer than 10 rows has an ID that is undefined.
Note: DataTables uses jQuery as a dependency, so it's assumed you can use jQuery selectors rather than strictly vanilla JS.

Sending appropriate input to plugin

I am using a third party javascript plugin to develop a two-column table functionality as per my requirements. The plugin accepts an input json array which looks something like the following:
var data = {"Project" : [{'Start':'02/20/2012',
'End':'02/20/2012',
'Content':'Project Description',
'Group' : 'Table Group 1'
},...
] };
Group in the above json when used in the plugin can be given any type of content (custom html content as well) which it renders internally as:
var items = []; //json array items will be pushed by items.push from input `data` json
for(var i=0,im = items.length;i<im;i++){
var group = items[i].Group;
groupDiv.innerHtml = group;
}
In my case, to the Group item of the json array item, I am passing a custom HTML which looks like the following:
var customHtml = '<div><span class="button-red"></span>'+
'<div class = "quick-info-hide">' +
'Some Custom Content from input' +
'</div></div>'
I am generating this customHtml from some input (another larger json) and sending it to the plugin and was trying not to modify the plugin itself. However, I had to modify the plugin to add a certain functionality here (row expansion on/off) which is kind of troubling me now.
When the row is not expanded, customHtml's span and div should have class style1, and if it expanded, customHtml's span and div should have class style2.
However, inside the plugin, customHtml is assigned without any if condition of expansion/collapse. Since the plugin was not built with a logic of row expansion/collapse on click, it wasn't expected to do so as well. I want to change the styles here on expansion/collapse to assign to groupDiv.innerHtml i.e customHtml which probably can be done by another variation of customHtml1 which will have different styles.
What is the best approach to do this?
Should I add an if condition here and send two variations of customHtml in the plugin and apply the suitable one on respective if condition? Is there a better method as well in this case to not spoil the generic approach of the plugin (which I seem to be doing here with modification)?

jQuery break out of table

I have a standard HTML formatted table, that dynamically generates the content, via Zend Framework. From which I have an issue altering the form internally PHP side. So I need to alter the tables appearance somehow. With that on the occasion I have an element show up in one of the rows and when this element shows up I want to break out of the table and then do something after it then start the table again.
Basically I want to inject the equivlant of
</tbody></table>/*other stuff*/<table><tbody> after the row containing the one element I seek which in this case is a label.
I tried $("label[for='theLable']").parents('tr').after('</tbody></table><br><table><tbody>') which appears to ignore the ending table parts add the br, and then does a complete open/close tag for table and tbody within the same table I am trying to break out of so inbetween tr tags basically it adds this new table
Whats the best way to approach this concept?
update with jsfiddle link
http://jsfiddle.net/cPWDh/
You can't really modify the HTML of the document the way you're thinking, since it's not a legitimate way to alter the DOM.
Instead, I would create a new table and .append the rows you want to move to it, which will automatically move them from their current location (instead of copying them):
$(document).ready(function() {
var $trow = $('label[for="specialLabel"]').closest('tr'),
$table = $trow.closest('table');
$('<table>').append( $trow.nextAll().andSelf() ).insertAfter($table);
});​
http://jsfiddle.net/cPWDh/1/
this approach won't work in js. What you could do if the table has not too many rows is this:
var nextTable = $("table").after("/*other stuff*/<table id="nextTable"></table>");
//now you loop over the lines of your original table that you want to have after the "break", and move them to the nextTable:
var before = true;
$("table tr").each(function(){
if ($(this).has("[for='theLable']")) {
before = false;
}
if (!before) {
nextTable.append($(this));
}
});

Tree Menu? In JS?

I need a tree menu. But instead of a listview where you expand/collapse i need a dropdown box with the list and when you click on a element i need the box to update (with the first entry being 'Back') so the menu stays in a neat little dialog.
Does this menu have a name? Does anyone know where i can get code to do this?
I can think of several jQuery plugins which would soot your purposes. However, I would recommend jQuery iPod Style Drilldown Menu (Newer Version), which is exactly what it sounds like. The dropdown box updates in place, uses a cool sideways slide animation, and includes a "Back" button (as you desired). Finally, if you don't want any animation, you can try tweaking the plugin's many options. Setting crossSpeed to 0 may work, for example.
Adam is right, jQuery offers an assortment of menu's which you could use. Really though, this is a somewhat trivial problem, the code to write it would take up about 1/10th the space that jQuery's code will. So if possible I would say write it without jQuery.
The most effective method would be to do it JS OOP (Javascript Object-Oriented), but understandably this is a confusing topic.
Basically you just want something like:
function drillDown(){
//Any code that multiple drilldowns
// might need on the same page goes here
//Every instance of a drillDown will
// instantiate a new set of all functions/variables
// which are contained here
//A reference to the parent node the dropdown is placed in
this.parent;
//A reference to the div the dropdown is incased in
this.object;
//Returns a reference to this object so it can be
// stored/referenced from a variable in it's
// superclass
return this;
}
//Prototype Functions
//prototypes are shared by all
// instances so as to not double up code
//this function will build the dropdown
drillDown.prototype.build = function(parent){
//Too lazy to write all this, but build a div and your select box
// Add the select box to the div,
// Add the div to the parent (which is in your document somewhere)
var divEle = document.createElement('div');
var inputBox = document.createElement('input');
//code code code
divEle.appendChild(inputBox);
parent.appendChild(divEle);
}
//this function loads the newest dataset of
drillDown.prototype.loadNewDataSet = function(data){
//first clear out the old list
// remember we have a reference to both the
// 'object' and 'parent' by using
// this.object and this.parent
//load the data, we are going to use the text from
// the select boxes to load each new dataset, woo eval();
// If you didn't know, eval() turns a string into JS code,
// in this case referencing an array somewhere
var dataSet = eval(data);
//then loop through your list adding each new item
for(item in dataSet){
//add item to the list
//change the .onClick() of each one to load the next data set
// a la ->
selectItem.onClick = function(){this.loadNewDataSet(item);};
//if you name your datasets intelligently,
// say a bunch of arrays named for their respective selectors,
// this is mad easy
}
}
//Then you can just build it
var drillDownBox = new drillDown();
drillDownBox.build(document.getElementsByTagName('body')[0]);
drillDownBox.loadNewDataSet("start");
//assuming your first dataset array is named "start",
// it should just go
And by the way, Adam also said it, but wasn't explicit, this is refered to as a drill-down.

clone table row

How can i use javascript (i assume) to clone a table row like ive beautifully illustrated in the picture below?
You can hookup a live event to all the buttons. If you give them a class of clone for instance the following will work.
$('input.clone').live('click', function(){
//put jquery this context into a var
var $btn = $(this);
//use .closest() to navigate from the buttno to the closest row and clone it
var $clonedRow = $btn.closest('tr').clone();
//append the cloned row to end of the table
//clean ids if you need to
$clonedRow.find('*').andSelf().filter('[id]').each( function(){
//clear id or change to something else
this.id += '_clone';
});
//finally append new row to end of table
$btn.closest('tbody').append( $clonedRow );
});
Please Note:
If you have elements in the table row with id's you will need to do a .each through them and set them to a new value otherwise you will end up with duplicate id's in the dom which is not valid and can play havoc with jQuery selectors
You can do this like so
If you want a really simple solution, just use innerHTML:
var html = document.getElementById("the row").innerHTML;
var row = document.createElement('p');
row.innerHTML= html;
document.getElementById("table id").appendChild(row);
For what purpose do you want to use the data? I've done similar things previously on data input forms and generally I've found it to be beneficial to the users not to manipulate everything in Javascript but to hook to store the data on the server and interface with AJAX.
The issue is that as soon as you start letting users do this sort of complex table manipulation and they accidentally hit the back button you end up with a lot of disgruntled punters. Coding up transient storage on a database isn't that much harder than manipulating Javascript and in fact can be easier as you can break the operations down more easily. Debugging is simpler for that reason too (you always have inspect access to the current state of your table).
Lots of option for handling via AJAX - the simplest being to just use a place-holder division and feed the whole table structure in as needed.
A jQuery example:
$(document).ready(function(){
$('TABLE.recs').delegate('INPUT.clone','click',function(e){
e.preventDefault();
var s = $(this).parent().parent().clone().wrap('<div>').parent().html();
$('TABLE.recs TBODY TR:last').after(s);
});
});

Categories

Resources