Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

run a custom function on the click of the image insert button : Textangular

I need to override the default functionality of the image insert button of the textAngular.

I need to open a modal on the click of the same. How to do this?

like image 640
Bhumi Singhal Avatar asked Apr 30 '14 11:04

Bhumi Singhal


Video Answer


2 Answers

I had a similar problem and found it wasn't documented super well. There are a few bug threads where some solutions are mentioned:

https://github.com/fraywing/textAngular/issues/54 and https://github.com/fraywing/textAngular/issues/146

Following another user's solution there, and the customizing the toolbar section on the wiki, my solution looked like this:

config(['$provide',
  function($provide) {
    $provide.decorator('taOptions', ['taRegisterTool', '$modal', '$delegate',
      function(taRegisterTool, $modal, taOptions) {
        // $delegate is the taOptions we are decorating
        // here we override the default toolbars specified in taOptions.
        taOptions.toolbar = [
          ['clear', 'h1', 'h2', 'h3'],
          ['ul', 'ol'],
          ['bold', 'italics'],
          ['insertLink', 'insertVideo']
        ];

        // Create our own insertImage button
        taRegisterTool('customInsertImage', {
          iconclass: "fa fa-picture-o",
          action: function($deferred) {
            var textAngular = this;
            var savedSelection = rangy.saveSelection();
            var modalInstance = $modal.open({
              // Put a link to your template here or whatever
              template: '<label>Enter the url to your image:</label><input type="text" ng-model="img.url"><button ng-click="submit()">OK</button>',
              size: 'sm',
              controller: ['$modalInstance', '$scope',
                function($modalInstance, $scope) {
                  $scope.img = {
                    url: ''
                  };
                  $scope.submit = function() {
                    $modalInstance.close($scope.img.url);
                  };
                }
              ]
            });

            modalInstance.result.then(function(imgUrl) {
              rangy.restoreSelection(savedSelection);
              textAngular.$editor().wrapSelection('insertImage', imgUrl);
              $deferred.resolve();
            });
            return false;
          },
        });

        // Now add the button to the default toolbar definition
        // Note: It'll be the last button
        taOptions.toolbar[3].push('customInsertImage');
        return taOptions;
      }
    ]);
  }
]);

Check out the plunkr!

Major gotcha: This may be evident to others, but you need the restore selection stuff for the image insert to work. I guess execCommand puts the image at the cursor position, and that position is lost when you open up your own modal. I'm not sure if rangy specifically is necessary, or if you could just make sure the editor has cursor focus first before calling wrapSelection.

Edit: If you're importing the rangy library, textAngular has an optional method in the action constructor for it. Docs: "restoreSelection is only defined if the rangy library is included and it can be called as restoreSelection() to restore the users selection in the WYSIWYG editor." So your action method can use it instead of direct rangy calls.

action: function($deferred, restoreSelection) {
                var textAngular = this;
                var modalInstance = $modal.open({
                    ....
                });

                modalInstance.result.then(function(imgUrl) {
                  restoreSelection();
                  textAngular.$editor().wrapSelection('insertImage', imgUrl);
                  $deferred.resolve();
                });
                return false;
              },
            });
            ...
like image 53
crennie Avatar answered Oct 03 '22 11:10

crennie


Im' sharing the code for an image upload service I implemented through angular-bootsrap-ui $modal service and DanialFarid's angular-file-upload service.

.config(function ($provide) {

            $provide.decorator('taOptions', ['taRegisterTool', '$delegate', '$modal', function (taRegisterTool, taOptions, $modal) {
                taRegisterTool('uploadImage', {
                    iconclass: "fa fa-image",
                    action: function (deferred) {
                        $modal.open({
                            controller: 'UploadImageModalInstance',
                            templateUrl: 'views/modals/upload.html'
                        }).result.then(
                            function (result) {
                                document.execCommand('insertImage', true, result);
                                deferred.resolve();
                            },
                            function () {
                                deferred.resolve();
                            }
                        );
                        return false;
                    }
                });
                taOptions.toolbar[1].push('uploadImage');
                return taOptions;
            }]);
        })

Now the view for the modal with the button that handles the $scope.upload() function, previews the uploaded image, and a button that fires the $scope.insert() function.

<form data-ng-submit="insert()">
    <div class="modal-header">
        <div class="col-md-10">
            <h4 class="modal-title"><span class="glyphicon glyphicon-picture"></span> Upload Image</h4>
        </div>
        <div class="col-md-2 right">
            <a class="close" href data-ng-click="$dismiss()"><span class="glyphicon glyphicon-remove"></span></a>
        </div>
    </div>
    <div class="modal-body">
        <img data-ng-src="{{image}}">
        <progressbar data-ng-show="progress > 0 && progress < 100" class="progress-striped active" value="progress"></progressbar>
    </div>
    <div class="modal-footer center clearfix">
        <button data-ng-click="$dismiss()" type="button" class="btn btn-default pull-left">Cancel</button>
        <button type="submit" data-ng-disabled="image == null || image == '' || image == 'img/posts/default.svg'" class="btn btn-primary pull-right">Insert Image</button>
        <button type="button" data-ngf-select data-ngf-change="upload()" data-ng-model="files" data-ngf-multiple="false" class="btn btn-primary pull-right"><span class="glyphicon glyphicon-picture mR5"></span>Upload Image</button>
    </div>
</form>

And also the controller that handles the file upload and image insert:

app.controller('UploadImageModalInstance', function($scope, $modalInstance, Upload){

            $scope.image = 'img/default.png';

            $scope.progress = 0;
            $scope.files = [];

            $scope.upload = function(){
                Upload.upload({
                    url: 'api/upload',
                    fields: {'dir': 'img/uploads/'},
                    file: $scope.files[0],
                    method: 'POST'
                }).progress(function (evt) {
                    $scope.progress = parseInt(100.0 * evt.loaded / evt.total);
                }).success(function (data) {
                    $scope.progress = 0;
                    $scope.image = data.dir+data.filename;
                });
            };

            $scope.insert = function(){
                $modalInstance.close($scope.image);
            };
        })
like image 22
Logus Graphics Avatar answered Oct 03 '22 09:10

Logus Graphics