1

The website I am working on needs to have dynamic labels, for example: If the webpage is listing the authors of a particular book (with more than one author) it would look like this: Author 1: Nikola Tesla [Remove] Author 2: Elon Musk [Remove] Author 3: Alan Turing [Remove]

(note that [Remove]in this case is a button that removes the particular person as a author.)

My problem is this, let's say I removed Elon Musk as an author the label for Turing should now change to reflect that (would become Author 2).

I've tried a couple different things using client side JavaScript (as the solution needs to work without refreshing the page or any postbacks) but I couldn't get close to a working solution myself, my logic seems to be off or limited by my lack of experiance in web dev.. I haven't done much Web Dev at all so I'm really learning as I'm going. The solution would also need to work in the case of the user adding a new author to the book.

Edit: The authors are NOT stored in a table but rather just listed using labels. This (due to things out of my control) cannot be changed.

Edit 2: Here is the code I believe is relevant let me know if anything else is needed.
<div ID='dvAuthor" + i.ToString + "' class='form-group'><div class='col-sm-4 control-label'>

An added twist is that that is on the server side and it replaces a placeholder when the author is added (this means when an author is added that page does refresh -- this is fine, but removing should not require the same). Even more fun is that we're not using JQuery!

The i.ToString is just an integer that is added so that the author's ID is numbered, ex dvAuthor0 and so on.

Edit 3: Reply to @Basic

Okay that clears things up a bit. The div for the author's label is coming from the server (i.e. each time an author is added the page refreshes and the client now has the newly added author presented to them.) So I guess my question is, how would I loop through the div's on the client, or even better could I loop through each author's div and just grab their IDs if I don't know exactly how many authors are on the page? Would it be something like this while(hasNextAuthor) {add author ID to array} Sorry for all the questions, I'm really new to Web Dev stuff, I am trying my best.

Also, I don't need to worry about removing the authors from the webpage, I have a function that does that already (both in the client side and on the server). The numbering is the only thing that needs to be done and it really is only cosmetic, the current numbering system works okay but does not dynamically change the numbering as the user removes authors, but rather waits until the user selects save and then reloads the page with correct numbering.

Edit 4: I think I have a way I can get this done, I just have one hang up... How can I get the number of authors on the webpage from the client side? Is their a way in JavaScript where I can loop through and see how many divs are created for the webpage?

10
  • 1
    Post some of the actual code! :D Commented May 11, 2015 at 20:09
  • If you post your HTML and current JavaScript I'll expand my answer to do exactly what you need it to. At the moment it would work if you applied the same concept. Commented May 11, 2015 at 20:21
  • @VulgarBinary I've asked my superiors for permission to post edited code examples, I will most likely have a response tomorrow morning (work day is finishing here). (The program is high security). I will make sure to provide examples in the future at the time of posting my question, sorry about the delay. But thanks for the help you've provided so far. Commented May 11, 2015 at 20:45
  • No worries, the concept I've posted below should at least get you on the right track if you cannot post your code. The ID of the element itself shouldn't really matter, you just need to get all the #'s for the author and renumber them on each remove. The actual remove link I'm guessing links to an actual ID (uuid or whatever) that calls your .NET. If this is purely cosmetic, something along the lines of what I already posted should point you in the right direction. :-) I'll check back tomorrow. Commented May 11, 2015 at 20:47
  • Considering the lack of postback and database storage, I'm kind of curious what happens after you press your remove button. As in, once you make your list sorted like you want, what does your page do? Commented May 11, 2015 at 21:16

3 Answers 3

1

There are libraries available which do templating through JavaScript. Knockout is a good one, which you can learn more about here: http://knockoutjs.com/documentation/template-binding.html ...and see a good example here: https://www.devbridge.com/articles/knockout-a-real-world-example/

Using Knockout, you basically create a client-side ViewModel and an observable array of authors. They can then be bound to template HTML UI, which interacts with the ViewModel until it's time to save it back.

Re-binding should be of little concern using that library.

Sign up to request clarification or add additional context in comments.

Comments

0

Original JQuery Solution

You can use an array with odd numbered indexes and bind to it. That way you can account for missing indexes.

There is an older stackoverflow article here that answers your question.

It amounts to specifying the index of each element along with the input value:

<input type="hidden" name="Author.Index" value="3" />

If you are purely looking to make the text pretty you can do:

<div id="author_1" class="author-container">Author <span class="authors" data-index="1">1</span>: First Last <a ..>[Remove]</a></div>

Then in JavaScript you can do (Assuming JQuery):

function UpdateIndexes()
{
   var idx = 1;
   $(".authors").each(function(el){
      $(this).text(idx);
      idx++;
   });
}

$(function(){
    $(".whateverRemoveSelector").on("click", function(){
      $(this).parents(".author-container").remove();
      UpdateIndexes();
   });
})

Just JavaScript Solution

I tried to keep the variable names vanilla enough to make this easy to follow. This does both creation from the author's array, wiring the remove event, as well as renumbering the author's.

Hopefully this solves what you need to do!

var authors = [
  { Name: "J.K. Rowling" },
  { Name: "Orson Scott Card" },
  { Name: "Stephen King" },
  { Name: "Nicholas Sparks" }
];

/*
<div ID='dvAuthor" + i.ToString + "' class='form-group'><div class='col-sm-4 control-label'>
*/

function Remove(){
  var e = event.target.parentNode.parentNode;  
  e.parentNode.removeChild(e);
  
  var numbers = document.getElementsByClassName("sel-author-number");
  for(var i = 0; i < numbers.length; i++){
    var number = numbers[i];
    number.innerHTML = i+1;
  }
}

window.onload = function(){
  var authors = [
    { Name: "J.K. Rowling" },
    { Name: "Orson Scott Card" },
    { Name: "Stephen King" },
    { Name: "Nicholas Sparks" }
  ];
  
  var e = document.getElementById("authorsContainer");
  for(var i = 0; i < authors.length; i++){
    var container = document.createElement("div");
    var author = document.createElement("div");
    var authorNumber = document.createElement("span");
    authorNumber.setAttribute("class", "sel-author-number");
    authorNumber.appendChild(document.createTextNode((i+1)));
    container.setAttribute("class", "form-group");
    var authorID = "author" + (i+1);
    container.setAttribute("id", authorID); 
    author.setAttribute("class","col-sm-4 control-label");
    author.appendChild(authorNumber);
    author.appendChild(document.createTextNode(": " + authors[i].Name));
    var removeLink = document.createElement("span");
    removeLink.appendChild(document.createTextNode("[Remove]"));
    author.appendChild(removeLink);
    container.appendChild(author);
    
    e.appendChild(container);
    removeLink.onclick = function(){
      Remove();
    };
  }
};
<div id="authorsContainer"></div>

4 Comments

I've added some code, and more details. The changes would be only for making the text look pretty -- and not actually used or referenced anywhere else. Let me know if you think this method would still work or if you need any more details. Thanks for all the help so far.
Modified answer to hopefully solve what you were looking for. Good luck @errorreplicating!
Thank you so much, I'm still working on implementing a solution on my end but I've learned a lot so far, guys like you and @Basic are what make this community so great and what help keep me positive as I'm working on things that are becoming increasingly frustrating. Thanks again!
I unfortunately don't have enough reputation to vote on this account but once I do I will make sure to come back and vote. Cheers!
0

You've got 2 different issues;

  • Manage a list of authors (possibly with ids)
  • Display a numbered list

For the first part, have an array or authors and use js to add/remove. If you're not familiar with the technique, see this answer. When any change is made to that array, call a second "update screen" function which clears the <div> holding the authors and re-creates its contents.

Your update() function might look something like this:

//Add and remove from authors as you wish, then call update()
var authors = ['Bob', 'Sue'];

function update() {
    var container = document.getElementById('Authors');

    //clear the container, open a list
    container.innerHTML = "<ul>"

    //Recreate the contents...
    for(var i = 0; i < authors.length; i++) {
        //Add the author
        container.innerHtml += '<li>' + i + '. ' + authors[i] + '</li>';
    }

    //Close the list
    container.innerHTML += "</ul>"
}

Of course, if you're using jQuery this code can be cleaned up considerably...

Edit: It doesn't matter where the authors are coming from originally, you can get them into a javascript list easily. Guessing a bit at what the looping code/object model looks like, change your code that generates the divs

<% For i = ... %>
    <div ID='dvAuthor" + i.ToString + "' class='form-group'><div class='col-sm-4 control-label'>
<% Next %>

to generate array entries instead

var authors = [];
<% for i = ... %>
    authors[i] = '<%=Authors(i).Name.Replace("'", "\'") %>';
<% Next %>

or if that's not possible, you can populate the list from the current page contents (messier but...)

var authors = [];
var authorDivs = document.getElementById("Container").getElementsByTagName("div");
for(var i=0;i<authorDivs.length;i++) {
    authors[i] = authorDivs[i].innerHTML;
}

And with nothing extraneous:

var authorDivs = document.getElementById("Container").getElementsByTagName("div");
for(var i=0;i<authorDivs.length;i++) {
    var currentId = authorDivs[i].id;
    var currentContents = authorDivs[i].innerHTML;
    // etc...
}

7 Comments

Unfortunately the authors are coming from a database so I don't think it would be possible to store them in an array like that. I've added some more details above so hopefully that clears things up a little bit. And, no JQuery sadly.
See my edit - where the data comes from is irrelevant. You can manipulate the list via the dom alone if you prefer, but it will get messy fast. That's why I prefer the single "authoritative" array on the page that everything else updates from. If you prefer, mix the first/last snippet to manipulate the DOM directly and skip the authors array
I've added a edit above to reply to your comment, I'm getting closer to understand what is happening, I'd appreciate any more help you could offer.
Ok, in response to your edits, my last snippet does what you need. Let's say you have the following structure on the page... <div id="Container"><div id="dvAuthorXXX">...</div><div id="dvAuthorYYY">...</div></div>... The last snippet will find all <div> tags inside the element with id Container and loop through them. authorDivs.length is how you determine the count of authors on the page, authorDivs[i] represents each author div, so eg authorDivs[i].id would return the id for the current div as you loop through.
Thank you so much, I appreciate it a lot and I've learned a lot. I'm still working on it but I think I now know what I'm doing (kind of).
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.