001// Licensed under the Apache License, Version 2.0 (the "License"); 002// you may not use this file except in compliance with the License. 003// You may obtain a copy of the License at 004// 005// http://www.apache.org/licenses/LICENSE-2.0 006// 007// Unless required by applicable law or agreed to in writing, software 008// distributed under the License is distributed on an "AS IS" BASIS, 009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 010// See the License for the specific language governing permissions and 011// limitations under the License. 012 013package org.apache.tapestry5.corelib.components; 014 015import org.apache.tapestry5.ComponentResources; 016import org.apache.tapestry5.MarkupWriter; 017import org.apache.tapestry5.annotations.Import; 018import org.apache.tapestry5.annotations.Parameter; 019import org.apache.tapestry5.annotations.SupportsInformalParameters; 020import org.apache.tapestry5.ioc.annotations.Inject; 021import org.apache.tapestry5.services.DateUtilities; 022 023import java.util.Date; 024 025/** 026 * Used to present an interval value using Moment.js's from() or fromNow() functions. The interval 027 * is determined in terms of a start and end date; either (but not both) may be omitted, in which 028 * case the client will dynamically update the element. In that case, the value will live update, approximately every second. 029 * 030 * This component will render an empty element. The element will match the template element, 031 * or a "span" if the template did not provide an element. Informal parameters will be rendered 032 * into the element. 033 * 034 * When the end date is after the start date, the rendered text will be prefixed with "in". 035 * When the end date precedes the start date, the rendered text will be suffixed with "ago". 036 * The plain parameter is used to turn off the prefix or suffix. 037 * 038 * @tapestrydoc 039 * @see LocalDate 040 * @since 5.4 041 */ 042@SupportsInformalParameters 043@Import(module = "t5/core/time-interval") 044public class TimeInterval 045{ 046 /** 047 * The start date for the interval. If omitted, the start time is considered "now" and will automatically 048 * update in the browser. 049 */ 050 @Parameter 051 Date start; 052 053 /** 054 * The end date for the interval. If omitted, the end time is considered "now" and will update automatically 055 * in the browser. 056 */ 057 @Parameter() 058 Date end; 059 060 /** 061 * If true, then output is plain: no "in" prefix or "ago" suffix. 062 */ 063 @Parameter 064 boolean plain; 065 066 @Inject 067 ComponentResources resources; 068 069 @Inject 070 DateUtilities dateUtilities; 071 072 private String toISO(Date date) 073 { 074 return date == null ? null : dateUtilities.formatISO8601(date); 075 } 076 077 boolean beginRender(MarkupWriter writer) 078 { 079 writer.element(resources.getElementName("span"), 080 // Trigger the client-side logic: 081 "data-timeinterval", "true", 082 "data-timeinterval-start", toISO(start), 083 "data-timeinterval-end", toISO(end)); 084 085 if (plain) 086 { 087 writer.attributes("data-timeinterval-plain", true); 088 } 089 090 resources.renderInformalParameters(writer); 091 092 writer.end(); 093 094 // Skip the body regardless. 095 return false; 096 } 097 098}