Skip to content

Commit

Permalink
Added a new 'date' filter that works with jQuery UI datepicker to con…
Browse files Browse the repository at this point in the history
…strain a 'text' entry to a date; added jquery in 3rd-part including minimum jQuery UI and CSS for the datepicker; trim spaces when saving in the 'file' plugin.
  • Loading branch information
ssire committed Mar 14, 2012
1 parent baadbf9 commit 8514934
Show file tree
Hide file tree
Showing 23 changed files with 673 additions and 9 deletions.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
354 changes: 354 additions & 0 deletions 3rd-part/jquery/css/ui-lightness/jquery-ui-1.8.18.custom.css

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions 3rd-part/jquery/js/jquery-1.7.1.min.js

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions 3rd-part/jquery/js/jquery-ui-1.8.18.custom.min.js

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions editor/editor.xhtml
Expand Up @@ -16,7 +16,12 @@ Author: Stephane Sire
<meta name="keywords" content="template, XTiger, XML"></meta>

<!-- Dependency for some filters -->
<script type="text/javascript" src="../3rd-part/jquery-1.5.1.min.js"></script>
<!-- <script type="text/javascript" src="../3rd-part/jquery-1.5.1.min.js"></script> -->
<script src="../3rd-part/jquery/js/jquery-1.7.1.min.js" type="text/javascript"></script>

<!-- Dependency for 'date' filter -->
<link rel="stylesheet" href="../3rd-part/jquery/css/ui-lightness/jquery-ui-1.8.18.custom.css" type="text/css" charset="utf-8" />
<script src="../3rd-part/jquery/js/jquery-ui-1.8.18.custom.min.js" type="text/javascript"></script>

<!-- BEGIN XTiger Library Loading -->
<script type="text/javascript" src="../src/core/loader.js"></script>
Expand Down Expand Up @@ -72,7 +77,8 @@ Author: Stephane Sire
<script type="text/javascript" src="../src/filters/video.js"></script>
<script type="text/javascript" src="../src/filters/autocomplete.js"></script>
<script type="text/javascript" src="../src/filters/debug.js"></script>
<script type="text/javascript" src="../src/filters/service.js"></script>
<script type="text/javascript" src="../src/filters/service.js"></script>
<script type="text/javascript" src="../src/filters/date.js"></script>

<!-- contributions -->
<script type="text/javascript" src="../contribs/src/schemas/schemalogger.js"></script>
Expand Down
9 changes: 9 additions & 0 deletions editor/editornoframe.xhtml
Expand Up @@ -17,6 +17,14 @@ Author: Stephane Sire
<link rel="stylesheet" href="../axel/axel.css" type="text/css"></link>
<link rel="stylesheet" href="../axel/bundles/photo/photo.css" type="text/css"></link>

<!-- Dependency for some filters -->
<!-- <script type="text/javascript" src="../3rd-part/jquery-1.5.1.min.js"></script> -->
<script src="../3rd-part/jquery/js/jquery-1.7.1.min.js" type="text/javascript"></script>

<!-- Dependency for 'date' filter -->
<link rel="stylesheet" href="../3rd-part/jquery/css/ui-lightness/jquery-ui-1.8.18.custom.css" type="text/css" charset="utf-8" />
<script src="../3rd-part/jquery/js/jquery-ui-1.8.18.custom.min.js" type="text/javascript"></script>

<!-- BEGIN XTiger Library Loading -->
<script type="text/javascript" src="../src/core/loader.js"></script>
<script type="text/javascript" src="../src/core/dom.js"></script>
Expand Down Expand Up @@ -69,6 +77,7 @@ Author: Stephane Sire
<script type="text/javascript" src="../src/filters/autocomplete.js"></script>
<script type="text/javascript" src="../src/filters/debug.js"></script>
<script type="text/javascript" src="../src/filters/service.js"></script>
<script type="text/javascript" src="../src/filters/date.js"></script>

<!-- contributions -->
<script type="text/javascript" src="../contribs/src/schemas/schemalogger.js"></script>
Expand Down
12 changes: 6 additions & 6 deletions src/devices/text.js
Expand Up @@ -170,7 +170,7 @@
if (this.currentEditor) {
// another editing was in progress with the same device
// this is unlikely to happen as when directly clicking another field will trigger unfocus first
this.stopEditing (true);
this.stopEditing (true);
} else {
// registers to keyboard events
this._kbdHandlers = this.keyboard.register(this);
Expand All @@ -183,11 +183,11 @@
if (!doSelectAll) {
offset = this._computeOffset(mouseEvent, editor);
}
coldStart = true;
this.field.show (editor);
}
coldStart = true;
this.field.show (editor);
}

this.currentEditor = editor;
this.currentEditor = editor;
ghost = editor.getGhost();

// computes current geometry of the editor to apply it to the buffer later on
Expand All @@ -199,7 +199,7 @@

if (editor.getParam('enablelinebreak') == 'true') {
this.keyboard.enableRC();
}
}

// cursor positioning and initial text selection
if (doSelectAll) {
Expand Down
188 changes: 188 additions & 0 deletions src/filters/date.js
@@ -0,0 +1,188 @@
/* ***** BEGIN LICENSE BLOCK *****
*
* @COPYRIGHT@
*
* This file is part of the Adaptable XML Editing Library (AXEL), version @VERSION@
*
* @LICENSE@
*
* Web site : http://media.epfl.ch/Templates/
*
* Author(s) : Stephane Sire (Oppidoc)
*
* ***** END LICENSE BLOCK ***** */

///////////////////////////////////////////////////////////////////
// NOTES :
// - this filter requires JQuery and JQuery UI datepicker !!!
// - DO NOT CHAIN this filer
///////////////////////////////////////////////////////////////////

(function(){

var DEFAULT_REGION = 'fr';
var DEFAULT_FORMAT = 'ISO_8601';

// FIXME: move to bundles ?
var REGION = {
'fr': {
closeText: 'Fermer',
prevText: 'Précédent',
nextText: 'Suivant',
currentText: 'Aujourd\'hui',
monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Décembre'],
monthNamesShort: ['Janv.','Févr.','Mars','Avril','Mai','Juin','Juil.','Août','Sept.','Oct.','Nov.','Déc.'],
dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],
dayNamesShort: ['Dim.','Lun.','Mar.','Mer.','Jeu.','Ven.','Sam.'],
dayNamesMin: ['D','L','M','M','J','V','S'],
weekHeader: 'Sem.',
dateFormat: 'dd/mm/yy',
firstDay: 1,
isRTL: false,
showMonthAfterYear: false,
yearSuffix: ''
}
};

// converts a date string between two different formats
// leave it unchanged in case of errot
// FIXME: some formats such as RSS also requires to pass Day and Month name options !!!!
var _convertDate = function ( editor, dateStr, inSpec, outSpec ) {
var inFormat = editor.getParam(inSpec) || DEFAULT_REGION;
var outFormat = editor.getParam(outSpec) || DEFAULT_FORMAT;
if (inSpec === 'date_region') { // double indirection
inFormat = REGION[inFormat] ? REGION[inFormat].dateFormat : $.datepicker.regional[''].dateFormat;
outFormat = $.datepicker[outFormat];
}
if (outSpec === 'date_region') { // double indirection
inFormat = $.datepicker[inFormat];
outFormat = REGION[outFormat] ? REGION[outFormat].dateFormat : $.datepicker.regional[''].dateFormat;
}
var res = null;
try {
res = $.datepicker.formatDate(outFormat,$.datepicker.parseDate(inFormat, dateStr));
}
catch (e) {
res = dateStr;
}
return res;
};

/*****************************************************************************\
| |
| jQuery date picker device |
| |
| FIXME: - move to separate file |
\*****************************************************************************/
var datepickerDevice = function ( doc ) {
var _this = this;
this.handle = xtdom.createElement(doc, 'input');
this.jhandle = $(this.handle).attr({'id' : 'xt-date-datepicker', 'size' : 10});
$('body', doc).append(this.handle);
this.jhandle.datepicker().datepicker('option', 'onClose', function () { _this.onClose() });
this.myDoc = doc;
this.cache = {};
};

datepickerDevice.prototype = {
// Replaces the editor's handle with the date picker input
// Somehow similar to PlacedField in text device
// Replaces the handle with a hook that has the same root element as the handle
// and that contains an input or textarea edit field
// FIXME: register keyboard manager to track TAB navigation ?
grab : function ( editor, doSelectAll ) {
var _htag, region = editor.getParam('date_region') || DEFAULT_REGION;
$.datepicker.setDefaults((region === 'fr') ? REGION['fr'] : $.datepicker.regional['']);
this.jhandle.val(editor.getData()); // FIXME: format data to date (?)
this.editorHandle = editor.getHandle();
this.model = editor;
_htag = xtdom.getLocalName(this.editorHandle);
if (! this.cache[_htag]) {
this.hook = xtdom.createElement(this.myDoc, _htag);
this.cache[_htag] = this.hook;
} else {
this.hook = this.cache[_htag];
}
var parent = this.editorHandle.parentNode;
if (this.hook.firstChild != this.handle) {
this.hook.appendChild(this.handle);
}
parent.insertBefore (this.hook, this.editorHandle, true);
parent.removeChild(this.editorHandle);
if (doSelectAll) {
xtdom.focusAndSelect(this.handle);
} else {
this.jhandle.datepicker('show');
}
this.closingInProgress = false;
},
release : function ( isCancel ) {
var parent = this.hook.parentNode;
parent.insertBefore (this.editorHandle, this.hook, true);
parent.removeChild(this.hook);
if (! isCancel) {
this.model.update(this.jhandle.val()); // updates model with new value
}
if (! this.closingInProgress) { // external call (e.g. TAB navigation ?)
this.closingInProgress = true;
this.jhandle.datepicker('hide');
}
},
onClose : function ( ) {
if (! this.closingInProgress) {
this.release();
}
},
};

xtiger.registry.registerFactory('datepickerdev',
{
getInstance : function (doc) {
var cache = xtiger.session(doc).load('datepickerdev');
if (! cache) {
cache = new datepickerDevice(doc);
xtiger.session(doc).save('datepickerdev', cache);
}
return cache;
}
}
);

var datepickerFilterMixin = {

// Property remapping for chaining
'->': {
'load' : '__datepickerSuperLoad',
'save' : '__datepickerSuperSave'
},

startEditing : function ( aEvent ) {
var _doSelect = aEvent ? (!this._isModified || aEvent.shiftKey) : false;
var picker = xtiger.factory('datepickerdev').getInstance(this.getDocument());
picker.grab(this, _doSelect);
},

stopEditing : function ( isCancel ) {
var picker = xtiger.factory('datepickerdev').getInstance(this.getDocument());
picker.release();
},

load : function (aPoint, aDataSrc) {
this.__datepickerSuperLoad(aPoint, aDataSrc);
// post-action : converts view data to date_region format
this._setData(_convertDate(this, this._data, 'date_format', 'date_region'));
},

save : function (aLogger) {
var tmp = this._data;
// pre-action : converts view data model to date_format
this._data = _convertDate(this, tmp, 'date_region', 'date_format');
this.__datepickerSuperSave(aLogger);
this._data = tmp; // reestablish it for next save
}
}

// Expose the filter to the 'text' plugin (i.e. text.js must have been loaded)
xtiger.editor.Plugin.prototype.pluginEditors['text'].registerFilter('date', datepickerFilterMixin);

})();
2 changes: 1 addition & 1 deletion src/plugins/file.js
Expand Up @@ -293,7 +293,7 @@ xtiger.editor.FileFactory = (function FileFactory() {
// do not change state - proceed with upload (which may also fail on conflict !)
this.gotoLoading();
} else {
this.gotoComplete(response);
this.gotoComplete($.trim(response));
this.transmission = null;
}
},
Expand Down
82 changes: 82 additions & 0 deletions test/gui/Date.xhtml
@@ -0,0 +1,82 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:xt="http://ns.inria.org/xtiger" xml:lang="en">
<head>
<!-- Use UTF-8 and avoid the xml protocol declaration at the top for Internet Explorer -->
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=8;" />
<meta name="description" content="XTiger XML document template" />
<meta name="keywords" content="template, XTiger" />

<title>XTiger XML and AXEL Interactive (GUI) test case : 'dat' primitive editor plugin</title>

<xt:head version="1.1" templateVersion="1.0" label="TestCase">
</xt:head>

<link rel="stylesheet" href="../../3rd-part/jquery/css/ui-lightness/jquery-ui-1.8.18.custom.css" type="text/css" charset="utf-8" />
<!-- <script src="../../3rd-part/jquery/js/jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="../../3rd-part/jquery/js/jquery-ui-1.8.18.custom.min.js" type="text/javascript"></script> -->

<link rel="stylesheet" href="../../axel/axel.css" type="text/css"></link>
<!-- <script type="text/javascript" src="../../axel/axel.js"></script> -->

<script type="text/javascript">
var form;
function init() {
form = new xtiger.util.Form('../../axel/bundles');
form.setTemplateSource(document);
form.enableTabGroupNavigation();
if (! form.transform()) { alert(this .form.msg); }
}
// xtdom.addEventListener(window, 'load', init, false);
</script>

<!-- Template styling -->
<style type="text/css">
p.explic {
font-size: 90%;
}
.avertissement {
color: green;
}
</style>

</head>
<body>

<h1>Interactive (GUI) test case for <tt>'date'</tt> editor</h1>

<h2><xt:use types="text" label="Title">Click to edit a page title</xt:use></h2>

<!-- Test Case 1 -->

<h3>Click to edit the date, the first time it should be set to the current date</h3>

<p>Check the calendar region is 'fr' and format is 'ISO_8601'</p>

<p>Date : <xt:use types="text" param="filter=date;date_region=fr;date_format=ISO_8601" label="Date"/></p>

<!-- Test Case 2 -->

<h3>Select and click to edit the optional date, it should not be editable while not selected</h3>

<p>Check the calendar region is 'en' and format is 'RSS'</p>

<p>Date : <xt:use types="text" param="filter=date;date_region=en;date_format=RSS" label="Date" option="unset"/></p>

<!-- Test Case 3 -->

<h3>Click on the plus icon to create and edit a list of dates</h3>

<p>List of dates : </p>

<ul>
<xt:repeat minOccurs="0" maxOccurs="*" label="Dates">
<li class="date"><xt:menu-marker/><xt:use types="text" param="filter=date" label="Date"/></li>
</xt:repeat>
</ul>

<p>End of the test</p>
</body>
</html>

0 comments on commit 8514934

Please sign in to comment.