Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Date ranges #16

Closed
wants to merge 15 commits into from
Closed

RFC: Date ranges #16

wants to merge 15 commits into from

Conversation

eternicode
Copy link
Contributor

This is a Request For Comments regarding date ranges in bootstrap-datepicker, and related discussion should preferably happen here.

Specifically, I'm looking for ideas and opinions on how to display it, what markup to use, what options might be involved, etc.

@Garito
Copy link

Garito commented Mar 31, 2012

I would like to discuss about the markup in the first place.

Given the actual code for a field:

<div class="control-group">
    <label class="control-label" for="date">Date</label>
    <div class="controls">
        <div class="input-append">
            <input id="date" name="date" value="2012-3-31" />
            <span class="add-on">€</span>
        </div>
    </div>
</div>

The most logical/simple step will be something like:

<div class="control-group">
    <label class="control-label" for="sDate">Date</label>
    <div class="controls">
        <div class="input-append">
            <input id="sDate" name="sDate" value="2012-3-31" />
            <label class="control-label" for="fDate">to</label>
            <input id="fDate" name="fDate" value="2012-12-21" />
            <span class="add-on">€</span>
        </div>
    </div>
</div>

But this version will lost the hability to click on the field label to focus on it

Perhaps this version will be better for our needs?

<fieldset class="control-group">
    <legend>Date range</label>
    <div class="controls">
        <div class="input-append">
            <label class="control-label" for="sDate">From</label>
            <input id="sDate" name="sDate" value="2012-3-31" />
            <label class="control-label" for="fDate">to</label>
            <input id="fDate" name="fDate" value="2012-12-21" />
            <span class="add-on">€</span>
        </div>
    </div>
</fieldset>

@Nerian
Copy link

Nerian commented Mar 31, 2012

My two cents:

The user just need to click on the first input field. That input will display a calendar that allows to select two dates. When two dates are selected the hidden fields are updated with the relevant values.

<div class="control-group">
    <label class="control-label" for="date">Date</label>
    <div class="controls">
        <div class="input-append">
            <input id="date" name="date"/>
            <input type='hidden' class='date-range-start' name="date[start]" value="2012-3-31" />
            <input type='hidden' class='date-range-end' name="date[end]" value="2012-4-31" />
        </div>
    </div>
</div>

This, in rails, will be received like this:

Started GET "/....some-url..../?date[start]=2012-3-31&date[end]=2012-4-31"

Parameters: {"date"=>{"start"=>"2012-3-31", "end"=>"2012-4-31"}}

@eternicode
Copy link
Contributor Author

The main concern with the markup is making it noscript-friendly -- that is, still usable if js is turned off for whatever reason.

Although I do like @Nerian's hidden fields, it's not noscript friendly, so not really an option. I do agree, though, that both selected dates (and the range between them) should be visible on the one datepicker, whichever field it's shown on.

@Garito, I think you're on the right track with the to label between the two fields, but perhaps not as a label (span.add-on already has the styles we need for that, and some of the styles for label get in the way of those). I'm not too concerned about being able to focus the field through clicking the label, unless you can provide a compelling argument for it.

I've started a new range branch for the range picker. Currently it's just got some tentative CSS updates to use with this markup:

<div class="control-group">
    <label class="control-label" for="sDate">Date</label>
    <div class="controls">
        <div class="input-daterange">
            <input class="input-small" id="sDate" name="sDate" value="2012-03-31" />
            <span class="add-on">to</span>
            <input class="input-small" id="fDate" name="fDate" value="2012-12-21" />
        </div>
    </div>
</div>

Other areas to think about are how to instantiate the range picker (what options, what assumptions can be made, ...) and what the interaction looks like.

The instantiation is tricky. We could detect when two inputs are selected (ie, $('#sDate, #fDate')), which I don't particularly like -- it could be sticky where, for example, $('.datepicker') is used and returns only two inputs. I'm leaning more toward some explicit option, maybe ranged: true (but I really don't want to have to support N-input ranges...), or perhaps even a separate jQuery plugin altogether, $().daterangepicker(). So many directions to go, all of which have downsides.

I think the interaction can be simple enough: maintain the two dates internally, and when a date is selected, if it is before the current end date it becomes the new start date, and if it is after the current start date it becomes the new end date.

I don't think it'll be possible (certainly not easy) to maintain keyboard controls for ranges, though.

@Garito
Copy link

Garito commented Apr 7, 2012

@eternicode the only reason why I put this on the list of possibilities is because the pair label/input pattern

Good point with the add-on class for the to. Bootstrap people could make it attached to the both fields (I mean visually) And when you click the Date label the first input will be focused

When come back to my work I will implement my data-renge field with the markup you are using so I could test the library ;)

@eternicode
Copy link
Contributor Author

@Garito just to be clear, the range branch currently only has the CSS changes for the form layout I mentioned -- there's no range functionality yet.

@Garito
Copy link

Garito commented Apr 8, 2012

Yeah! FileMerge is my friend...

@eternicode
Copy link
Contributor Author

Well, this weekend I had somewhat of a breakthrough -- there's now a new daterange implementation in the range branch. The README now lists the html to use:

<div class="input-daterange">
    <input class="input-small" name="start" value="2012-03-31" />
    <span class="add-on">to</span>
    <input class="input-small" name="end" value="2012-12-21" />
</div>

And you set it up with:

$('.input-daterange').datepicker({format: 'yyyy-mm-dd'})

I still need to make it respect data-attributes on the .input-daterange, but it's a start.

Basically, this sets up a separate "monitor" object that keeps the individual datepickers (one for each input) in sync, with a few changes to the datepickers themselves to be able to display these ranges.

Check it out, let me know your thoughts.

--HG--
rename : build.less => build/build.less
@activestylus
Copy link

Big problem with that implementation - most people need those name attributes to post info to the database. You should consider using data* attributes instead

@activestylus
Copy link

For what its worth I do like your last proposed idea in terms of actual markup. All you have to do is use data-datepicker-name instead of name attribute on those inputs and you should be golden.

Now if you really wanted to get fancy the script would convert those both into hidden inputs and simply display the range in a styled div. This way you could do the range selection from one dropdown.

Interestingly enough it seems that Stefan Petre did something similar a while back, but stopped maintaining it: http://www.eyecon.ro/datepicker/

@activestylus
Copy link

Another one worth looking at is http://foxrunsoftware.github.com/DatePicker/

Unfortunately I think you will find that most implementations are pretty hefty, definitely have not found any minified versions under 30-40K. So far I am impressed with how lightweight the bootstrap implementation is - would be great if that terse philosophy sticks as features are added, or perhaps the code could be modularized so people can use either a stripped-down version or get all the whistles and bells.

@eternicode
Copy link
Contributor Author

@activestylus, you're absolutely correct on the name attributes!

I guess it's not clear from the markup (and also not from the docs), but the name attributes are completely arbitrary -- the default behavior depends only on source order (via jquery) of the child inputs. Non-default behavior would be to pass an inputs option, as an array of input elements, and only those elements (and their order in the array) will be used.

As for auto-combining the inputs, it's something that I wouldn't mind happening, but I'm not happy with any implementations that have come to mind. Plus, unless I'm mistaken, any kind of DOM morphing would not be very friendly to bootstrap's data-api concept (in which they only initiate a plugin when its element is interacted with -- meaning, specifically, not on page load).

@a-bronx
Copy link

a-bronx commented Oct 19, 2012

I'd suggest adding a 'data-lower-bound-for="<selector>"' and 'data-upper-bound-for="<selector>"' attributes, so that two datepickers could work together limiting each other:

<label>From
    <input type="text" class="date" id="validFrom" name="validFrom" value="2012-01-01"
        data-lower-bound-for="#validTo"
    />
</label>
<label>To
    <input type="text" class="date" id="validTo" name="validTo" value="2012-12-31"
        data-upper-bound-for="#validFrom"
    />
</label>
$("input.date").each(function(){
    var _this = $(this);
    _this.datepicker()
        .on("changeDate", function(ev) {
            var data = _this.data();
            if ("lowerBoundFor" in data) {
                $(data.lowerBoundFor).datepicker("setStartDate", ev.date);
            }
            if ("upperBoundFor" in data) {
                $(data.upperBoundFor).datepicker("setEndDate", ev.date);
            }
        });
    })

@twashing
Copy link

Is this feature still in development? I'd love to have it available for a project I am working on.

Thanks

@eternicode
Copy link
Contributor Author

@twashing yes, it's still in development; it's under the range branch. I'm mostly just keeping it up with master right now, and I haven't modified it recently aside from update merges.

@PatrickHuetter
Copy link

Please keep working on it! 👍

@FGRibreau
Copy link

Can't wait for range to be in master!

@eternicode eternicode mentioned this pull request Apr 2, 2013
@eternicode
Copy link
Contributor Author

This is now in master.

@eternicode eternicode closed this Apr 2, 2013
@FGRibreau
Copy link

YEAAAH ! 👍

@rchavik
Copy link

rchavik commented Apr 3, 2013

Thank you

@ragulka
Copy link
Contributor

ragulka commented Apr 18, 2013

Is there a way to determine which date was changed when listening to the changeDate event? I'd like to move focus automatically to the "To" field when the date in "from" has changed.

@ragulka
Copy link
Contributor

ragulka commented Apr 18, 2013

Answering my own question: it's possible to listen to the changeDate event on both "from" and "to" inputs, instead of just the container.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants