1
0
mirror of http://git.whoc.org.uk/git/password-manager.git synced 2024-11-14 08:49:01 +01:00

Improved text area autoresize behaviour

This commit is contained in:
Giulio Cesare Solaroli 2015-02-26 21:03:33 +01:00
parent 375fc0c10e
commit a4718b2c04
8 changed files with 140 additions and 41 deletions

View File

@ -1812,7 +1812,8 @@ span.count {
#extraFeaturesPanel div ul li p {
font-size: 10pt;
font-weight: 100;
padding-bottom: 5px; }
padding-bottom: 5px;
line-height: 1.2em; }
#extraFeaturesPanel div ul li a.button {
-webkit-border-radius: 2;
-moz-border-radius: 2;
@ -2018,7 +2019,11 @@ div.cardList.narrow {
#cardDetailPage .edit .cardDetailToolbar, .cardDetail .edit .cardDetailToolbar {
background-color: #1863a1;
color: white; }
#cardDetailPage .edit .cardField:hover, .cardDetail .edit .cardField:hover {
#cardDetailPage .edit .cardField, .cardDetail .edit .cardField {
border-top: 1px solid #eee; }
#cardDetailPage .edit .cardField:last-child, .cardDetail .edit .cardField:last-child {
border-bottom: 1px solid #eee; }
#cardDetailPage .edit .cardField:hover, .cardDetail .edit .cardField:hover {
background-color: #eee; }
#cardDetailPage .edit input::-webkit-input-placeholder, #cardDetailPage .edit textarea::-webkit-input-placeholder, .cardDetail .edit input::-webkit-input-placeholder, .cardDetail .edit textarea::-webkit-input-placeholder {
font-style: italic;
@ -2063,13 +2068,13 @@ div.cardList.narrow {
.content .tagEditor {
padding: 10px; }
.content .cardNotes {
padding: 10px;
width: 100%;
border: 0px;
font-size: 10pt;
font-style: italic;
white-space: pre-wrap;
word-wrap: break-word; }
.content .cardNotes div {
padding: 10px; }
.content .dropArea {
background-color: #ccc;
width: 100%;

File diff suppressed because one or more lines are too long

View File

@ -44,35 +44,6 @@ Clipperz.PM.UI.Components.Cards.Edit = React.createClass({
//----------------------------------------------------------------------------
componentDidMount: function() {
var textareas;
var autoresize = this.autoresize;
textareas = [].slice.call(this.getDOMNode().querySelectorAll('textarea'));
textareas.forEach(function(aTextarea) {
aTextarea.addEventListener('input', autoresize, false);
autoresize({target:aTextarea});
});
},
componentWillUnmount: function() {
var textareas;
var autoresize = this.autoresize;
textareas = [].slice.call(this.getDOMNode().querySelectorAll('textarea'));
textareas.forEach(function(aTextarea) {
aTextarea.removeEventListener('input', autoresize, false);
});
},
autoresize: function (anEvent) {
anEvent.target.style.height = 'auto';
anEvent.target.style.height = anEvent.target.scrollHeight+'px';
window.scrollTo(window.scrollLeft, (anEvent.target.scrollTop + anEvent.target.scrollHeight));
},
//----------------------------------------------------------------------------
record: function () {
return this.props['_record'];
},
@ -287,7 +258,8 @@ console.log("DROP"); //, anEvent);
},
renderNotes: function (someNotes) {
return React.DOM.textarea({'className':'cardNotes', 'onChange':this.handleChange(this.record(), 'setNotes'), 'defaultValue':someNotes, 'key':this.props['_reference'] + '_notes', 'placeholder': "notes"});
// return React.DOM.textarea({'className':'cardNotes', 'onChange':this.handleChange(this.record(), 'setNotes'), 'defaultValue':someNotes, 'key':this.props['_reference'] + '_notes', 'placeholder': "notes"});
return Clipperz.PM.UI.Components.Cards.TextArea({'className':'cardNotes', 'onChange':this.handleChange(this.record(), 'setNotes'), 'defaultValue':someNotes, 'key':this.props['_reference'] + '_notes', 'placeholder': "notes"});
},
//............................................................................
@ -343,7 +315,8 @@ console.log("DROP"); //, anEvent);
React.DOM.input({'_className_':'_fieldLabel_', 'onChange':this.handleChange(field, 'setLabel'), 'defaultValue':aField['label'], 'placeholder': "label"}),
]),
React.DOM.div({'className':'fieldValue'}, [
React.DOM.textarea({'className':React.addons.classSet(cardFieldValueClasses), 'onChange':this.handleChange(field, 'setValue'), 'defaultValue':aField['value'], 'placeholder': "value"}),
// React.DOM.textarea({'className':React.addons.classSet(cardFieldValueClasses), 'onChange':this.handleChange(field, 'setValue'), 'defaultValue':aField['value'], 'placeholder': "value"}),
Clipperz.PM.UI.Components.Cards.TextArea({'className':React.addons.classSet(cardFieldValueClasses), 'onChange':this.handleChange(field, 'setValue'), 'defaultValue':aField['value'], 'placeholder': "value"}),
])
]),
React.DOM.div({'className':'fieldAction action'}, aField['actionType'].toLowerCase())

View File

@ -0,0 +1,110 @@
/*
Copyright 2008-2013 Clipperz Srl
This file is part of Clipperz, the online password manager.
For further information about its features and functionalities please
refer to http://www.clipperz.com.
* Clipperz is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
* Clipperz is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
*/
'use strict';
Clipperz.Base.module('Clipperz.PM.UI.Components.Cards');
Clipperz.PM.UI.Components.Cards.TextArea = React.createClass({
//----------------------------------------------------------------------------
componentDidMount: function() {
this.recalculateSize();
this.getDOMNode().addEventListener('input', this.recalculateSize, false);
},
componentWillUnmount: function() {
this.getDOMNode().removeEventListener('input', this.recalculateSize, false);
},
// componentDidUpdate: function(prevProps) {
// if (prevProps.style || prevProps.value !== this.props.value || this.props.value == null) {
// this.recalculateSize();
// }
// },
// onChange: function(e) {
// if (this.props.onChange) {
// this.props.onChange(e);
// }
//
// if (this.props.value === undefined) {
// // controlled mode
// this.recalculateSize();
// }
// },
//----------------------------------------------------------------------------
recalculateSize: function () {
this.recalculateSize_1()
},
// http://maximilianhoffmann.com/posts/autoresizing-textareas
recalculateSize_1: function () {
var node = this.getDOMNode();
node.style.height = 'auto';
node.style.height = node.scrollHeight+'px';
window.scrollTo(window.scrollLeft, (node.scrollTop + node.scrollHeight));
},
recalculateSize_2: function() {
var diff;
var node = this.getDOMNode();
if (window.getComputedStyle) {
var styles = window.getComputedStyle(node);
// If the textarea is set to border-box, it's not necessary to subtract the padding.
if (
styles.getPropertyValue('box-sizing') === "border-box"
|| styles.getPropertyValue('-moz-box-sizing') === "border-box"
|| styles.getPropertyValue('-webkit-box-sizing') === "border-box"
) {
diff = 0;
} else {
diff = ( parseInt(styles.getPropertyValue('padding-bottom') || 0, 10)
+ parseInt(styles.getPropertyValue('padding-top') || 0, 10)
);
}
} else {
diff = 0;
}
// var node = this.getDOMNode();
node.style.height = 'auto';
node.style.height = (node.scrollHeight - diff) + 'px';
},
//----------------------------------------------------------------------------
// render: function () {
// return React.DOM.textarea({'className':'cardNotes', /*'onChange':this.handleChange(this.record(), 'setNotes'), 'defaultValue':someNotes, 'key':this.props['_reference'] + '_notes',*/ 'placeholder': "notes"});
// },
render: function() {
return React.DOM.textarea(this.props, this.props.children);
},
});

View File

@ -91,7 +91,9 @@ Clipperz.PM.UI.Components.Cards.View = React.createClass({
//console.log("NOTES", someNotes);
if (someNotes != "") {
result = React.DOM.div({'className':'cardNotes'}, someNotes);
result = React.DOM.div({'className':'cardNotes'}, [
React.DOM.div({}, someNotes)
]);
} else {
result = null;
}

View File

@ -75,7 +75,7 @@ Clipperz.PM.UI.Components.Selections = React.createClass({
var filterType;
var filterValue;
console.log("SELECTIONS PROPS", this.props);
//console.log("SELECTIONS PROPS", this.props);
tagInfo = this.props['tags'] ? this.props['tags'] : {};
tags = MochiKit.Base.filter(Clipperz.PM.DataModel.Record.isRegularTag, MochiKit.Base.keys(tagInfo)).sort(Clipperz.Base.caseInsensitiveCompare);
archivedCardsCount = this.props['archivedCardsCount'];

View File

@ -225,6 +225,12 @@ $cardViewBasePadding: 10px;
}
.cardField {
border-top: 1px solid #eee;
&:last-child {
border-bottom: 1px solid #eee;
};
&:hover {
background-color: #eee;
}
@ -305,17 +311,19 @@ $cardViewBasePadding: 10px;
}
.cardNotes {
padding: $cardViewBasePadding;
width: 100%;
border: 0px;
font-size: 10pt;
font-style: italic;
// font-style: italic;
white-space: pre-wrap;
word-wrap: break-word;
// background-color: gold;
div {
padding: $cardViewBasePadding;
}
}
.dropArea {

View File

@ -77,6 +77,7 @@
font-size: 10pt;
font-weight: 100;
padding-bottom: 5px;
line-height: 1.2em;
}
a.button {