SitePoint Sponsor

User Tag List

Results 1 to 9 of 9
  1. #1
    SitePoint Member
    Join Date
    Nov 2007
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Add value to a list, make it deletable

    Hello all,

    I am new to JavaScript and wanted to know if someone could help me out with something I want to do.

    I want to have, for example, three links such as:

    HTML Code:
    <a href="#" onclick="addToList('Bananas')">Bananas</a>
    <a href="#" onclick="addToList('Potatoes')">Potatoes</a>
    <a href="#" onclick="addToList('Oranges')">Oranges</a>
    Then, later on the page there should be a div like so:
    HTML Code:
    <div id="list">
    
    </div>
    When someone clicks one of the above links, it should enter a new element as follows:

    After clicking Bananas link:
    HTML Code:
    <div id="list">
    <span onclick="removeMyself()">Bananas</span>
    </div>
    If someone clicks a certain element in the div, it will be removed from the div:
    HTML Code:
    <div id="list">
    
    </div>
    Does anyone know how to achieve this? All the data I want to pass will be done in the onclick function call itself, no need for anything dynamic. Any tips would be greatly appreciated!

    Thanks!

  2. #2
    SitePoint Wizard Pepejeria's Avatar
    Join Date
    Jan 2005
    Location
    Too far up north
    Posts
    1,566
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You can achieve this using the DOM. Here is some good reading on how to use it.

  3. #3
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,729
    Mentioned
    104 Post(s)
    Tagged
    4 Thread(s)
    That was a very good description of what you're after.

    Here's how to achieve it.

    The items that are added will want a space between them, so that can be added as a part of the name itself so that we don't have to worry about additional elements when we remove them.

    The onclick event will require a special function to add an event, to make the process as cross browser compatible as possible.

    Code Javascript:
    var Event = {
        add: function () {
            if (window.addEventListener) {
                return function (el, type, fn) {
                    Dom.get(el).addEventListener(type, fn, false);
                };
            } else if (window.attachEvent) {
                return function (el, type, fn) {
                    var f = function () {
                        fn.call(Dom.get(el), window.event);
                    };
                    Dom.get(el).attachEvent('on' + type, f);
                };
            }
        }()
    };

    Now that we can easily add an event, the addToList function follows quite nicely.

    Code Javascript:
    function addToList(name) {
        var el = document.getElementById('list');
        var span = document.createElement('span');
        span.appendChild(document.createTextNode(name + ' '));
        Event.add(span, 'click', removeMyself);
        el.appendChild(span);
    }

    And the removeMyself function is as follows.

    Code Javascript:
    function removeMyself(evt) {
        evt = evt || window.event;
        if (evt) {
            var target = evt.target || evt.srcElement;
            target.parentNode.removeChild(target);
        }
    }
    Last edited by paul_wilkins; Jan 9, 2008 at 08:15.

  4. #4
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,729
    Mentioned
    104 Post(s)
    Tagged
    4 Thread(s)
    However, now we need to consider the semantics of the html.

    Those span's aren't going to be one after another, they're going to be one above another, so a paragraph would be better than using inline spans.

    Even better than paragraphs is to make them list items, so that it's an actual list that's being built.

    Then we have

    Code HTML4Strict:
    <ul id="list">
     
    </ul>

    and for the addToList function

    Code Javascript:
    function addToList(name) {
        var el = document.getElementById('list');
        var li = document.createElement('li');
        li.appendChild(document.createTextNode(name));
        Event.add(li, 'click', removeMyself);
        el.appendChild(li);
    }

    But once we have a list, clicking on them is counter intuitive, so you may want to have the list as actual text, with a remove link (or a red X) following the item.

    Code Javascript:
    function addToList(name) {
        var el = document.getElementById('list');
        var li = document.createElement('li');
        var span = document.createElement('span');
        var a = document.createElement('a');
        span.appendChild(document.createTextNode(name));
        a.setAttribute('href', '#');
        a.setAttribute('class', 'remove');
        a.appendChild(document.createTextNode('Remove'));
        Event.add(a, 'click', removeListItem);
        li.appendChild(span);
        li.appendChild(document.createTextNode(' ');
        li.appendChild(a);
        el.appendChild(li);
    }

    Then the link will have to remove the list item instead of just itself, but that's just a small improvement too. We'll just walk up the tree until we find the list item, and give up if we get to the body tag.

    Code Javascript:
    function removeListItem(evt) {
        evt = evt || window.event;
        if (evt) {
            var target = evt.target || evt.srcElement;
            while (target.nodeName.toLowerCase() !== 'li' &&
                     target.nodeName.toLowerCase() !== 'body') {
                target = target.parentNode;
            }
            if (target.nodeName !== 'body') {
                target.parentNode.removeChild(target);
            }
        }
    }

    It then wouldn't take much for css to make it look presentable. The text has already been placed in a span to allow for easier formatting, and we can remove the bullet points, give the list a fixed width, float the span left and align the rest of the text (such as the link) to the right. Put in a background color, reset the margins and paddings for cross-browser compatibility, and we're about there.

    Code CSS:
    #list {
        margin: 0;
        padding: 0.5em;
        list-style-type: none;
        background: #eee;
        width: 10em;
    }
    #list li {
        text-align: right;
    }
    #list li span {
        float: left;
    }

    Now that's looking a whole lot better.

  5. #5
    SitePoint Member
    Join Date
    Nov 2007
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Wow, thanks for the very detailed solution. I have been analyzing this code for a long time and am amazed at how you came up with it. Is there a book you would recommend to learn how to program in JavaScript in this manner? I know there are online tutorials but I usually use those for short-term jobs.

    Again, thanks for the elucidation, it has really helped me solve not only the problem but other questions I had about how to properly use JavaScript.

  6. #6
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,729
    Mentioned
    104 Post(s)
    Tagged
    4 Thread(s)
    I'm afraid that it's called experience, where you drag in bit and pieces from many different experiences. Notice how the original solutions began as quite simple solutions, and then along the way there were relatively small adjustments made to solve separate issues as we went along.

    That Event.add() stuff came from an article about adding and removing events, and then was modified to work without the other Dom functions in the example.

    However, there are some good books to help you along the way. See this following thread, for example.

    http://www.sitepoint.com/forums/showthread.php?t=524502

  7. #7
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,729
    Mentioned
    104 Post(s)
    Tagged
    4 Thread(s)
    On coming back to this now, the whole Event.add() function can be removed.
    That technique is useful if you're wanting to add multiple onload events to the body, but other common situations are few and far between.

    It's much better to use the traditional event registration when you know there is going to be only one event function attached to an element.
    http://www.quirksmode.org/js/events_tradmod.html

    Code Javascript:
    function addToList(name) {
        // ...
        a.onclick = removeListItem;
        // ...
    }
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  8. #8
    SitePoint Wizard
    Join Date
    Nov 2004
    Location
    Nelson BC
    Posts
    2,310
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    short answer:
    Code:
    function addToList(item) {
    	var newItem = document.getElementById("list").appendChild(document.createElement("span"));
    	newItem.innerHTML = item;
    	newItem.onclick = function () {
    		this.parentNode.removeChild(this);
    	}
    }

  9. #9
    SitePoint Member
    Join Date
    Nov 2007
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for the references, pmw57 -- I will definitely look into those. jimfraser -- an efficient solution, thanks again!


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •