3
\$\begingroup\$

I'm changing an HTML datepicker value (#date) into 3 separate values in order to post them to a booking engine. I've managed to get it to work but there is a lot of repetition and the original #date value is also submitted unnecessarily.

The engine takes these parameters:

date_day=27&date_month=9&date_year=2013&nights=3&people=2&ref=558&langClient=eng&expr=EUR`

HTML

 <form id="quick_res" action="#" method="post" name="availability">            
            <ul>    
                <li>
                <label for="date" id="anchor">Date :</label><input type="date" name="date" id="date" placeholder="12/09/13">
                </li>

                <li>
                <label for="numNights">Nights :</label><input type="number" name="nights" id="nights" placeholder="2">
                </li> 

                <li>
                <label for="numGuests">Guests :</label><input type="number" name="people" id="people" placeholder="2"> 
                </li>                                       

                <input name="ref" type="hidden" id="ref" value="558" /> 
                <input name="langClient" type="hidden" id="langClient" value="eng" />
                <li class="select-container">
                <label for="currency">Currency :</label> 
                    <select name="expr" id="expr">
                        <option value="EUR" selected="selected">EURO</option>
                        <option value="USD">US Dollar</option>
                        <option value="ARS">Argentine Peso</option>
                        <option value="AUD">Australian Dollar</option>
                        </select>
                </li>
                </ul>

                <input type="submit" name="submit" class="secondary button radius text-center" value="Click to Book">                    


    </form>

jQuery

 $('#date').on('change', function() {
     var new_val = $(this).val().split('-'),
         dateYear = parseInt(new_val[0]),
         dateMonth = parseInt(new_val[1]),
         dateDay = parseInt(new_val[2]);

    $('<input>', {
        type: 'hidden',
        name: 'date_day',
        id: 'date_day',
        value: dateDay

    }).appendTo('#anchor');

    $('<input>', {
        type: 'hidden',
        name: 'date_month',
        id: 'date_month',
        value: dateMonth

    }).appendTo('#anchor');

    $('<input>', {
        type: 'hidden',
        name: 'date_year',
        id: 'date_year',
        value: dateYear

    }).appendTo('#anchor');

 });
\$\endgroup\$
2
\$\begingroup\$

The tought process to make your code DRY is almost always the same:

  1. Find the commonalities between blocks of code.
  2. Extract these into an iterable structure.
  3. Loop.

Here we can see that everything is the same except the prefix and the value.

The code could be changed to:

Please note that you should always specify the radix argument when using the parseInt function since 10 is not default in every browser.

$('#date').on('change', function() {
    var newVal = $(this).val().split('-'), //renamed new_val to newVal, always stick to one naming convention
        dateParts = {
            year: parseInt(newVal[0], 10),
            month: parseInt(newVal[1], 10),
            day: parseInt(newVal[2], 10)
        };

    $('#anchor').append($.map(dateParts, function (index, key) {
        var name = 'date_' + key;

        return $('<input>', {
            type: 'hidden',
            name: name,
            id: name,
            value: dateParts[key]
        });
    }));
});

EDIT:

Note that with the above logic, you will end up having duplicate inputs with different values if the user changes the value multiple times. You could solve this by removing the previously added inputs before adding the new ones, but you could also simply add the inputs just prior to form submission by listening to the submit event instead.

Also, if you want to avoid sending #date's value, you can disable that input before submitting; disabled inputs aren't sent to the server.

Finally, you could choose to simply submit the form in AJAX using $.ajax (or any of it's shortcut methods such as $.post). That would have the advantage of making your site slighlty more dynamic and you would not have to append inputs to the form since you can use the data option.

\$\endgroup\$
  • \$\begingroup\$ Thanks, much better. I made a few edits though. There was no need to add 1 to the month to make up for 0 base as the month is already provided in the date. \$\endgroup\$ – mantis Sep 30 '13 at 9:14
  • \$\begingroup\$ @mantis, Thanks for fixing silly mistakes ;) I updated the answer with additionnal information. \$\endgroup\$ – plalx Sep 30 '13 at 13:08
  • \$\begingroup\$ Thanks for the edit comment. You're right, I do need to do it on submit as I put in some code to initialize the date and of course it won't work if the date isn't changed. I was going to submit in ajax but its a responsive site whereas the booking engine's is not and it would be a lot of extra work to restyle their content. It would make more sense though. Would I need some sort of endpoint page for that? I'm going to try to work it out on submit now :) \$\endgroup\$ – mantis Sep 30 '13 at 13:55
  • \$\begingroup\$ jsfiddle.net/rHZwS :) Unfortunately, when I go back to the page after being sent to the booking form the date is, of course, gone. Is there a way to remove it from the data submitted but reset it after submission? \$\endgroup\$ – mantis Sep 30 '13 at 14:15
  • \$\begingroup\$ @mantis You mean that the selected date value isin't persistent after the page reloads? You could use localStorage to make it persistent through requests. Did I misunderstood your problem? \$\endgroup\$ – plalx Sep 30 '13 at 14:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.