001/*
002 *  Copyright 2012 GWT-Bootstrap
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package com.github.gwtbootstrap.datepicker.client.ui.base;
017
018import java.util.Date;
019
020import com.github.gwtbootstrap.client.ui.TextBox;
021import com.github.gwtbootstrap.client.ui.base.HasAlternateSize;
022import com.github.gwtbootstrap.client.ui.base.HasId;
023import com.github.gwtbootstrap.client.ui.base.HasPlaceholder;
024import com.github.gwtbootstrap.client.ui.base.HasSize;
025import com.github.gwtbootstrap.client.ui.base.HasStyle;
026import com.github.gwtbootstrap.client.ui.base.HasVisibility;
027import com.github.gwtbootstrap.client.ui.base.HasVisibleHandlers;
028import com.github.gwtbootstrap.client.ui.base.IsResponsive;
029import com.github.gwtbootstrap.client.ui.base.IsSearchQuery;
030import com.github.gwtbootstrap.client.ui.base.PlaceholderHelper;
031import com.github.gwtbootstrap.client.ui.base.ResponsiveHelper;
032import com.github.gwtbootstrap.client.ui.base.SearchQueryStyleHelper;
033import com.github.gwtbootstrap.client.ui.base.SizeHelper;
034import com.github.gwtbootstrap.client.ui.base.Style;
035import com.github.gwtbootstrap.client.ui.base.StyleHelper;
036import com.github.gwtbootstrap.client.ui.constants.AlternateSize;
037import com.github.gwtbootstrap.client.ui.constants.Device;
038import com.github.gwtbootstrap.client.ui.event.HiddenHandler;
039import com.github.gwtbootstrap.client.ui.event.HideEvent;
040import com.github.gwtbootstrap.client.ui.event.HideHandler;
041import com.github.gwtbootstrap.client.ui.event.ShowEvent;
042import com.github.gwtbootstrap.client.ui.event.ShowHandler;
043import com.github.gwtbootstrap.client.ui.event.ShownHandler;
044import com.github.gwtbootstrap.datepicker.client.ui.util.LocaleUtil;
045import com.google.gwt.core.client.GWT;
046import com.google.gwt.dom.client.Element;
047import com.google.gwt.editor.client.IsEditor;
048import com.google.gwt.editor.client.adapters.TakesValueEditor;
049import com.google.gwt.event.dom.client.ChangeEvent;
050import com.google.gwt.event.dom.client.ChangeHandler;
051import com.google.gwt.event.dom.client.HasChangeHandlers;
052import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
053import com.google.gwt.event.logical.shared.ValueChangeEvent;
054import com.google.gwt.event.logical.shared.ValueChangeHandler;
055import com.google.gwt.event.shared.HandlerRegistration;
056import com.google.gwt.i18n.client.DateTimeFormat;
057import com.google.gwt.user.client.ui.HasValue;
058import com.google.gwt.user.client.ui.Widget;
059
060/**
061 * Base DatePicker component.
062 *
063 * @author Carlos Alexandro Becker
064 * @author ohashi keisuke
065 * @since 2.0.4.0
066 */
067public class DateBoxBase extends Widget implements HasValue<Date>, HasValueChangeHandlers<Date>, HasVisibility,
068        HasChangeHandlers, HasVisibleHandlers, HasAllDatePickerHandlers, IsEditor<TakesValueEditor<Date>>, HasPlaceholder, HasAlternateSize, IsSearchQuery, HasSize, HasId, IsResponsive , HasStyle {
069
070    private final TextBox box;
071    private String format;
072    private String language;
073    private DateTimeFormat dtf;
074    private TakesValueEditor<Date> editor;
075
076    /** placeholderHelper */
077    private PlaceholderHelper placeholderHelper = GWT.create(PlaceholderHelper.class);
078
079    public DateBoxBase() {
080        this.box = new TextBox();
081        setElement(box.getElement());
082        setFormat("mm/dd/yyyy");
083        this.language = LocaleUtil.getLanguage();
084        setValue(new Date());
085    }
086
087    /**
088     * {@inheritDoc}
089     */
090    @Override
091    public void setFormat(String format) {
092        this.format = format;
093        Date oldValue = getValue();
094        this.dtf = DateTimeFormat.getFormat(format.replaceAll("mm", "MM"));
095        if (oldValue != null) {
096            setValue(oldValue);
097        }
098    }
099
100    public void setLanguage(String language) {
101        this.language = language;
102        LocaleUtil.forceLocale(language);
103    }
104
105    /**
106     * Returns the internal instance of textbox element. Use only if know what you are doing.
107     *
108     * @return internal textbox intance.
109     */
110    protected TextBox getBox() {
111        return box;
112    }
113
114    /**
115     * {@inheritDoc}
116     */
117    @Override
118    public Date getValue() {
119        try {
120            return dtf != null && box.getValue() != null ? dtf.parse(box.getValue()) : null;
121        } catch(Exception e) {
122            return null;
123        }
124    }
125    
126    /**
127     * Get un-tranceform text
128     * @return text box value
129     */
130    public String getOriginalValue() {
131        return box.getValue();
132    }
133
134    /**
135     * {@inheritDoc}
136     */
137    @Override
138    public void setValue(Date value) {
139        setValue(value, false);
140    }
141
142    /**
143     * {@inheritDoc}
144     */
145    @Override
146    public void setValue(Date value, boolean fireEvents) {
147        box.setValue(value != null ? dtf.format(value) : null);
148        
149        updateValue(box.getElement());
150        
151        if (fireEvents) {
152            ValueChangeEvent.fire(this, value);
153        }
154    }
155    
156    protected native void updateValue(Element e)/*-{
157        if($wnd.jQuery(e).data('datepicker')) {
158            $wnd.jQuery(e).data('datepicker').update();
159        }
160    }-*/;
161
162    /**
163     * {@inheritDoc}
164     */
165    @Override
166    public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Date> dateValueChangeHandler) {
167        return addHandler(dateValueChangeHandler, ValueChangeEvent.getType());
168    }
169
170    /**
171     * {@inheritDoc}
172     */
173    @Override
174    protected void onLoad() {
175        super.onLoad();
176        configure();
177    }
178
179    /**
180     * Configure the elements for a specific widget.
181     * Use only if you know what you are doing.
182     *
183     * @param w: the widget to configure.
184     */
185    protected void configure(Widget w) {
186        w.getElement().setAttribute("data-date-format", format);
187        w.getElement().setAttribute("data-date-language", language);
188        configure(w.getElement());
189    }
190
191    /**
192     * dateChange event handler.
193     */
194    public void onChange() {
195        ValueChangeEvent.fire(this, getValue());
196    }
197    
198    public void onShow() {
199        fireEvent(new ShowEvent());
200    }
201    
202    public void onHide() {
203        fireEvent(new HideEvent());
204    }
205    public void reconfigure() {
206        removeDataIfExists(getElement());
207        configure();
208    }
209
210    /**
211     * configure this datepicker.
212     */
213    protected void configure() {
214        configure(this);
215    }
216    
217    protected native void removeDataIfExists(Element e) /*-{
218        var $that = $wnd.jQuery(e);
219        if($that.data('datepicker')) {
220            console.log($that.data());
221            $that.removeData('dateFormat');
222            $that.removeData('dateLanguage');
223            $that.removeData('dateWeekstart');
224            $that.removeData('dateStartdate');
225            $that.removeData('dateEnddate');
226            $that.removeData('datepicker');
227            $that.off();
228            console.log($that.data());
229        }
230    }-*/;
231
232    /**
233     * call jquery datepicker plugin in a element.
234     *
235     * @param e: Element that will be transformed in a datepicker.
236     */
237    protected native void configure(Element e) /*-{
238        var that = this;
239        $wnd.jQuery(e).datepicker();
240        $wnd.jQuery(e).on('change' , function() {
241            that.@com.github.gwtbootstrap.datepicker.client.ui.base.DateBoxBase::onChange()();
242        });
243        $wnd.jQuery(e).datepicker().on("show", function () {
244            that.@com.github.gwtbootstrap.datepicker.client.ui.base.DateBoxBase::onShow()();
245        });
246        $wnd.jQuery(e).datepicker().on("hide", function () {
247            that.@com.github.gwtbootstrap.datepicker.client.ui.base.DateBoxBase::onHide()();
248        });
249    }-*/;
250
251    private native void execute(Element e, String cmd) /*-{
252        $wnd.jQuery(e).datepicker(cmd);
253    }-*/;
254
255    private void execute(String cmd) {
256        execute(getElement(), cmd);
257    }
258
259    /**
260     * {@inheritDoc}
261     */
262    @Override
263    public void show() {
264        execute("show");
265    }
266
267    /**
268     * {@inheritDoc}
269     */
270    @Override
271    public void hide() {
272        execute("hide");
273    }
274
275    /**
276     * {@inheritDoc}
277     */
278    @Override
279    public void toggle() {
280        //TODO 2012/06/21 ohashi keisuke shoud be support
281        throw new UnsupportedOperationException("not support toggle");
282    }
283
284    /**
285     * {@inheritDoc}
286     */
287    @Override
288    public HandlerRegistration addHideHandler(HideHandler handler) {
289        return addHandler(handler, HideEvent.getType());
290    }
291
292    /**
293     * {@inheritDoc}
294     */
295    @Override
296    public HandlerRegistration addHiddenHandler(HiddenHandler handler) {
297        //TODO 2012/06/21 ohashi keisuke shoud be support
298        throw new UnsupportedOperationException("not support hidden event");
299    }
300
301    /**
302     * {@inheritDoc}
303     */
304    @Override
305    public HandlerRegistration addShowHandler(ShowHandler handler) {
306        return addHandler(handler, ShowEvent.getType());
307    }
308
309    /**
310     * {@inheritDoc}
311     */
312    @Override
313    public HandlerRegistration addShownHandler(ShownHandler handler) {
314        //TODO 2012/06/21 ohashi keisuke shoud be support
315        throw new UnsupportedOperationException("not support shown event");
316    }
317
318    /**
319     * {@inheritDoc}
320     */
321    @Override
322    public void setWeekStart(int start) {
323        getElement().setAttribute("data-date-weekstart", start + "");
324    }
325
326    /**
327     * {@inheritDoc}
328     */
329    @Override
330    public void setStartDate(String startDate) {
331        getElement().setAttribute("data-date-startdate", startDate);
332    }
333
334    /**
335     * {@inheritDoc}
336     */
337    @Override
338    public void setStartDate_(Date startDate) {
339        setStartDate(dtf.format(startDate));
340    }
341
342
343    /**
344     * {@inheritDoc}
345     */
346    @Override
347    public void setEndDate(String endDate) {
348        getElement().setAttribute("data-date-enddate", endDate);
349    }
350
351    /**
352     * {@inheritDoc}
353     */
354    @Override
355    public void setEndDate_(Date endDate) {
356        setEndDate(dtf.format(endDate));
357    }
358
359    /**
360     * {@inheritDoc}
361     */
362    @Override
363    public void setAutoClose(boolean autoclose) {
364        getElement().setAttribute("data-date-autoclose", autoclose + "");
365    }
366
367    /**
368     * {@inheritDoc}
369     */
370    @Override
371    public void setStartView(ViewMode mode) {
372        setStartView(mode.name());
373    }
374
375    /**
376     * {@inheritDoc}
377     */
378    @Override
379    public void setStartView(String mode) {
380        getElement().setAttribute("data-date-startview", mode.toLowerCase());
381    }
382
383        /**
384         * Retuen Editor
385         * @return editor
386         */
387        @Override
388        public TakesValueEditor<Date> asEditor() {
389                if(editor == null){
390                        editor = TakesValueEditor.of(this);
391                }
392                return editor;
393        }
394
395    @Override
396    public HandlerRegistration addChangeHandler(ChangeHandler handler) {
397        return addHandler(handler, ChangeEvent.getType());
398    }
399
400    /**
401     * {@inheritDoc}
402     */
403    @Override
404    public void setPlaceholder(String placeholder) {
405        placeholderHelper.setPlaceholer(getElement(), placeholder);
406    }
407
408    /**
409     * {@inheritDoc}
410     */
411    @Override
412    public String getPlaceholder() {
413        return placeholderHelper.getPlaceholder(getElement());
414    }
415
416    /**
417     * {@inheritDoc}
418     */
419    @Override
420    public void setSearchQuery(boolean searchQuery) {
421        SearchQueryStyleHelper.setSearchQuery(this, searchQuery);
422    }
423
424    /**
425     * {@inheritDoc}
426     */
427    @Override
428    public boolean isSearchQuery() {
429        return SearchQueryStyleHelper.isSearchQuery(this);
430    }
431
432    /**
433     * {@inheritDoc}
434     */
435    @Override
436    public void setAlternateSize(AlternateSize size) {
437        StyleHelper.changeStyle(this, size, AlternateSize.class);
438    }
439
440    /**
441     * {@inheritDoc}
442     */
443    @Override
444    public void setSize(int size) {
445        SizeHelper.setSize(this, size);
446    }
447
448    /**
449     * {@inheritDoc}
450     */
451    @Override
452    public String getId() {
453        return getElement().getId();
454    }
455
456    /**
457     * {@inheritDoc}
458     */
459    @Override
460    public void setId(String id) {
461        getElement().setId(id);
462    }
463
464    /**
465     * {@inheritDoc}
466     */
467    @Override
468    public void setShowOn(Device device) {
469        ResponsiveHelper.setShowOn(this, device);
470    }
471
472    /**
473     * {@inheritDoc}
474     */
475    @Override
476    public void setHideOn(Device device) {
477        ResponsiveHelper.setHideOn(this, device);
478        
479    }
480
481    /**
482     * {@inheritDoc}
483     */
484    @Override
485    public void setStyle(Style style) {
486        StyleHelper.setStyle(this, style);
487    }
488
489    /**
490     * {@inheritDoc}
491     */
492    @Override
493    public void addStyle(Style style) {
494        StyleHelper.addStyle(this, style);
495    }
496
497    /**
498     * {@inheritDoc}
499     */
500    @Override
501    public void removeStyle(Style style) {
502        StyleHelper.removeStyle(this, style);
503        
504    }
505}