Skip to content

Commit

Permalink
Merge pull request #67 from github/custom-elements-v1
Browse files Browse the repository at this point in the history
Use Custom Elements v1 API
  • Loading branch information
muan committed Jan 3, 2018
2 parents a13a1fb + 63d460c commit 90a1745
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 153 deletions.
2 changes: 1 addition & 1 deletion examples/polymer.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/0.7.23/webcomponents.min.js"></script>
<script src="../dist/time-elements-legacy.js"></script>
</head>
<body>
<h2>Past Date</h2>
Expand Down Expand Up @@ -91,5 +90,6 @@ <h2>Future Date</h2>
Oops! This browser doesn't support Web Components.
</time>
</p>
<script src="../dist/time-elements-legacy.js"></script>
</body>
</html>
98 changes: 48 additions & 50 deletions src/extended-time-element.js
Original file line number Diff line number Diff line change
@@ -1,63 +1,61 @@
import {makeFormatter} from './utils'

const ExtendedTimePrototype = Object.create(HTMLElement.prototype)

// Internal: Refresh the time element's formatted date when an attribute changes.
//
// Returns nothing.
ExtendedTimePrototype.attributeChangedCallback = function(attrName, oldValue, newValue) {
if (attrName === 'datetime') {
const millis = Date.parse(newValue)
this._date = isNaN(millis) ? null : new Date(millis)
}

const title = this.getFormattedTitle()
if (title) {
this.setAttribute('title', title)
export default class ExtendedTimeElement extends HTMLElement {
static get observedAttributes() {
return ['datetime', 'day', 'format', 'hour', 'minute', 'month', 'second', 'title', 'weekday', 'year']
}

const text = this.getFormattedDate()
if (text) {
this.textContent = text
}
}
// Internal: Refresh the time element's formatted date when an attribute changes.
//
// Returns nothing.
attributeChangedCallback(attrName, oldValue, newValue) {
if (attrName === 'datetime') {
const millis = Date.parse(newValue)
this._date = isNaN(millis) ? null : new Date(millis)
}

// Internal: Format the ISO 8601 timestamp according to the user agent's
// locale-aware formatting rules. The element's existing `title` attribute
// value takes precedence over this custom format.
//
// Returns a formatted time String.
ExtendedTimePrototype.getFormattedTitle = function() {
if (!this._date) {
return
}
const title = this.getFormattedTitle()
if (title && !this.hasAttribute('title')) {
this.setAttribute('title', title)
}

if (this.hasAttribute('title')) {
return this.getAttribute('title')
const text = this.getFormattedDate()
if (text) {
this.textContent = text
}
}

const formatter = makeFormatter({
day: 'numeric',
month: 'short',
year: 'numeric',
hour: 'numeric',
minute: '2-digit',
timeZoneName: 'short'
})
// Internal: Format the ISO 8601 timestamp according to the user agent's
// locale-aware formatting rules. The element's existing `title` attribute
// value takes precedence over this custom format.
//
// Returns a formatted time String.
getFormattedTitle() {
if (!this._date) {
return
}

if (formatter) {
return formatter.format(this._date)
} else {
try {
return this._date.toLocaleString()
} catch (e) {
if (e instanceof RangeError) {
return this._date.toString()
} else {
throw e
const formatter = makeFormatter({
day: 'numeric',
month: 'short',
year: 'numeric',
hour: 'numeric',
minute: '2-digit',
timeZoneName: 'short'
})

if (formatter) {
return formatter.format(this._date)
} else {
try {
return this._date.toLocaleString()
} catch (e) {
if (e instanceof RangeError) {
return this._date.toString()
} else {
throw e
}
}
}
}
}

export default ExtendedTimePrototype
69 changes: 27 additions & 42 deletions src/local-time-element.js
Original file line number Diff line number Diff line change
@@ -1,46 +1,32 @@
import {strftime, makeFormatter, isDayFirst} from './utils'
import ExtendedTimePrototype from './extended-time-element'
import ExtendedTimeElement from './extended-time-element'

const LocalTimePrototype = Object.create(ExtendedTimePrototype)

LocalTimePrototype.createdCallback = function() {
let value

value = this.getAttribute('datetime')
if (value) {
this.attributeChangedCallback('datetime', null, value)
}

value = this.getAttribute('format')
if (value) {
this.attributeChangedCallback('format', null, value)
}
}
export default class LocalTimeElement extends ExtendedTimeElement {
// Formats the element's date, in the user's current locale, according to
// the formatting attribute values. Values are not passed straight through to
// an Intl.DateTimeFormat instance so that weekday and month names are always
// displayed in English, for now.
//
// Supported attributes are:
//
// weekday - "short", "long"
// year - "numeric", "2-digit"
// month - "short", "long"
// day - "numeric", "2-digit"
// hour - "numeric", "2-digit"
// minute - "numeric", "2-digit"
// second - "numeric", "2-digit"
//
// Returns a formatted time String.
getFormattedDate() {
if (!this._date) {
return
}

// Formats the element's date, in the user's current locale, according to
// the formatting attribute values. Values are not passed straight through to
// an Intl.DateTimeFormat instance so that weekday and month names are always
// displayed in English, for now.
//
// Supported attributes are:
//
// weekday - "short", "long"
// year - "numeric", "2-digit"
// month - "short", "long"
// day - "numeric", "2-digit"
// hour - "numeric", "2-digit"
// minute - "numeric", "2-digit"
// second - "numeric", "2-digit"
//
// Returns a formatted time String.
LocalTimePrototype.getFormattedDate = function() {
if (!this._date) {
return
const date = formatDate(this) || ''
const time = formatTime(this) || ''
return `${date} ${time}`.trim()
}

const date = formatDate(this) || ''
const time = formatTime(this) || ''
return `${date} ${time}`.trim()
}

// Private: Format a date according to the `weekday`, `day`, `month`,
Expand Down Expand Up @@ -132,6 +118,5 @@ function formatTime(el) {
// var time = new LocalTimeElement()
// # => <local-time></local-time>
//
window.LocalTimeElement = document.registerElement('local-time', {
prototype: LocalTimePrototype
})
window.LocalTimeElement = LocalTimeElement
window.customElements.define('local-time', LocalTimeElement)
58 changes: 24 additions & 34 deletions src/relative-time-element.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,33 @@
import RelativeTime from './relative-time'
import ExtendedTimePrototype from './extended-time-element'
import ExtendedTimeElement from './extended-time-element'

const RelativeTimePrototype = Object.create(ExtendedTimePrototype)

RelativeTimePrototype.createdCallback = function() {
const value = this.getAttribute('datetime')
if (value) {
this.attributeChangedCallback('datetime', null, value)
}
}

RelativeTimePrototype.getFormattedDate = function() {
if (this._date) {
return new RelativeTime(this._date).toString()
export default class RelativeTimeElement extends ExtendedTimeElement {
getFormattedDate() {
if (this._date) {
return new RelativeTime(this._date).toString()
}
}
}

RelativeTimePrototype.attachedCallback = function() {
nowElements.push(this)
connectedCallback() {
nowElements.push(this)

if (!updateNowElementsId) {
updateNowElements()
updateNowElementsId = setInterval(updateNowElements, 60 * 1000)
if (!updateNowElementsId) {
updateNowElements()
updateNowElementsId = setInterval(updateNowElements, 60 * 1000)
}
}
}

RelativeTimePrototype.detachedCallback = function() {
const ix = nowElements.indexOf(this)
if (ix !== -1) {
nowElements.splice(ix, 1)
}
disconnectedCallback() {
const ix = nowElements.indexOf(this)
if (ix !== -1) {
nowElements.splice(ix, 1)
}

if (!nowElements.length) {
if (updateNowElementsId) {
clearInterval(updateNowElementsId)
updateNowElementsId = null
if (!nowElements.length) {
if (updateNowElementsId) {
clearInterval(updateNowElementsId)
updateNowElementsId = null
}
}
}
}
Expand All @@ -61,8 +54,5 @@ function updateNowElements() {
// var time = new RelativeTimeElement()
// # => <relative-time></relative-time>
//
window.RelativeTimeElement = document.registerElement('relative-time', {
prototype: RelativeTimePrototype
})

export default RelativeTimePrototype
window.RelativeTimeElement = RelativeTimeElement
window.customElements.define('relative-time', RelativeTimeElement)
25 changes: 12 additions & 13 deletions src/time-ago-element.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import RelativeTime from './relative-time'
import RelativeTimePrototype from './relative-time-element'
import RelativeTimeElement from './relative-time-element'

const TimeAgoPrototype = Object.create(RelativeTimePrototype)

TimeAgoPrototype.getFormattedDate = function() {
if (this._date) {
const format = this.getAttribute('format')
if (format === 'micro') {
return new RelativeTime(this._date).microTimeAgo()
} else {
return new RelativeTime(this._date).timeAgo()
export default class TimeAgoElement extends RelativeTimeElement {
getFormattedDate() {
if (this._date) {
const format = this.getAttribute('format')
if (format === 'micro') {
return new RelativeTime(this._date).microTimeAgo()
} else {
return new RelativeTime(this._date).timeAgo()
}
}
}
}

window.TimeAgoElement = document.registerElement('time-ago', {
prototype: TimeAgoPrototype
})
window.TimeAgoElement = TimeAgoElement
window.customElements.define('time-ago', TimeAgoElement)
25 changes: 12 additions & 13 deletions src/time-until-element.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import RelativeTime from './relative-time'
import RelativeTimePrototype from './relative-time-element'
import RelativeTimeElement from './relative-time-element'

const TimeUntilPrototype = Object.create(RelativeTimePrototype)

TimeUntilPrototype.getFormattedDate = function() {
if (this._date) {
const format = this.getAttribute('format')
if (format === 'micro') {
return new RelativeTime(this._date).microTimeUntil()
} else {
return new RelativeTime(this._date).timeUntil()
export default class TimeUntilElement extends RelativeTimeElement {
getFormattedDate() {
if (this._date) {
const format = this.getAttribute('format')
if (format === 'micro') {
return new RelativeTime(this._date).microTimeUntil()
} else {
return new RelativeTime(this._date).timeUntil()
}
}
}
}

window.TimeUntilElement = document.registerElement('time-until', {
prototype: TimeUntilPrototype
})
window.TimeUntilElement = TimeUntilElement
window.customElements.define('time-until', TimeUntilElement)

0 comments on commit 90a1745

Please sign in to comment.