Skip to content

Commit

Permalink
Slightly expand the input when the user focuses on it, unless they've…
Browse files Browse the repository at this point in the history
… already resized it.
  • Loading branch information
cjcenizal committed May 25, 2017
1 parent 72bb284 commit 6ba00d2
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 15 deletions.
2 changes: 1 addition & 1 deletion src/core_plugins/timelion/public/app.less
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
* 1. Anchor suggestions beneath input.
* 2. Allow for option of positioning suggestions absolutely.
*/
.timelionSearchInputContainer {
.timelionExpressionInputContainer {
flex: 1 1 auto;
display: flex;
flex-direction: column; /* 1 */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
<div class="timelionSearchInputContainer">
<div class="timelionExpressionInputContainer">
<textarea
data-expression-input
type="text"
rows="{{ rows }}"
class="kuiTextArea fullWidth"
placeholder=".es(*)"
rows="{{ rows }}"
input-focus
ng-model="sheet"
ng-focus="onFocusInput()"
ng-keydown="onKeyDownInput($event)"
ng-keyup="onKeyUpInput($event)"
ng-blur="onBlurInput()"
ng-mousedown="onMouseDownInput()"
ng-mouseup="onMouseUpInput()"
></textarea>

<timelion-expression-suggestions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import {
const Parser = PEG.buildParser(grammar);
const app = require('ui/modules').get('apps/timelion', []);

app.directive('timelionExpressionInput', function ($http, $timeout) {
app.directive('timelionExpressionInput', function ($document, $http, $interval, $timeout) {
return {
restrict: 'E',
scope: {
Expand All @@ -50,6 +50,11 @@ app.directive('timelionExpressionInput', function ($http, $timeout) {
template: timelionExpressionInputTemplate,
link: function (scope, elem) {
const expressionInput = elem.find('[data-expression-input]');
const TEASE_MULTILINE_HEIGHT = 80;
let expressionInputHeight;
let isExpressionInputResizing = false;
let hasExpressionInputResized = false;
let checkIfExpressionInputIsResizingInterval;

const navigationalKeys = {
ESC: 27,
Expand All @@ -64,6 +69,10 @@ app.directive('timelionExpressionInput', function ($http, $timeout) {

scope.functionSuggestions = new FunctionSuggestions();

function getExpressionInputHeight() {
return expressionInput.outerHeight();
}

function init() {
$http.get('../api/timelion/functions').then(function (resp) {
Object.assign(functionReference, {
Expand Down Expand Up @@ -141,12 +150,50 @@ app.directive('timelionExpressionInput', function ($http, $timeout) {
// Wait for the caret position of the input to update and then we can get suggestions
// (which depends on the caret position).
$timeout(getSuggestions, 0);

// Show the user that the input can support multiple lines by making it a bit taller when
// the user focuses (but only if the user hasn't resized it).
if (!hasExpressionInputResized) {
expressionInputHeight = TEASE_MULTILINE_HEIGHT;
expressionInput.css('height', `${TEASE_MULTILINE_HEIGHT}px`);
}
};

scope.onBlurInput = () => {
scope.functionSuggestions.hide();

if (!hasExpressionInputResized) {
expressionInput.css('height', '');
}
};

// We have to track resizing of the textarea by polling and comparing change in height because
// there is no native browser 'resize' event for textareas.
function checkIfExpressionInputIsResizing() {
const newExpressionInputHeight = getExpressionInputHeight();

if (newExpressionInputHeight !== expressionInputHeight) {
hasExpressionInputResized = true;
}

expressionInputHeight = newExpressionInputHeight;
}

scope.onMouseDownInput = () => {
isExpressionInputResizing = true;
checkIfExpressionInputIsResizingInterval = $interval(checkIfExpressionInputIsResizing, 100);
};

function onMouseUpDocument() {
if (isExpressionInputResizing) {
checkIfExpressionInputIsResizing();
$interval.cancel(checkIfExpressionInputIsResizingInterval);
isExpressionInputResizing = false;
}
}

$document.on('mouseup', onMouseUpDocument);

scope.onKeyDownInput = e => {
// If we've pressed any non-navigational keys, then the user has typed something and we
// can exit early without doing any navigation. The keyup handler will pull up suggestions.
Expand Down Expand Up @@ -214,6 +261,10 @@ app.directive('timelionExpressionInput', function ($http, $timeout) {
insertSuggestionIntoExpression(index);
};

scope.$on('$destroy', () => {
$document.off('mouseup', onMouseUpDocument);
});

init();
}
};
Expand Down
14 changes: 6 additions & 8 deletions src/core_plugins/timelion/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,12 @@
class="kuiFieldGroup kuiFieldGroup--alignTop kuiVerticalRhythm"
>
<div class="kuiFieldGroupSection kuiFieldGroupSection--wide">
<div class="kuiLocalSearch timelionLocalSearch">
<timelion-expression-input
sheet="state.sheet[state.selected]"
rows="1"
update-chart="search()"
should-popover-suggestions="true"
></timelion-expression-input>
</div>
<timelion-expression-input
sheet="state.sheet[state.selected]"
rows="1"
update-chart="search()"
should-popover-suggestions="true"
></timelion-expression-input>
</div>

<div class="kuiFieldGroupSection">
Expand Down
4 changes: 4 additions & 0 deletions ui_framework/components/_mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,16 @@
}
}
/**
* 1. Prevent Firefox users from being able to resize textareas to smaller than the min-height.
*/
@mixin formControl($borderRadius: $globalBorderRadius) {
@include formControlBase;
background-color: #ffffff;
border: 1px solid $globalFormControlBorderColor;
border-radius: $borderRadius;
transition: border-color $globalInputTransitionTiming;
min-height: 30px; /* 1 */
&:invalid {
@include formControlInvalid;
Expand Down
19 changes: 17 additions & 2 deletions ui_framework/dist/ui_framework.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
/**
* Nothing fancy, just the basics so we can use this for both regular and static controls.
*/
/**
* 1. Prevent Firefox users from being able to resize textareas to smaller than the min-height.
*/
/**
* 1. Angular will add an ng-untouched class to an input if it hasn't been touched yet.
* We only want invalid inputs to appear invalid after the user has had a chance to interact
Expand Down Expand Up @@ -843,6 +846,8 @@ body {
border: 1px solid #DEDEDE;
border-radius: 4px;
transition: border-color 0.1s linear;
min-height: 30px;
/* 1 */
padding-left: 28px;
/* 1 */
width: 100%;
Expand Down Expand Up @@ -879,6 +884,8 @@ body {
border: 1px solid #DEDEDE;
border-radius: 4px;
transition: border-color 0.1s linear;
min-height: 30px;
/* 1 */
padding-right: 30px;
/* 2 */
background-image: url('data:image/svg+xml;utf8,<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1408 704q0 26-19 45l-448 448q-19 19-45 19t-45-19l-448-448q-19-19-19-45t19-45 45-19h896q26 0 45 19t19 45z"/></svg>');
Expand Down Expand Up @@ -946,7 +953,9 @@ body {
background-color: #ffffff;
border: 1px solid #DEDEDE;
border-radius: 4px;
transition: border-color 0.1s linear; }
transition: border-color 0.1s linear;
min-height: 30px;
/* 1 */ }
.theme-dark .kuiTextArea {
color: #cecece; }
.kuiTextArea:invalid:not(.ng-untouched) {
Expand Down Expand Up @@ -984,7 +993,9 @@ body {
background-color: #ffffff;
border: 1px solid #DEDEDE;
border-radius: 4px;
transition: border-color 0.1s linear; }
transition: border-color 0.1s linear;
min-height: 30px;
/* 1 */ }
.theme-dark .kuiTextInput {
color: #cecece; }
.kuiTextInput:invalid:not(.ng-untouched) {
Expand Down Expand Up @@ -1794,6 +1805,8 @@ body {
border: 1px solid #DEDEDE;
border-radius: 4px;
transition: border-color 0.1s linear;
min-height: 30px;
/* 1 */
-webkit-box-flex: 1;
-webkit-flex: 1 1 100%;
-ms-flex: 1 1 100%;
Expand Down Expand Up @@ -1871,6 +1884,8 @@ body {
border: 1px solid #DEDEDE;
border-radius: 4px;
transition: border-color 0.1s linear;
min-height: 30px;
/* 1 */
padding-right: 30px;
/* 2 */
background-image: url('data:image/svg+xml;utf8,<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1408 704q0 26-19 45l-448 448q-19 19-45 19t-45-19l-448-448q-19-19-19-45t19-45 45-19h896q26 0 45 19t19 45z"/></svg>');
Expand Down

0 comments on commit 6ba00d2

Please sign in to comment.