views:

55

answers:

3

Hello,

I have an unordered list of elements organized in rows. When a user clicks on a row, I want the text in the row to be appended into a separate text field. The issue with my current code is that I if the user clicks multiple boxes, all of the associated text with each of those boxes will be appended into the textfield. I would like to append the text from only the last row element that the user clicked.

Here is my javascript:

function clickEvents() {

// Day List Selector
$('#DC_id_1').click(function() {
    $('#whenTextField').attr('value', 'Today');
});
$('#DC_id_3').click(function() {
    $('#whenTextField').attr('value', 'Tomorrow');
});
$('#DC_id_5').click(function() {
    $('#whenTextField').attr('value', 'Later');
});

// Time List Selector

$('#DC_id_37').click(function() {
   var day = $('#whenTextField').attr('value');
   $('#whenTextField').attr('value', day + ', Right Now');
});
$('#DC_id_39').click(function() {
   var day = $('#whenTextField').attr('value');
   $('#whenTextField').attr('value', day + ', Morning');
});
$('#DC_id_41').click(function() {
   var day = $('#whenTextField').attr('value');
   $('#whenTextField').attr('value', day + ', Midday');
});
$('#DC_id_43').click(function() {
   var day = $('#whenTextField').attr('value');
   $('#whenTextField').attr('value', day + ', Afternoon');
});
$('#DC_id_45').click(function() {
   var day = $('#whenTextField').attr('value');
   $('#whenTextField').attr('value', day + ', Evening');
});

}

Basically, I think I want to use an "if" statement to control the clicking in the Time List Selector elements list.

example:

if (DC_id_37 is clicked) { append('text'); } else if (DC_id_39 is clicked) { append('some other text');

Here is the associated HTML:

<ul id="dayList">
   <li id="DC_id_1">
      Today
   </li>
   <li id="DC_id_3">
      Tomorrow
   </li>
   <li id="DC_id_5">
      Later
   </li>
 </ul>

 <ul id="timeList">
    <li id="DC_id_37">
       Right Now
    </li>
    <li id="DC_id_39">
       Morning
    </li>
    <li id="DC_id_41">
       Midday
    </li>
    <li id="DC_id_43">
       Afternoon
    </li>
    <li id="DC_id_45">
       Evening
    </li>
 </ul>


 <textField id="whenTextField">

*Note I just created this HTML by hand, as I'm building the web app in Dashcode, and its putting out some very ugly HTML

Actual HTML created by Dashcode:

 <ul id="timeList"> 
   <li> 
      <div id="foo"></div> 
      <div id="DC_id_37">Right Now</div> 
      <div></div> 
   </li> 
   <li> 
       <div id="foo2"></div> 
       <div id="DC_id_39"></div> 
       <div></div> 
   </li> 
  </ul>
A: 

I believe this is what you're looking for:

$('#DC_id_37').click(function() {
   var day = $('#whenTextField').attr('value').split(",")[0];
   $('#whenTextField').attr('value', day + ', Right Now');
});

The .split(",")[0] will grab the first part of what's in the text box.


You could simplify your code with something like this:

$('#dayList li').click(function() {
  $('#whenTextField').attr('value',$(this).text());
});

$("#timeList li").click(function() {
  var day = $('#whenTextField').attr('value').split(",")[0];

  $('#whenTextField').attr('value', day + ', '+$(this).text());
});
Gert G
Thank you! Much appreciated! Now I need to read up on the documentation on the split method.
fordays
No problem. You can read more about split here: http://www.w3schools.com/jsref/jsref_split.asp Essentially it splits the string with the delimiter we specified (in this case a comma). It returns an array. The `[0]` grabs the first element of that array.
Gert G
+1  A: 

Instead of simply appending the new value, you need to replace the old value. I would do it this way:

// Based on the HTML you posted, we only need two click functions.
$("#dayList > li > div:eq(1)").click(function() {
    var newDate = $(this).text();

    var currentValues = $("#whenTextField").attr("value").split(", ");

    // Initialize this as an empty string in case the user has not yet selected
    // a time.
    var time = "";

    // Get the previous time, if one has already been appended.
    if (currentValues.length == 2) {
        time = ", " + currentValues[1];
    }

    // Update the value of the text field.
    $("#whenTextField").attr("value", newDate + time);
});

$("#timeList > li > div:eq(1)").click(function() {
    // Get the current date value.
    var date= $("#whenTextField").attr("value").split(", ")[0];

    // Get the text from the 'li' element that raised the event.
    var time = $(this).text();

    // Update the value of the text field, keeping the previously selected date.
    $("#whenTextField").attr("value", date + ", " + time);
});

This approach also saves the selected time if a user later changes the selected date.


Update:

I updated my example to match the second nested <div /> element under each <li /> using the :eq(n) selector (the selector is zero-based). This solution assumes that the target <div /> elements will always be the second one, based on your comment.

You have a few other options, too:

  • You could use the :parent selector to affect only <divs /> that contain text (or any child elements).

    $("#timeList > li > div:parent").click(function() { });

  • Or, you could use the Attribute Starts With Selector to affect only <div /> elements with IDs that start with "DC_id_".

    $("#timeList > li > div[id^='DC_id_']").click(function() { });

I'm not sure which solution performs the best. Personally, I would recommend going with the third option (the Attribute Starts With selector) since generated IDs are usually more predictable than an element's index or contents.

Justin R.
Hey, This looks great, however, I'm using Dashcode, and my HTML isn't structured as simply as I outlined in my example. Each <ul> is structured like this:<ul id="timeList"> <li> <div id="foo"></div> <div id="DC_id_37">Right Now</div> <div></div> </li> <li> <div id="foo2"></div> <div id="DC_id_39"></div> <div></div> </li></ul>How do i modify the $('timeList > li') selector to focus on the second nested <div> in each <li>?
fordays
I added the formatted HTML to the bottom of my original post for easier reading.
fordays
I updated my answer based on your comment, and gave you a few more options based on your updated HTML sample. I hope they help!
Justin R.
A: 

Roughly

html: (adjust to taste, prolly have to do some css)

<div class="appointment">
    <div class="options">
       <ul class="day">
          <li>Today</li>
          <li>Tomorrow</li>
          <li>Later</li>
       </ul>
       <ul class="time">
          <li>Right Now</li>
          <li>Morning</li>
          <li>Midday</li>
          <li>Afternoon</li>
          <li>Evening</li>
       </ul>
    </div>
    <input class="when" type="text" />
</div>

jquery

$('.appointment').each(function(){
    var self = $(this)
    , whenField = self.find('.when')
    , day = 'choose a day'
    , time = 'choose a time';

    self.delegate('.options li', 'click', function(e){
        var li = $(this), ul = li.closest('ul');
        if(ul.hasClass('day')) {
            day = li.text();
        } else if(ul.hasClass('time')) {
            time = li.text();
        }
        whenField.val(day + ' - ' + time);
    });
});

Reusable on a page, so you can have more appointment boxes on a page. I personally avoid using element ID's like the plague, better abstract it and shorten code substantially if you generalize.

BGerrissen