0

I am trying to bind a controller action to text that is highlighted in a text area, text input, or content-editable. Suppose that I have:

<input type="text" ng-model="name" placeholder="Enter Name">

With Angular 1.2.0, how can I watch for text that is highlighted inside the text box and display something on the page for the user?

Fourth
  • 9,163
  • 1
  • 23
  • 28
  • http://stackoverflow.com/questions/10341843/how-to-highlight-a-part-part-of-an-input-text-field-in-html-using-javascript-or – Ye Liu Sep 30 '13 at 17:09
  • @YeLiu that's kind of the opposite of what he/she wants.. – Langdon Sep 30 '13 at 17:13
  • Indeed - I want to react to the user highlighting some text, not highlight some text for them. – Fourth Sep 30 '13 at 17:18
  • I pointed to that question for a reason, take a look the accepted answer, it mentioned `selectionStart` and `selectionEnd`, those are all you need to accomplish what you want. I'm creating an answer for you. – Ye Liu Sep 30 '13 at 17:45

3 Answers3

3

Here is a pretty rough implementation of a directive that uses $timeout. It could probably be improved by monitoring mouseup and keyup (or selection events if they exist).

http://jsfiddle.net/4XDR8/1/

HTML

<div ng-app="app" ng-controller="TestCtrl">
    <input type="text" placeholder="Enter Name" ng-get-selection="name">
    {{name}}
    <br/>
    <br/>here select all this text down here
</div>

JavaScript:

var app = angular.module('app', []);

app.directive('ngGetSelection', function ($timeout) {
    var text = '';

    function getSelectedText() {
        var text = "";
        if (typeof window.getSelection != "undefined") {
            text = window.getSelection().toString();
        } else if (typeof document.selection != "undefined" && document.selection.type == "Text") {
            text = document.selection.createRange().text;
        }
        return text;
    }

    return {
        restrict: 'A',
        scope: {
            ngGetSelection: '='
        },
        link: function (scope, element) {
            $timeout(function getSelection() {
                var newText = getSelectedText();

                if (text != newText) {
                    text = newText;
                    element.val(newText);
                    scope.ngGetSelection = newText;
                }

                $timeout(getSelection, 50);
            }, 50);

        }
    };
});

app.controller('TestCtrl', function ($scope) {
    $scope.name = '';
});
Langdon
  • 19,875
  • 18
  • 88
  • 107
  • The question is trying to "watch for text that is highlighted inside the text box", but your solution is watching selection outside the input box... – Ye Liu Sep 30 '13 at 18:06
1

You can create a directive to utilize selectionStart and selectionEnd properties of an input element to achieve what you want to accomplish, like the following:

JS:

directive('watchSelection', function() {
    return function(scope, elem) {
        elem.on('mouseup', function() {
            var start = elem[0].selectionStart;
            var end = elem[0].selectionEnd;
            scope.selected = elem[0].value.substring(start, end);
            scope.$apply();
        });
    }; 
});

HTML:

<input type="text" ng-model="name" placeholder="Enter Name" watch-selection>

http://plnkr.co/edit/4LLfWk110p8ruVjAWRNv

Ye Liu
  • 8,946
  • 1
  • 38
  • 34
0

Here's how to grab the selected text from an input field:

http://jsfiddle.net/vREW8/

var input = document.getElementsByTagName('input')[0];
var selectedText = input.value.substring(input.selectionStart, input.selectionEnd);

You can use it with Anuglar.js any way that you want.

MattDiamant
  • 8,561
  • 4
  • 37
  • 46