coffeescript-ui
Version:
Coffeescript User Interface System
1,452 lines (1,191 loc) • 35.6 kB
text/coffeescript
###
* coffeescript-ui - Coffeescript User Interface System (CUI)
* Copyright (c) 2013 - 2016 Programmfabrik GmbH
* MIT Licence
* https://github.com/programmfabrik/coffeescript-ui, http://www.coffeescript-ui.org
###
CUI.Template.loadTemplateText(require('./DateTime.html'));
# CUI.tz_data = {}
moment = require('moment')
class CUI.DateTime extends CUI.Input
constructor: (opts) ->
super(opts)
:
button_tooltip: "Open calendar"
bc_appendix: ["B.C.","BC"]
initOpts: ->
super()
locale = CUI.DateTime.getLocale()
locale:
mandatory: true
default: locale
check: (v) ->
CUI.util.isArray(CUI.DateTimeFormats[v]?.formats)
input_types:
check: Array
display_type:
default: "long"
check: ["long", "short"]
min_year:
mandatory: true
default: 0
check: "Integer"
max_year:
mandatory: true
default: 9999
check: "Integer"
store_invalid:
mandatory: true
default: false
check: Boolean
#
init: ->
=
= CUI.DateTimeFormats[].formats
= CUI.DateTimeFormats[]
= []
if not ?.length
= .slice(0)
else
for type in
found = false
for f in
if f.type == type
.push(f)
found = true
CUI.util.assert(found, "new CUI.DateTime", "opts.input_types contains unknown type: #{type}", formats: , input_type: )
= [0]
for format in
if format.clock == false
= format
= format
break
=
return
setInputFormat: (use_clock = [0].clock) ->
if use_clock == true
=
else
=
@
initDateTimePicker: ->
if
return
= new CUI.Template
name: "date-time"
map:
calendar: true
analog_clock: true
hour_minute: true
digi_clock: true
# timezone_display: true
# timezone: true
header_left: true
header_center: true
header_right: true
hour: true
minute: true
second: true
for k in [
"calendar"
"hour_minute"
"hour"
"minute"
"second"
]
@["__#{k}"] = .map[k]
.append(
new CUI.defaults.class.Button(
class: "cui-date-time-browser-date"
icon_left: "left"
text: .tab_date
onClick: =>
)
, "header_left")
.append(
new CUI.defaults.class.Button(
class: "cui-date-time-browser-time"
icon_right: "right"
text: .tab_time
onClick: =>
)
, "header_right")
# = tmpl.map.timezone_display
# = new CUI.Select
# data: CUI.tz_data
# name: "tz"
# mark_changed: false
# undo_support: false
# onDataChanged: (data) =>
#
# options: =>
#
# .start()
#
# tmpl.append(, "timezone")
# if .digi_clock
# .append(, "digi_clock")
getTemplate: ->
new CUI.Template
name: "date-time-input"
map:
center: true
right: true
readOpts: ->
super()
=
=
# = (dateTime, value) =>
# corrected_value =
# if corrected_value
# corrected_value
# else
# # keep the invalid value
# value
getCurrentFormat: ->
getCurrentFormatDisplay: ->
?.__display
setCursor: (cursor) ->
switch cursor
when "hour", "minute", "second", "am_pm"
title = .tab_time
CUI.dom.setAttribute(.DOM, "browser", "time")
else
title = .tab_date
CUI.dom.setAttribute(.DOM, "browser", "date")
.replace(new CUI.Label(text: title), "header_center")
@
initFormat: (input_format) ->
moment.locale(.moment_locale or )
switch
when "short"
input_format.__display = input_format.display_short
else
input_format.__display = input_format.display
= text: input_format.invalid
for k, v of
v.match_str = k
input = input_format.input
rstr = "("+Object.keys().join("|")+")"
re = new RegExp(rstr, "g")
s = input.split("")
regexp = []
matcher = []
last_match_end = 0
while (match = re.exec(input)) != null
match_str = match[0]
match_start = match.index
regexp.push("("+CUI.util.escapeRegExp(s.slice(last_match_end, match_start).join(""))+")")
regexp.push("("+[match_str].regexp+")")
matcher.push([match_str])
last_match_end = match_start + match_str.length
regexp.push("("+CUI.util.escapeRegExp(s.slice(last_match_end).join(""))+")")
input_format.regexp = new RegExp("^"+regexp.join("")+"$")
input_format.matcher = matcher
input_format
getTemplateKeyForRender: ->
"center"
render: ->
super()
if CUI.util.isEmpty()
.setAttribute("placeholder", [0].text)
switch
when "short"
display_key = "display_short"
else
display_key = "display"
attr = [0][display_key+'_attribute']
if not attr
attr = [0][display_key].replace(/[:, \.]/g, "-").replace(/-+/g,"-")
.setAttribute("data-cui-date-time-format", attr)
= new CUI.defaults.class.Button
icon: "calendar"
tooltip: text: CUI.DateTime.defaults.button_tooltip
onClick: =>
format: (_s, _output_format="display", output_type=null) ->
CUI.util.assert(_output_format in CUI.DateTime.formatTypes, "CUI.DateTime.format", "output_format must be on of \"#{CUI.DateTime.formatTypes.join(',')}\".", parm1: _s, output_format: output_format)
if moment.isMoment(_s)
mom = _s
else
s = _s?.trim()
if CUI.util.isEmpty(s)
return null
mom =
if mom.isValid() and CUI.util.isNull(output_type)
output_type = .type
if not mom.isValid()
formats_tried = []
for format in
for k in CUI.DateTime.formatTypes
formats_tried.push(format[k])
console.warn("CUI.DateTime.format: Moment '#{s}' is invalid. Tried formats:", formats_tried)
return null
output_format = null
for f in
if f.type == output_type
output_format = f
break
CUI.util.assert(output_format, "CUI.DateTime.format", "output_type must be in known formats", formats: , output_type: output_type)
switch _output_format
when "store"
return CUI.DateTime.formatMoment(mom, output_format[_output_format])
else
return CUI.DateTime.formatMomentWithBc(mom, output_format[_output_format])
regexpMatcher: ->
YYYY:
regexp: "(?:-|)[0-9]{1,}"
inc_func: "year"
cursor: "year"
MM:
regexp: "(?:0[1-9]|1[0-2])"
inc_func: "month"
cursor: "month"
DD:
regexp: "[0-3][0-9]"
inc_func: "day"
cursor: "day"
HH:
regexp: "[0-2][0-9]"
inc_func: "hour"
cursor: "hour"
hh:
regexp: "[0-1][0-9]"
inc_func: "hour"
cursor: "hour"
mm:
regexp: "[0-5][0-9]"
inc_func: "minute"
cursor: "minute"
ss:
regexp: "[0-5][0-9]"
inc_func: "second"
cursor: "second"
A:
regexp: "(?:AM|PM)"
inc_func:
cursor: "am_pm"
a:
regexp: "(?:am|pm)"
inc_func:
cursor: "am_pm"
Y:
regexp: "(?:-|)[0-9]{1,}"
inc_func: "year"
cursor: "year"
incAMPM: (mom) ->
current_hour = mom.hour()
if current_hour < 12 # AM
# set PM
mom.add(12,"hour")
else
mom.subtract(12,"hour")
initValue: ->
super()
value =
corrected_value =
if corrected_value and corrected_value != value
console.warn("CUI.DateTime.initValue: Corrected value in data:", corrected_value, "Original value:", value)
[] = corrected_value
@
getValueForDisplay: ->
value = ?.trim?()
if CUI.util.isEmpty(value)
return ""
mom =
if not mom.isValid()
return value
return CUI.DateTime.formatMomentWithBc(mom, )
getValueForInput: (v = ) ->
if CUI.util.isEmpty(v?.trim())
return ""
mom =
if not mom.isValid()
return v
return CUI.DateTime.formatMomentWithBc(mom, .input)
__checkInput: (value) ->
.enable()
if not CUI.util.isEmpty(value?.trim())
mom =
if not mom.isValid()
return false
if mom.bc or value.startsWith("-")
.disable()
else
=
return true
__getInputBlocks: (v) ->
# console.debug "getInputBlocks", v, .regexp
match = v.match(.regexp)
if not match
return false
blocks = []
pos = 0
for m, idx in match
if idx == 0
continue
if idx % 2 == 0
blocks.push new CUI.DateTimeInputBlock
start: pos
string: m
datetime: v
input_format:
matcher: .matcher[idx/2-1]
pos += m.length
if idx % 2 == 1
continue
blocks
start_day: 1
storeValue: (value, flags={}) ->
mom =
if mom.isValid()
if mom.bc
value = "-"+mom.bc
else
value = mom.format(.store)
else if and value.trim().length > 0
value = 'invalid'
else
value = null
super(value, flags)
@
getDigiDisplay: (format) ->
digits = []
for d in format.split("")
if (idx = ["H","h","m","s","A","a"].indexOf(d)) > -1
cursor = ["hour", "hour", "minute", "second", "am_pm", "am_pm"][idx]
if d in ["A", "a"]
digits.push(mask: "[aApP]", attr: cursor: cursor, title: cursor)
digits.push(mask: "[mM]", attr: cursor: cursor, title: cursor)
else
digits.push(mask: "[0-9]", attr: cursor: cursor)
else if d == "*"
digits.push(mask: "[0-9A-Z+\-:\. ]")
else
digits.push(static: ":")
# console.debug digits
= new CUI.DigiDisplay(digits: digits)
openPopover: (btn) ->
= new CUI.Popover
element: btn
handle_focus: false
onHide: =>
placement: "se"
class: "cui-date-time-popover"
pane:
content:
# if not .__now
#
.show()
@
closePopover: ->
# if
# CUI.clearTimeout()
# = null
if
.destroy()
delete()
@
updateDateTimePicker: ->
# if .__now
# = CUI.setTimeout =>
#
# = null
# ,
# 1000*30 # update the popover every 30 seconds
console.debug "updating popover...",
#
# .position()
@
destroy: ->
# console.debug "destroying popover"
super()
setClock: (mom = ) ->
hour = mom.hour()
minute = mom.minute()
second = mom.second()
millisecond = 0 # mom.millisecond()
seconds = second + millisecond / 1000
minutes = minute + seconds / 60
hours = (hour%12) + minutes / 60
CUI.dom.setStyleOne(, "transform", "rotate(" + hours * 30 + "deg)")
CUI.dom.setStyleOne(, "transform", "rotate(" + minutes * 6 + "deg)")
CUI.dom.setStyleOne(, "transform", "rotate(" + seconds * 6 + "deg)")
setDigiClock: (mom = ) ->
f = .digi_clock
console.debug "setDigiClock", f, mom, mom.format(f)
if f
.display(mom.format(f))
@
setPrintClock: (mom = ) ->
if not .timezone_display
return @
mom_tz = mom.clone()
mom_tz.tz(CUI.tz_data.tz)
# console.debug .timezone_display, mom_tz.format(.timezone_display)
CUI.dom.empty()
CUI.dom.append(, mom_tz.format(.timezone_display))
setTimezone: ->
UNUSEDgetTimezoneData: ->
if
return CUI.resolvedPromise()
$.get("#{CUI.getPathToScript()}/moment-timezone-meta.json")
.done (tz_data) =>
names = []
by_name = {}
for tz in tz_data
tz.geo = tz.lat+"/"+tz.long
# tz.print_name = tz.name.split("/").slice(-1)[0]
tz.print_name = tz.name
names.push(tz.print_name)
by_name[tz.print_name] = tz
names.sort()
= []
for n in names
.push(by_name[n])
# console.debug "timezone data loaded",
getTimezoneOpts: ->
if
mom = .clone()
opts = []
for tz, idx in
if not mom and tz.name != CUI.DateTimeFormats["de-DE"].timezone
continue
if mom
span = CUI.dom.span("cui-timezone-offset").setAttribute("title", tz.geo)
span.textContent = mom.tz(tz.name).format("zZ")
span
else
span = null
opts.push
text: tz.print_name
right: span
value: tz.name
opts
# s: string to parse
# formats: format to check
# use_formats: formats which are used to call our "initFormat", if format
# matched is not among them, init to the first check format.
# these formats are the "allowed" formats, this is used in __checkInput
parse: (stringValue, formats = , use_formats = formats) ->
if not (stringValue?.trim?().length > 0)
return moment.invalid()
for format in formats
mom =
if mom
if format in use_formats
=
else
=
mom.locale(moment.locale())
if mom.year() > # Year must not be greater than max year.
return moment.invalid()
# console.debug "parsing ok", mom, f, moment.locale()
return mom
if not formats.some((format) -> format.support_bc)
return moment.invalid()
# Moment support not all BC dates, we get here
# if the year is below that, or ends with a supported
# appendix like "v. Chr."
# lets see if the date is below zero
checkBC = false
hasBCAppendix = false
if stringValue.startsWith("-")
checkBC = true
stringValue = stringValue.substring(1)
else
us = stringValue.toLocaleUpperCase()
for appendix in CUI.DateTime.defaults.bc_appendix
ua = appendix.toLocaleUpperCase()
if us.endsWith(" "+ua)
stringValue = stringValue.substring(0, stringValue.length - ua.length).trim()
hasBCAppendix = checkBC = true
break
if not checkBC
return moment.invalid()
# set bc to the value
m = stringValue.match(/^[0-9]+$/)
if not m
return moment.invalid()
# fake a moment
mom = moment()
mom.bc = parseInt(stringValue)
if hasBCAppendix # If it has BC appendix, means that the number value of the year is one less.
mom.bc--
if mom.bc < 10
mom.bc = "000"+mom.bc
else if mom.bc < 100
mom.bc = "00"+mom.bc
else if mom.bc < 1000
mom.bc = "0"+mom.bc
else
mom.bc = ""+mom.bc
return mom
# like parse, but it used all known input formats
# to recognize the value
parseValue: (value, output_format = null) ->
input_formats = .slice(0)
for format in
CUI.util.pushOntoArray(format, input_formats)
mom =
if not output_format
return mom
if not mom.isValid()
return null
if mom.bc
return "-"+mom.bc
else
return mom.format([output_format])
__parseFormat: (f, s) ->
for k in CUI.DateTime.formatTypes
CUI.util.assert(f[k], "CUI.DateTime.__parseFormat", ".#{k} must be set", format: f)
mom = moment(s, f[k], true) # true the input format
if mom.isValid()
return mom
for p in f.parse
mom = moment(s, p, true)
if mom.isValid()
return mom
return
setMomentFromInput: ->
inp = .value.trim()
if inp.length > 0
=
if inp == "" or not .isValid()
= moment()
.__now = true
=
return
setInputFromMoment: ->
# .value = .format(.input)
# console.error "stored value:", .val()
#
@
__clearOverwriteMonthAndYear: ->
= null
= null
drawDate: (_mom) ->
if not _mom
mom = .clone()
mom.bc = .bc
else
mom = _mom
updateCalendar: (mom, update_current_moment = true) ->
CUI.dom.empty()
CUI.dom.append(, )
CUI.dom.append(, )
CUI.dom.append(, )
if update_current_moment
= mom.clone()
.bc = mom.bc
console.info("CUI.DateTime.updateCalendar:", .format(.input))
@
getDateTimeDrawer: (mom) ->
am_pm = [0].clock_am_pm
data =
month: mom.month()
year: mom.year()
date: mom.date()
hour: null
minute: null
second: null
am_pm: null
if .clock
data.hour = mom.hour()
data.minute = mom.minute()
data.second = mom.second()
if am_pm
data.am_pm = Math.floor(data.hour / 12)*12
data.hour = data.hour%12
pad0 = (n) ->
if n < 10
"0"+n
else
""+n
date_sel = new CUI.Select(
name: "date"
data: data
group: "date"
onDataChanged: =>
options: =>
opts = []
for day in [1..mom.daysInMonth()]
opts.push
text: pad0(day)
value: day
opts
).start()
month_sel = new CUI.Select(
name: "month"
data: data
group: "date"
onDataChanged: =>
options: =>
opts = []
for month in [0..11]
opts.push
text: pad0(month+1)
value: month
opts
).start()
year_sel = new CUI.Select(
name: "year"
data: data
group: "date"
onDataChanged: =>
options: =>
options = []
minYear = data.year - 20
if minYear <
minYear =
for year in [minYear..data.year + 20]
options.push
text: "#{year}"
value: year
options
).start()
if [0].clock
if
emtpy_clock_opts = [
text: ''
value: null
]
else
emtpy_clock_opts = []
hour_sel = new CUI.Select(
name: "hour"
data: data
group: "time"
onDataChanged: (_data) =>
if _data.hour == null
else
if am_pm
else
.position()
options: =>
opts = emtpy_clock_opts.slice(0)
if am_pm
for hour in [1..12]
opts.push
text: pad0(hour)
value: hour%12
else
for hour in [0..23]
opts.push
text: pad0(hour)
value: hour
opts
).start()
# minute_colon = new CUI.Label(text: ":")
minute_sel = new CUI.Select(
class: "cui-date-time-60-select"
name: "minute"
group: "time"
data: data
onDataChanged: (_data) =>
if _data.minute == null
else
.position()
options: =>
opts = emtpy_clock_opts.slice(0)
for minute in [0..59]
opts.push
text: pad0(minute)
value: minute
opts
).start()
if am_pm
am_pm_sel = new CUI.Select(
class: "cui-date-time-am-pm-select"
name: "am_pm"
group: "time"
data: data
onDataChanged: (_data) =>
if _data.am_pm == null
else
.position()
options: =>
opts = emtpy_clock_opts.slice(0)
for am_pm in ["AM", "PM"]
opts.push
text: am_pm
value: if am_pm == "AM" then 0 else 12 # offset in hours
opts
).start()
# second_colon = new CUI.Label(text: ":")
# second_sel = new CUI.Select(
# class: "cui-date-time-60-select"
# name: "second"
# data: data
# onDataChanged: =>
#
# options: =>
# opts = []
# for second in [0..59]
# opts.push
# text: pad0(second)
# value: second
# opts
# ).start()
new CUI.Buttonbar(
buttons: [
date_sel
month_sel
year_sel
hour_sel
# minute_colon
minute_sel
am_pm_sel
# second_colon
# second_sel
]
).DOM
drawYearMonthsSelect: (mom) ->
year = null
updateCalendar = =>
data =
month: mom.month()
year: mom.year()
month_opts = []
for m, idx in moment.months()
month_opts.push
text: m
value: idx
now_year = moment().year()
month_label_max_chars = 0
for opt in month_opts
if opt.text?.length > month_label_max_chars
month_label_max_chars = opt.text?.length
month_label = new CUI.Label
text: month_opts[data.month].text
month_label.setTextMaxChars(month_label_max_chars)
##### HEADER includes YEAR and MONTH
header_year_month = new CUI.HorizontalLayout
maximize_vertical: false
maximize_horizontal: true
class: "cui-date-time-footer"
left:
content: new CUI.Buttonbar
class: "cui-date-time-header-month"
buttons:
[
icon: "left"
onClick: (ev) =>
if mom.clone().subtract(1, "months").year() <
return
mom.subtract(1, "months")
,
month_label
# new CUI.Select(
# attr:
# cursor: "month"
# class: "cui-date-time-month-select"
# data: data
# name: "month"
# onShow: =>
#
# onHide: =>
#
# mark_changed: false
# onDataChanged: (_data, element, ev) =>
#
# options: month_opts
# ).start()
,
icon: "right"
onClick: (ev) =>
if mom.clone().add(1, "months").year() >
return
mom.add(1, "months")
]
right:
content: new CUI.Buttonbar
class: "cui-date-time-header-year"
buttons: [
icon: "left"
group: "year"
onClick: =>
if data.year - 1 <
return
mom.subtract(1, "years")
,
new CUI.NumberInput(
attr:
cursor: "year"
max:
min:
placeholder: ""+now_year
data: data
name: "year"
group: "year"
onDataChanged: (data) =>
if CUI.util.isEmpty(data.year)
year = now_year
else
year = data.year
CUI.scheduleCallback(ms: 500, call: updateCalendar)
).start()
,
icon: "right"
group: "year"
onClick: =>
if data.year + 1 >
return
mom.add(1, "years")
]
header_year_month.DOM
drawMonthTable: (_mom) ->
month = _mom.month()
year = _mom.year()
# set first day of month as start
mom = moment([
year
month
1
_mom.hour()
_mom.minute()
_mom.second()
0
]) # .utc()
month_table = CUI.dom.table("cui-date-time-date")
CUI.Events.listen
node: month_table
type: "click"
call: (ev) =>
ev.stopPropagation()
target = ev.getTarget()
# console.debug "click on date table", ev.getTarget()
if CUI.dom.closest(target, ".cui-date-time-day")
data = CUI.dom.data(CUI.dom.closest(target, "td,.cui-td"))
=
# order here is important, we need to set the month
# before we set the date!
.year(data.year)
.month(data.month)
.date(data.date)
if [0].clock
.position()
else
return
# Wk, Mo, Tu, We, Th...
tr = CUI.dom.tr("cui-date-time-month-header")
CUI.dom.append(month_table, tr)
td_func = CUI.dom.th
tabWeekDiv = CUI.dom.div("cui-date-time-dow")
tabWeekDiv.textContent = .tab_week
CUI.dom.append(tr, CUI.dom.append(td_func("cui-date-time-week-title"), tabWeekDiv))
for dow in [..+6]
weekday = moment.weekdaysMin(dow%7)
day_div = CUI.dom.div("cui-date-time-dow")
day_div.textContent = weekday
CUI.dom.addClass(day_div, "cui-date-time-day-"+weekday.toLowerCase())
CUI.dom.append(tr, CUI.dom.append(td_func(), day_div))
# Weeks
mom.subtract((mom.day()-+7)%7, "days")
dow =
weeks = 0
now = moment()
loop
curr_y = mom.year()
curr_m = mom.month()
day_no = mom.date()
if (dow-)%7 == 0
if weeks ==6
# if ((curr_m > m and date.getUTCFullYear() == year) or date.getUTCFullYear() > year)
break
tr = CUI.dom.tr()
CUI.dom.append(month_table, tr)
week_no = mom.week() #==0)
CUI.dom.append(tr, CUI.dom.append(CUI.dom.td("cui-date-time-week"), CUI.dom.text(week_no)))
weeks++
div_type = CUI.dom.td
day_span = CUI.dom.span()
day_span.textContent = day_no
day_div = div_type("cui-date-time-day", cursor: "day", datestr: [curr_y, curr_m, day_no].join("-"))
CUI.dom.append(day_div, day_span)
if curr_m < month
CUI.dom.addClass(day_div, "cui-date-time-previous-month")
else if curr_m > month
CUI.dom.addClass(day_div, "cui-date-time-next-month")
else
CUI.dom.addClass(day_div, "cui-date-time-same-month")
if year == now.year() and month == now.month() and day_no == now.date()
CUI.dom.addClass(day_div, "cui-date-time-now")
CUI.dom.addClass(day_div, "cui-date-time-day-"+mom.format("dd").toLowerCase())
td = day_div
CUI.dom.append(tr, td)
CUI.dom.data(td,
date: day_no
month: curr_m
year: curr_y
)
mom.add(1, "days")
dow++
month_table
markDay: ->
for el in CUI.dom.matchSelector(.DOM, ".cui-date-time-calendar .cui-date-time-selected")
CUI.dom.removeClass(el, "cui-date-time-selected")
# console.debug "markDay", , .__now
if .__now
return
datestr = [
.year()
.month()
.date()
].join("-")
# console.debug "markDay", datestr
for el in CUI.dom.matchSelector(, "[datestr=\"#{datestr}\"]")
CUI.dom.addClass(el, "cui-date-time-selected")
return
# drawHourMinute: ->
# if
#
# return
# = CUI.dom.table("cui-date-time-day-grid")
# .empty().append()
# CUI.Events.listen
# node:
# type: "click"
# call: (ev) =>
# if not
# return
# ev.stopPropagation()
# $target = $(ev.getTarget())
# # console.debug "clicked on ", $target
# if $target.closest(".cui-date-time-grid-hour").length
# hour = DOM.data($target.closest("td,.cui-td")[0], "hour")
# if [0].clock_am_pm
# current_hour = .hour()
# if current_hour < 12 # AM
# .hour(hour%12)
# else
# .hour(hour%12+12)
# else
# .hour(hour)
# .second(0)
# if .minute() % 5 != 0
# .minute(0)
# if [0].clock_am_pm
# cursor = "am_pm"
# else
# cursor = "minute"
# if $target.closest(".cui-date-time-grid-am-pm").length
# current_hour = .hour()
# am_pm = $target.closest("td,.cui-td").data("am_pm")
# if am_pm == "AM"
# if current_hour >= 12
# .hour(current_hour-12)
# else
# if current_hour < 12
# .hour(current_hour+12)
# .second(0)
# cursor = "minute"
# if $target.closest(".cui-date-time-grid-minute").length
# .minute(DOM.data($target.closest("td,.cui-td")[0], "minute"))
# .second(0)
# cursor = "blur"
# delete(.__now)
#
#
# if cursor == "blur"
#
# else
#
# return
# #CUI.dom.tr().appendTo(table).append(
# # CUI.dom.td("cui-date-time-hour-minute-label", colspan: 6).append(CUI.dom.text("Hour"))
# #)
# if not [0].clock_am_pm
# for hour in [0..23]
# if hour % 6 == 0
# tr = CUI.dom.tr("cui-date-time-grid-hour-row").appendTo()
# tr.append(
# td = CUI.dom.td("cui-date-time-grid-hour")
# .setAttribute("hour", hour)
# .append(CUI.dom.text(hour))
# )
# DOM.data(td[0], "hour", hour)
# tr.addClass("cui-date-time-grid-row-last")
# else
# for hour in [1..12]
# if (hour-1) % 6 == 0
# tr = CUI.dom.tr("cui-date-time-grid-hour-row").appendTo()
# tr.append(
# td = CUI.dom.td("cui-date-time-grid-hour")
# .setAttribute("hour", hour)
# .append(CUI.dom.text(hour))
# )
# DOM.data(td[0], "hour", hour)
# tr.addClass("cui-date-time-grid-row-last")
# # ----------------------
# tr = CUI.dom.tr("cui-date-time-grid-am-pm-row").appendTo()
# for am_pm in ["AM","PM"]
# tr.append(
# td = CUI.dom.td("cui-date-time-grid-am-pm")
# .setAttribute("am_pm", am_pm)
# .append(CUI.dom.text(am_pm))
# )
# DOM.data(td[0], "am_pm", am_pm)
# tr.append(CUI.dom.td("",colspan:4))
# tr.addClass("cui-date-time-grid-row-last")
# #CUI.dom.tr().appendTo(table).append(
# # CUI.dom.td("cui-date-time-hour-minute-label", colspan: 6).append(CUI.dom.text("Minute"))
# #)
# for minute in [0..59] by 5
# if minute % 6 == 0
# tr = CUI.dom.tr("cui-date-time-grid-minute-row").appendTo()
# if minute < 10
# _minute = ":0"+minute
# else
# _minute = ":"+minute
# tr.append(
# td = CUI.dom.td("cui-date-time-grid-minute")
# .setAttribute("minute", minute)
# .append(CUI.dom.text(_minute))
# )
# DOM.data(td[0], "minute", minute)
# tr.addClass("cui-date-time-grid-minute-row-last")
#
# return
# markTime: ->
# .DOM.find(".cui-date-time-day-grid .cui-date-time-selected").removeClass("cui-date-time-selected")
# for k in ["hour", "minute"]
# if .__now
# continue
# units = [k]()
# if k == "hour" and [0].clock_am_pm
# units = (units+11)%12+1 # convert hours in visible hour format
# if k == "minute"
# units = units - (units % 5)
# .find("[#{k}=\"#{units}\"]").addClass("cui-date-time-selected")
# if [0].clock_am_pm
# for _c in .find("[am_pm]")
# c = _c
# if .__now
# continue
# if .hour() < 12
# if c.getAttribute("am_pm") == "AM"
# c.addClass("cui-date-time-selected")
# else
# if c.getAttribute("am_pm") == "PM"
# c.addClass("cui-date-time-selected")
# return
# Keys when try parsing
: ["store", "input", "display", "display_short"]
: (locale) ->
CUI.util.assert(CUI.DateTimeFormats[locale], "CUI.DateTime.setLocale", "Locale #{locale} unknown", DateTimeFormats: CUI.DateTimeFormats)
CUI.DateTime.__locale = locale
: ->
if CUI.DateTime.__locale
locale = CUI.DateTime.__locale
else
for locale of CUI.DateTimeFormats
break
return locale
# format the date_str
# output_format "display_short", "display", "store", "input"
# output_type "date_time", "date", "date_time_secons", "year_month",v "year"
: (datestr_or_moment, output_format, output_type) ->
dt = new CUI.DateTime()
str = dt.format(datestr_or_moment, output_format, output_type)
# console.debug "DateTime.format", date, type, output_type, DateTime.__locale, str
str
# limit output to the given types
# the library is very awkward here...
: (datestr, output_types, output_format) ->
if not datestr
return null
dt = new CUI.DateTime(input_types: output_types)
mom = dt.parseValue(datestr)
if not mom.isValid()
return null
dt.format(mom, output_format)
: (datestr_or_moment, opts={}) ->
if not opts.hasOwnProperty("input_types")
opts.input_types = null
dt = new CUI.DateTime(opts)
mom = dt.parseValue(datestr_or_moment)
if not mom.isValid()
return null
: (mom, format) ->
if mom.bc
return "-"+mom.bc
return mom.format(format)
# BC appendix always adds one year. Therefore year 0 is 1 BC.
: (mom, format) ->
if mom.year() == 0
return "1 #{CUI.DateTime.defaults.bc_appendix[0]}"
if mom.bc
bc = parseInt(mom.bc) + 1
return "#{(bc)} #{CUI.DateTime.defaults.bc_appendix[0]}"
if mom.year() > 0
v = mom.format(format)
# remove the "+"
return v.replace("+"+mom.year(), ""+mom.year())
mom.subtract(1, "year")
v = mom.format(format) + " " + CUI.DateTime.defaults.bc_appendix[0]
# remove the "-"
return v.replace(mom.year(), ""+(-1 * mom.year()))
: (datestr) ->
if CUI.util.isEmpty(datestr)
return null
dt = new CUI.DateTime(input_types: null)
dt.parse(datestr)
: (string) ->
return CUI.DateTimeRangeGrammar.stringToDateRange(string)
: (from, to) ->
return CUI.DateTimeRangeGrammar.dateRangeToString(from, to)