Last active
April 18, 2016 10:57
-
-
Save fhrbek/2dfe0d347d1e98083cadb5ad397637c7 to your computer and use it in GitHub Desktop.
Datetime Range Picker with Chrono
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Ember from 'ember'; | |
import DatetimeObject from '../datetime-input/datetime-object'; | |
import DatetimeRangeObject from '../datetime-range-input/datetime-range-object'; | |
export default Ember.Controller.extend({ | |
appName: 'PE Datetime Range Selector Demo', | |
datetimeRange: DatetimeRangeObject.create(), | |
init () { | |
this.reset(); | |
}, | |
reset () { | |
var date = moment().utc(), | |
from, to; | |
to = date.format('YYYY-MM-DD [00:00]'); | |
date.subtract(1, 'day'); | |
from = date.format('YYYY-MM-DD [00:00]'); | |
// This does not work well - if we only change inner attributes, | |
// the datetime-input component does not recognize any change in | |
// parameters and does not call didReceiveAttrs callback; | |
// see the uncommented code below which creates brand new objects | |
this.setProperties({ | |
'datetimeRange.from.timestamp': from, | |
'datetimeRange.to.timestamp': to | |
}); | |
/* | |
this.setProperties({ | |
'datetimeRange.from': DatetimeObject.create({'timestamp': from}), | |
'datetimeRange.to': DatetimeObject.create({'timestamp': to}) | |
}); | |
*/ | |
}, | |
updateObject: function (obj, diff) { | |
var properties = Object.keys(diff); | |
properties.forEach((property) => { | |
var value = diff[property], | |
orig = obj.get(property); | |
if (orig instanceof Ember.Object) { | |
this.updateObject(orig, value) | |
} else { | |
obj.set(property, value); | |
} | |
}); | |
}, | |
actions: { | |
valueChanged: function (diff) { | |
this.updateObject(this.get('datetimeRange'), diff); | |
}, | |
reset: function () { | |
this.reset(); | |
} | |
} | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Ember from 'ember'; | |
import DatetimeObject from './datetime-object'; | |
export default Ember.Component.extend({ | |
tagName: 'span', | |
datetimeObject: DatetimeObject.create(), | |
didReceiveAttrs () { | |
this._super(...arguments); | |
this.set('workDatetimeObject', DatetimeObject.create({'timestamp': this.get('datetimeObject.timestamp')})); | |
}, | |
didUpdateAttrs () { | |
console.log('DID UPDATE ATTRS CALLED'); | |
}, | |
classNames: ['datetime-input'], | |
classNameBindings: ['workDatetimeObject.isValid::invalid'], | |
didInsertElement: function () { | |
this.$('input').blur(() => { | |
// This assignment looks superfluous to me but without is, the work timestamp is not updated | |
// as didReceiveAttrs is not called if a nested property only (on the datetimeObject) is changed. Why??? | |
this.set('workDatetimeObject.timestamp', this.get('workDatetimeObject.normalizedTimestamp')); | |
this.sendAction('valueChangedAction', {'timestamp': this.get('workDatetimeObject.timestamp')}); | |
}); | |
}, | |
actions: { | |
workValueChanged: function (timestamp) { | |
this.set('workDatetimeObject.timestamp', timestamp); | |
} | |
} | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Ember from 'ember'; | |
export default Ember.Object.extend({ | |
timestamp: '', | |
normalFormat: 'YYYY-MM-DD HH:mm', | |
acceptedFormats: [ | |
'YYYY', | |
'YYYYMM', | |
'YYYY-MM', | |
'YYYYMMDD', | |
'YYYY-MM-DD', | |
'YYYYMMDDHH', | |
'YYYY-MM-DD HH', | |
'YYYYMMDDHHmm', | |
'YYYY-MM-DD HH:mm', | |
'H', | |
'HA', | |
'H:m', | |
'H:mA' | |
], | |
parsedTimestamp: Ember.computed('timestamp', 'acceptedFormats', 'acceptedFormats.[]', function () { | |
var tstr = this.get('timestamp'); | |
if (Ember.isBlank(tstr)) { | |
return null; | |
} | |
var result; | |
result = moment(tstr, this.get('acceptedFormats'), true); | |
if (!result.isValid()) { | |
var chronoResult = chrono.parse(tstr)[0]; | |
if (chronoResult) { | |
result = moment(chronoResult.start.date()); | |
} | |
} | |
return result.isValid() ? result : false; | |
}), | |
normalizedTimestamp: Ember.computed('parsedTimestamp', 'normalFormat', function () { | |
var ts = this.get('parsedTimestamp'); | |
if (ts !== false) { | |
if (ts === null) { | |
return null; | |
} else { | |
return ts.format(this.get('normalFormat')); | |
} | |
} | |
return this.get('timestamp'); | |
}), | |
isValid: Ember.computed('timestamp', function () { | |
return this.get('parsedTimestamp') !== false; | |
}) | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Ember from 'ember'; | |
import DatetimeRangeObject from './datetime-range-object'; | |
export default Ember.Component.extend({ | |
tagName: 'span', | |
datetimeRangeObject: DatetimeRangeObject.create(), | |
classNames: ['datetime-range-input'], | |
classNameBindings: ['datetimeRangeObject.isValid::invalid'], | |
actions: { | |
fromChanged: function (diff) { | |
this.sendAction('valueChangedAction', {'from': diff}); | |
}, | |
toChanged: function (diff) { | |
this.sendAction('valueChangedAction', {'to': diff}); | |
} | |
} | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Ember from 'ember'; | |
import DatetimeObject from '../datetime-input/datetime-object'; | |
export default Ember.Object.extend({ | |
from: DatetimeObject.create(), | |
to: DatetimeObject.create(), | |
isValid: Ember.computed('from.timestamp', 'to.timestamp', function () { | |
var from = this.get('from'), | |
to = this.get('to'); | |
return from.get('isValid') && to.get('isValid') && | |
(from.get('parsedTimestamp') === null || to.get('parsedTimestamp') === null || | |
from.get('parsedTimestamp').isSameOrBefore(to.get('parsedTimestamp'))); | |
}), | |
err: Ember.computed('from.timestamp', 'to.timestamp', 'isValid', function () { | |
var from = this.get('from'), | |
to = this.get('to'), | |
err = ''; | |
if (!from.get('isValid')) { | |
err += 'Timestamp from is not valid;'; | |
} | |
if (!to.get('isValid')) { | |
err += 'Timestamp to is not valid;'; | |
} | |
if (from.get('isValid') && to.get('isValid') && !this.get('isValid')) { | |
err = 'Individual timestamps are valid but the range is invalid'; | |
} | |
return err; | |
}) | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
margin: 12px 16px; | |
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; | |
font-size: 12pt; | |
} | |
button { | |
margin-top: 1em; | |
} | |
label { | |
margin-right: 1em; | |
} | |
.datetime-range-input.invalid input, | |
.datetime-input.invalid input { | |
background-color: #ffaaaa; | |
} | |
.datetime-range-input .delimiter { | |
margin-left: .5em; | |
margin-right: .5em; | |
} | |
.info { | |
color: #bbb; | |
} | |
.error { | |
color: #f55; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"version": "0.7.2", | |
"EmberENV": { | |
"FEATURES": {} | |
}, | |
"options": { | |
"use_pods": true, | |
"enable-testing": false | |
}, | |
"dependencies": { | |
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js", | |
"ember": "https://cdnjs.cloudflare.com/ajax/libs/ember.js/2.4.4/ember.debug.js", | |
"ember-data": "https://cdnjs.cloudflare.com/ajax/libs/ember-data.js/2.4.3/ember-data.js", | |
"ember-template-compiler": "https://cdnjs.cloudflare.com/ajax/libs/ember.js/2.4.4/ember-template-compiler.js", | |
"moment": "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.12.0/moment.js", | |
"chrono": "https://cdn.jsdelivr.net/chrono/1.2.0/chrono.js" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment