I am starting a project that has been managed using a spreadsheet until now but needs to be converted to a mysql/php application. The amount of rows in the spreadsheet has exceeded something that can be easily sorted, filtered and edited.

A particular field has a weak entity that is not worthy of its own field in the database. It concatenates data from other fields in the same database record plus some arbitrary text. I want to display this concatenation in a textarea for each record. The application will display anywhere from 1 to 10 rows on a screen page. Each record is a table. Only the Command syntax is a form element, in this case textarea. All other record data is static text rendered by php. Below is a depiction of the web page and each record.

+------------------+-------------------------------------------------------------------------------+
| Record:          | 1                                                                             |
| FileName:        | This_is_a_file_name.mkv                                                       |
| Production Date: | 2010-02-28                                                                    | 
| Release Date:    | 2010-10-01                                                                    |
| Project ID:      | J0290                                                                         | 
| Command:         | mv /current_location/This_is_a_file_name.mkv \                                |
|                  |    /new_location/This_is_a_file_name-J0290-Prod_2010-02-28-Rel_2010-10-01.mkv |
+------------------+-------------------------------------------------------------------------------+

+------------------+-------------------------------------------------------------------------------+
| Record:          | 2                                                                             |
| FileName:        | Another_File_name.mkv                                                         |
| Production Date: | 2011-12-20                                                                    | 
| Release Date:    | 2012-03-15                                                                    |
| Project ID:      | H0500                                                                         | 
| Command:         | mv /current_location/Another_File_name.mkv \                                  |
|                  |    /new_location/Another_File_name-H0500-Prod_2011-12-20-Rel_2012-03-15.mkv   |
+------------------+-------------------------------------------------------------------------------+

In the mark-up, I plan something like

<textarea class="command">

</textarea>

I want to use Javascript on the textarea that renders the Command but am stuck getting started. Javascript is great for working with page and form elements when the DOM object is an id for an id has to be unique. But what about when the elements are a class?

On document ready, I want the javascript to fire and produce the command syntax for each record consecutively and without having to click on each command textarea to fire a javacript to render the command syntax.

Research I have done so far hasn't shown clear examples of gathering all the class objects on a page and traversing through them.

Can someone point me in the right direction for executing this project? Can it be accomplished with vanilla javascript or do I need a library like jQuery? I have a fair amount of experience at server-side php programming. I want this as a challenge to improve client-side programming skills.

Recommended Answers

All 11 Replies

You can do it in vanilla JavaScript if you want. There is a getElementsByClassName function, similar to the familiar getElementById, that returns an array of the elements with that class name.

Something along the lines of

var elements = document.getElementsByClassName("command");
for(var i = 0; i < elements.length; i++) {
  elements[i].innerHTML = "changed";
}

In jQuery the same action would be something like

$(".command").html("changed");

It's easier to do in jQuery, but marginally slower in terms of performance. It would depend on the rest of your JavaScript code whether or not it would be worth to use a library, but if this is the only part I wouldn't bother with it.

I am back to working on this project after a considerable hiatus working on other jobs. As in my original post, I am doing this project to expand the small amount of javascript skills I already have.

Consider the following as an example of data. I would have anywhere from 1 to 20 such forms on a page. This application is an expanded form of editing a database over simple columns along a row for the data is too wide at times to be visible on the width of a screen. As well, it is in a form for now for, eventually, I want to be able to edit the data using ajax in which clicking on a cell would become a form input.

This is an example of what I have designed based on research carried out so far. I am thinking it is the simplest based on my skill level and the precision it gives for drilling down through the DOM. If there is another way to do it that is simpler, I am open to it. Keep in mind though, I want to use vanilla javascript as much as possible for I plan on using jQuery for ajax I want to add later. I am not concerned about cross-browser compatibility. An admin tool, I only use most recent versions of Firefox or Chromium on Ubuntu.

<form id="row_105">
  <table id="table_105">
    <thead>
      <tr>...</tr>
    </thead>
    <tbody>
      <tr>
        <td id="show_105">
          show name
        </td>
        <td id="production_number">
          J0209
        </td>
        <td id="sement_105">
          01
        </td>
        <td id="production_date_105">
          2009-10-30
        </td>
        <td id="release_date">
          2010-01-15
        </td>
      </tr>
      <tr>
        <td id="id_105">
          105    //record id from database which serves as numeric part of all id's listed in a form
        </td>
      </tr>
      <tr>
        <td id="filename_105">
          A_File_name
        </td>
      </tr>
      <tr>
        <td id="speaker_105">
          Brad Roberts
        </td>
      </tr>
      <tr>
        <td>
          <textarea onload="genCommand(105)" data-no="105" id="textarea_105" name="command_105">
            Want to concatenate the data from the id's above *_105 here, plus some static text  
          </textarea>
        </td>
      </tr>
    </tbody>
  </table>
</form>

I am having a challenge figuring out exactly how a function would fire. I want the concatenated text in the textarea to update when the page loads or is refreshed. As my example above indicates, I considered using an onload attribute to fire the javascript function but research indicates that is only available for <body>, <frame>, <frameset>, <iframe>, <img>, <input type="image">, <link>, <script> and <style>. How can I have the concatenations up-to-date without clicking on a button beside each textarea?

A method I have already planned for a bit would be for the value in data-no be passed to the javascript function. Will something like below work for each textarea above up to how many unique textareas are on the page? If onload is not available, then how would I pass data-no value to the javascript?

<script type="text/javascript" >
function genCommand (n) {
    syntax for concatenating data from the above id's to come after getting these questions answered 
}
</script>

Given something like this :

var filename = getElementById("filename_105");

is required, how do I build the string in the function so the above syntax is correct? Will this work?

<script type="text/javascript" >
function genCommand (n) {
    fname = "filename_"+ n;
    var filename = getElementById(fname);
}
</script>

Thanks for taking the time to read this.

Member Avatar for diafol

If you are going to implement jQuery to deal with ajax, then I'm not sure why you wouldn't leverage jQuery's other convenient features. Seems a bit wasteful to include a whole library just for that. If, as you say, you are trying to develop your vanilla js skills, fine, I can see the logic, but for building an app (quickly), it doesn't make much sense.

Member Avatar for diafol

Will this work?

You wrote it, but you didn't try it?

Millions of ways of doing it though.

Not sure I'd specifically name each item like this - Use jQuery .closest('tr').children('td') get the content. Or use .siblings() Depends how you want to call it too.

@diafol

Thank you for your second reply. Yes, I did try it.

HTML:

<td colspan="5" data-id="1">
    <textarea id="textarea_1" onload="genCommand(1)" class="command" name="command"></textarea>
 </td>

Js:

function genCommand(dbrow) {
    console.log(dbrow);
    var message = 'test ' + dbrow;
    var target  = 'textara_' + dbrow;
    document.getElementById(target).value = message;
}

I loaded the browser and set a breakpoint in the debugger on the first line, then reloaded. The script does not fire. No pause by the debugger. No messages of syntax error in the console. No iteration of dbrow in the console. All textareas on the page are empty.

Line 4 textara_ is that how it is in the actual source code, or just a copy error?

@JamesCherrill

It is a typo. Correction: copy error. It was valid in the source.

The browser is not even getting to that line. As stated above, the console.log value does not show and no errors are showing in the console.

@diafol

Millions of ways of doing it though.

Can you show just one?

Since onload is not available, the challenge comes back to how do I initiate a function that will look at all form tags, for example, and read all data-id atrributes so I have an array I can loop through?

If I can form an array of all the database row numbers stashed in each data-id, I can grab the sets of id's, no?

Member Avatar for diafol

Ok something like this... (quick nonsense - but gives you an idea):

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Page Title</title>
</head>
<body>
<form>
    <table>
        <thead>
            <tr>
                <th>Heading 1</th>
                <th>Heading 2</th>
                <th>Heading 3</th>
                <th>Heading 4</th>
                <th>Heading 5</th>
                <th>Actions</th>
            </tr>
        </thead>
        <tbody id="tabledata">
            <tr data-id="1">
                <td class="field1">SomeInfo11</td>
                <td class="field2">SomeInfo12</td>
                <td class="field3">SomeInfo13</td>
                <td class="field4">SomeInfo14</td>
                <td class="field5">
                    <textarea class="updatable">BOO</textarea>
                </td>
                <td class="actions">
                    <button class="update_row">Update</button>
                    <button class="delete_row">Delete</button>
                </td>
            </tr>
            <tr data-id="2">
                <td class="field1">SomeInfo21</td>
                <td class="field2">SomeInfo22</td>
                <td class="field3">SomeInfo23</td>
                <td class="field4">SomeInfo24</td>
                <td class="field5">
                    <textarea class="updatable"></textarea>
                </td>
                <td class="actions">
                    <button class="update_row">Update</button>
                    <button class="delete_row">Delete</button>
                </td>
            </tr>
            <tr data-id="3">
                <td class="field1">SomeInfo31</td>
                <td class="field2">SomeInfo32</td>
                <td class="field3">SomeInfo33</td>
                <td class="field4">SomeInfo34</td>
                <td class="field5">
                    <textarea class="updatable"></textarea>
                </td>
                <td class="actions">
                    <button class="update_row">Update</button>
                    <button class="delete_row">Delete</button>
                </td>
            </tr>
        </tbody>
    </table>
</form>
<script>
    function loadAll(targetField){
        var tablebody = document.getElementById('tabledata');
        var concatField = targetField - 1;
        for (var i = 0, row; row = tablebody.rows[i]; i++) {
            var str = [];
            var tx = row.cells[concatField].children[0];
            for (var j = 0, col; col = row.cells[j]; j++) {
                if(j < concatField) {
                    str[j] = col.innerHTML;
                } else{
                    break;
                }
            }
            tx.innerHTML = str.join('_');
        }
    }
    loadAll(5); // 5 = fifth column being the one you want to fill
</script>
</body>
</html>

@diafol

Thank you for the reply. Your example did not address a key requirement: I have more than one table. From my post earlier this week:

Consider the following as an example of data. I would have anywhere from 1 to 20 such forms on a page.

Your structure of:

    function loadAll(targetField){
    ...
    }
    loadAll(5);

helped to solve the question of how to invoke the javascript. It may not be pretty and at this time probably clumsy but this is what I put together. The exact data model has changed from my earlier posts but this is the abbreviated gist of it:

HTML

<table data-dbrow="20">
    <tr>
        <td id="show_20"></td>
        <td id="production_number_20"></td>
        <td id="segment_20"></td>
        <td id="production_date_20"></td>
        <td id="release_date_20"></td>
    </tr>
</table>

The value held in the attribute data-dbrow could be anything from 1 to 800+

JS

function genCommand() {
    var tableArray              = [];
    var tableArray              = document.getElementsByClassName('tuple');
    for (var i = 0; i < tableArray.length; i++) {
         var x                  = tableArray[i].getAttribute('data-dbrow');
         var show               = document.getElementById('show_' + x).innerHTML;
         var production_number  = document.getElementById('production_number_' + x).innerHTML;
         var segment            = document.getElementById('segment_' + x).innerHTML;
         var production_date    = document.getElementById('production_date_' + x).innerHTML;
         var release_date       = document.getElementById('release_date_' + x).innerHTML;
         var record             = document.getElementById('record_' + x).innerHTML;
         var filename_in        = document.getElementById('filename_in_' + x).innerHTML;
         var models_or_title    = document.getElementById('models_or_title_' + x).innerHTML;
         var link_path          = document.getElementById('link_path_' + x).innerHTML;
    }
}
genCommand();

I am working on defining the many variables in an array that will be looped to define them. The key part is I now have a method to loop the 1-10 or 20 tables on a page and can retrieve the data held in each of the id's to massage and manipulate in a table's textarea as in my models stated above.

Thanks for your help. :-)

Member Avatar for diafol

Give the tables a common classname and loop on that

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.