Added HTML native support for auto-completion in tag editor

Not sure on which browser this feature is working; only tested in Chrome for Mac.
This commit is contained in:
Giulio Cesare Solaroli 2015-03-03 17:42:25 +01:00
parent 03ce1d3497
commit 2368d471e8
7 changed files with 53 additions and 34 deletions

View File

@ -25,6 +25,10 @@ Clipperz.Base.module('Clipperz.PM.UI.Components.Cards');
Clipperz.PM.UI.Components.Cards.Detail = React.createClass({ Clipperz.PM.UI.Components.Cards.Detail = React.createClass({
propTypes: {
'allTags': React.PropTypes.array,
},
viewComponentProps: function () { viewComponentProps: function () {
var result; var result;

View File

@ -29,6 +29,7 @@ Clipperz.PM.UI.Components.Cards.Edit = React.createClass({
//============================================================================ //============================================================================
propTypes: { propTypes: {
'allTags': React.PropTypes.array,
// 'label': React.PropTypes.string /*.isRequired */ , // 'label': React.PropTypes.string /*.isRequired */ ,
// 'loading': React.PropTypes.bool, // 'loading': React.PropTypes.bool,
}, },
@ -264,13 +265,12 @@ console.log("DROP"); //, anEvent);
//............................................................................ //............................................................................
renderTags: function (someTags) { cleanupTags: function (someTags) {
var tags; return MochiKit.Base.filter(Clipperz.PM.DataModel.Record.isRegularTag, someTags).sort(Clipperz.Base.caseInsensitiveCompare);
var allTags; },
tags = MochiKit.Base.filter(Clipperz.PM.DataModel.Record.isRegularTag, someTags).sort(Clipperz.Base.caseInsensitiveCompare); renderTags: function (someTags) {
allTags = tags; return Clipperz.PM.UI.Components.Cards.TagEditor({'selectedTags':this.cleanupTags(someTags), 'allTags':this.cleanupTags(this.props['allTags']), 'readOnly':false });
return Clipperz.PM.UI.Components.Cards.TagEditor({'selectedTags':tags, 'allTags':allTags, 'readOnly':false });
}, },
//............................................................................ //............................................................................

View File

@ -43,10 +43,14 @@ Clipperz.PM.UI.Components.Cards.TagEditor = React.createClass({
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
stillNotUsedTags: function () { listOfTagsNotUsedYet: function () {
// return MochiKit.Base.filter(function, this.props['allTags']); var selectedTags = this.props['selectedTags'];
//console.log("ALL TAGS", this.props['allTags']);
//console.log("SELECTED TAGS", this.props['selectedTags']);
return MochiKit.Base.filter(function (aTag) { return selectedTags.indexOf(aTag) == -1 }, this.props['allTags']);
// return this.props['allTags'];
}, },
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
removeTagHandler: function (anEvent) { removeTagHandler: function (anEvent) {
@ -67,24 +71,23 @@ Clipperz.PM.UI.Components.Cards.TagEditor = React.createClass({
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
addTagValue: function (anEvent) {
this.addTag(anEvent.currentTarget.value);
anEvent.currentTarget.value = "";
},
handleKeyDown: function(anEvent) { handleKeyDown: function(anEvent) {
switch (anEvent.keyCode) { switch (anEvent.keyCode) {
case 9: // tab case 9: // tab
console.log("TAB"); this.addTagValue(anEvent);
// if (anEvent.shiftKey || !this.state.isOpen) { break;
// return;
// }
// this.selectFocusedOption();
break;
case 13: // enter case 13: // enter
console.log("ENTER"); this.addTagValue(anEvent);
this.addTag(anEvent.currentTarget.value); anEvent.preventDefault();
anEvent.currentTarget.value = ""; break;
// this.selectFocusedOption(); /*
break;
case 27: // escape case 27: // escape
console.log("ESCAPE"); console.log("ESCAPE");
// if (this.state.isOpen) { // if (this.state.isOpen) {
@ -92,22 +95,22 @@ Clipperz.PM.UI.Components.Cards.TagEditor = React.createClass({
// } else { // } else {
// this.clearValue(); // this.clearValue();
// } // }
break; break;
case 38: // up case 38: // up
console.log("UP"); console.log("UP");
// this.focusPreviousOption(); // this.focusPreviousOption();
break; break;
case 40: // down case 40: // down
console.log("DOWN"); console.log("DOWN");
// this.focusNextOption(); // this.focusNextOption();
break; break;
default: return; default:
return;
*/
} }
anEvent.preventDefault();
}, },
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -120,7 +123,10 @@ Clipperz.PM.UI.Components.Cards.TagEditor = React.createClass({
}, },
renderEditField: function () { renderEditField: function () {
return React.DOM.input({'type':'text', 'onKeyDown':this.handleKeyDown, 'placeholder': "tag"}); return [
React.DOM.input({'type':'text', 'list':'tagListData', 'onKeyDown':this.handleKeyDown, 'placeholder': "tag"}),
React.DOM.datalist({'id':'tagListData'}, MochiKit.Base.map(function (aTag) { return React.DOM.option({}, aTag); }, this.listOfTagsNotUsedYet()))
];
}, },
render: function () { render: function () {

View File

@ -24,6 +24,10 @@ refer to http://www.clipperz.com.
Clipperz.Base.module('Clipperz.PM.UI.Components.Pages'); Clipperz.Base.module('Clipperz.PM.UI.Components.Pages');
Clipperz.PM.UI.Components.Pages.CardDetailPage = React.createClass({ Clipperz.PM.UI.Components.Pages.CardDetailPage = React.createClass({
propTypes: {
'allTags': React.PropTypes.array,
},
/* /*
viewComponentProps: function () { viewComponentProps: function () {
var result; var result;

View File

@ -33,6 +33,8 @@ Clipperz.PM.UI.Components.Pages.MainPage = React.createClass({
}, },
propTypes: { propTypes: {
'tags': React.PropTypes.object,
'allTags': React.PropTypes.array,
'messageBox': React.PropTypes.object.isRequired, 'messageBox': React.PropTypes.object.isRequired,
'featureSet': React.PropTypes.oneOf(['FULL', 'EXPIRED', 'TRIAL', 'OFFLINE']).isRequired, 'featureSet': React.PropTypes.oneOf(['FULL', 'EXPIRED', 'TRIAL', 'OFFLINE']).isRequired,
'accountInfo': React.PropTypes.object.isRequired, 'accountInfo': React.PropTypes.object.isRequired,

View File

@ -29,9 +29,10 @@ Clipperz.PM.UI.Components.Panels.MainPanel = React.createClass({
//========================================================================= //=========================================================================
propTypes: { propTypes: {
'messageBox': React.PropTypes.object.isRequired, 'allTags': React.PropTypes.array,
'featureSet': React.PropTypes.oneOf(['FULL', 'EXPIRED', 'TRIAL', 'OFFLINE']).isRequired, 'messageBox': React.PropTypes.object.isRequired,
'style': React.PropTypes.oneOf(Clipperz_PM_UI_availableStyles).isRequired, 'featureSet': React.PropTypes.oneOf(['FULL', 'EXPIRED', 'TRIAL', 'OFFLINE']).isRequired,
'style': React.PropTypes.oneOf(Clipperz_PM_UI_availableStyles).isRequired,
}, },
style: function () { style: function () {

View File

@ -242,12 +242,11 @@ console.log("THE BROWSER IS OFFLINE");
shouldShowRegistrationForm = parameters['shouldShowRegistrationForm'] && canRegisterNewUsers; shouldShowRegistrationForm = parameters['shouldShowRegistrationForm'] && canRegisterNewUsers;
this.pages()['loginPage'].setProps({'mode':this.loginMode(), 'isNewUserRegistrationAvailable':canRegisterNewUsers}); this.pages()['loginPage'].setProps({'mode':this.loginMode(), 'isNewUserRegistrationAvailable':canRegisterNewUsers});
this.showLoginForm();
if (shouldShowRegistrationForm) { if (shouldShowRegistrationForm) {
this.showRegistrationForm_handler(); this.showRegistrationForm_handler();
} else {
this.showLoginForm();
} }
// this.overlay().done("", 0.5); // this.overlay().done("", 0.5);
this.overlay().hide(); this.overlay().hide();
}, },
@ -725,6 +724,9 @@ console.log("THE BROWSER IS OFFLINE");
// MochiKit.Base.method(this.user(), 'getTags', this.shouldIncludeArchivedCards()), // MochiKit.Base.method(this.user(), 'getTags', this.shouldIncludeArchivedCards()),
MochiKit.Base.method(this, 'allTags', this.shouldIncludeArchivedCards()), MochiKit.Base.method(this, 'allTags', this.shouldIncludeArchivedCards()),
MochiKit.Base.method(this, 'setPageProperties', 'mainPage', 'tags'), MochiKit.Base.method(this, 'setPageProperties', 'mainPage', 'tags'),
MochiKit.Base.method(this, 'allTags', true || this.shouldIncludeArchivedCards()),
MochiKit.Base.keys,
MochiKit.Base.method(this, 'setPageProperties', 'mainPage', 'allTags'),
MochiKit.Base.method(this, 'getAllCardsCount'), MochiKit.Base.method(this, 'getAllCardsCount'),
MochiKit.Base.method(this, 'setPageProperties', 'mainPage', 'allCardsCount'), MochiKit.Base.method(this, 'setPageProperties', 'mainPage', 'allCardsCount'),
MochiKit.Base.method(this, 'getArchivedCardsCount'), MochiKit.Base.method(this, 'getArchivedCardsCount'),