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