tiny.js 16.6 KB
/**
 * Created by Administrator on 2015/2/27.
 */
/**
 * Binds a TinyMCE widget to <textarea> elements.
 *
 *    //link image media
 */


angular.module('xn.tiny', [])
    .value('uiTinymceConfig', {
        height: 500,
        resize: false,
        plugins: [
            "advlist autolink lists  charmap print preview anchor",
            "searchreplace visualblocks code fullscreen ",
            "insertdatetime  table  contextmenu paste wordcount image imagetools  link template media codesample pagebreak"
        ],
        toolbar: "insertfile undo redo | styleselect | bold italic strikethrough forecolor backcolor  | " +
        "alignleft aligncenter alignright alignjustify | bullist numlist outdent indent image template ",
        file_browser_callback_types: 'image ', //media
    })
    .value('xnTinymceConfig', { })
    .directive('uiTinymce', ['$rootScope', '$compile', '$timeout', '$window', '$sce', 'uiTinymceConfig',"xnTinymceConfig",'uiTinymceService',"ImgTinyService",
        function($rootScope, $compile, $timeout, $window, $sce, uiTinymceConfig,xnTinymceConfig, uiTinymceService,imgTinyService) {
            uiTinymceConfig = uiTinymceConfig || {};

            if (uiTinymceConfig.baseUrl) {
                tinymce.baseURL = uiTinymceConfig.baseUrl;
            }
            console.log("xnTinymceConfig",xnTinymceConfig)
            if(xnTinymceConfig.templates){
                uiTinymceConfig.templates = xnTinymceConfig.templates||[];
            }

            return {
                scope:{
                    diskId:"="
                },
                require: ['ngModel', '^?form'],
                priority: 599,
                link: function(scope, element, attrs, ctrls) {
                    if (!$window.tinymce) {
                        return;
                    }

                    var ngModel = ctrls[0],
                        form = ctrls[1] || null;

                    var expression, options = {
                            debounce: true,
                            convert_urls:false
                        }, tinyInstance,
                        updateView = function(editor) {
                            var content = editor.getContent({format: options.format}).trim();
                            content = $sce.trustAsHtml(content);
                            ngModel.$setViewValue(content);
                            if (!$rootScope.$$phase) {
                                scope.$digest();
                            }
                        };

                    function toggleDisable(disabled) {
                        if (disabled) {
                            ensureInstance();

                            if (tinyInstance) {
                                tinyInstance.getBody().setAttribute('contenteditable', false);
                            }
                        } else {
                            ensureInstance();

                            if (tinyInstance && !tinyInstance.settings.readonly && tinyInstance.getDoc()) {
                                tinyInstance.getBody().setAttribute('contenteditable', true);
                            }
                        }
                    }

                    // fetch a unique ID from the service
                    var uniqueId = uiTinymceService.getUniqueId();
                    attrs.$set('id', uniqueId);

                    expression = {};

                    angular.extend(expression, scope.$eval(attrs.uiTinymce));

                    //Debounce update and save action
                    var debouncedUpdate = (function(debouncedUpdateDelay) {
                        var debouncedUpdateTimer;
                        return function(ed) {
                            $timeout.cancel(debouncedUpdateTimer);
                            debouncedUpdateTimer = $timeout(function() {
                                return (function(ed) {
                                    if (ed.isDirty()) {
                                        ed.save();
                                        updateView(ed);
                                    }
                                })(ed);
                            }, debouncedUpdateDelay);
                        };
                    })(400);


                    var setupOptions = {
                        // Update model when calling setContent
                        // (such as from the source editor popup)
                        setup: function(ed) {
                            ed.on('init', function() {
                                ngModel.$render();
                                ngModel.$setPristine();
                                ngModel.$setUntouched();
                                if (form) {
                                    form.$setPristine();
                                }
                            });

                            // Update model when:
                            // - a button has been clicked [ExecCommand]
                            // - the editor content has been modified [change]
                            // - the node has changed [NodeChange]
                            // - an object has been resized (table, image) [ObjectResized]
                            ed.on('ExecCommand change NodeChange ObjectResized', function() {
                                if (!options.debounce) {
                                    ed.save();
                                    updateView(ed);
                                    return;
                                }
                                debouncedUpdate(ed);
                            });

                            ed.on('blur', function() {
                                element[0].blur();
                                ngModel.$setTouched();
                                if (!$rootScope.$$phase) {
                                    scope.$digest();
                                }
                            });
                            ed.on("paste",function (e) {

                                if(e.clipboardData){
                                    var clipboard = e.clipboardData;
                                    for(var i=0,len=clipboard.items.length; i<len; i++) {
                                        if(clipboard.items[i].kind == 'file' || clipboard.items[i].type.indexOf('image') > -1) {
                                            var imageFile = clipboard.items[i].getAsFile();
                                            imageFile.name = new Date().getTime()+".png";

                                            var fd = new FormData();
                                            fd.append("File", imageFile);
                                            fd.append("Type", "PHOTO");
                                            var viewValue =$sce.getTrustedHtml(ngModel.$viewValue);

                                            imgTinyService.fileUpload(fd).then(function(data) {
                                                if (tinyInstance &&tinyInstance.getDoc()) {
                                                    tinyInstance.setContent(viewValue+"<img src=\""+ data.url + "\" >");
                                                    updateView(ed);
                                                }
                                            });

                                        }
                                    }
                                }
                            });

                            ed.on('remove', function() {
                                element.remove();
                            });

                            if (uiTinymceConfig.setup) {
                                uiTinymceConfig.setup(ed, {
                                    updateView: updateView
                                });
                            }

                            if (expression.setup) {
                                expression.setup(ed, {
                                    updateView: updateView
                                });
                            }
                        },
                        format: expression.format || 'html',
                        selector: '#' + attrs.id
                    };


                    /*--------------------------------附件添加开始----------------------------------------------------------------------*/
                    /*  setupOptions.file_browser_callback= function(field_name, url, type, win) {
                          console.log(field_name,url,type,win);
                          scope.isOpen=true;
                          scope.$digest();
                         /!* win.document.getElementById(field_name).value = 'my browser value';*!/
                      };*/

                    setupOptions.file_picker_callback=function(callback, value, meta) {
                        console.log(callback,value,meta);
                        scope.isOpen=true;
                        scope.$digest();

                        // Provide file and text for the link dialog
                        if (meta.filetype == 'image') {
                            addImg(callback);
                        }

                        if (meta.filetype == 'media') {
                            addMedia(callback);
                        }
                    };
                    scope.isOpen=false;
                    scope.attachmentPopup = {
                        idList: "",
                        attachmentList: ""
                    };
                    //添加附件
                    var imgElem = angular.element("<div class='mce-content-img-body'><div xn-img-box-single  data-type='image'  " +
                        " ng-Model='attachmentPopup'  data-is-open-single='isOpen' data-disk-id='diskId'></div></div>");

                    var $imgElem = $compile(imgElem)(scope);
                    element.after($imgElem);

                    //监听显示

                    //监控单选
                    var unwatch=null;
                    function addImg(callback) {
                        unwatch=scope.$watch(function(){
                            return  scope.isOpen;
                        },function(newdata){
                            if(!newdata){
                                if(scope.attachmentPopup.idList){
                                    callback(scope.attachmentPopup.attachmentList.path, {alt: scope.attachmentPopup.attachmentList.fileName});
                                }
                                unwatch();
                            }
                        });
                    }

                    function addMedia(callback){
                        callback('movie.mp4', {source2: 'alt.ogg', poster: 'image.jpg'});
                    };

                    /*--------------------------------附件添加结束----------------------------------------------------------------------*/
                    // extend options with initial uiTinymceConfig and
                    // options from directive attribute value
                    angular.extend(options, uiTinymceConfig, expression, setupOptions);
                    // Wrapped in $timeout due to $tinymce:refresh implementation, requires
                    // element to be present in DOM before instantiating editor when
                    // re-rendering directive
                    $timeout(function() {
                        if (options.baseURL){
                            tinymce.baseURL = options.baseURL;
                        }
                        options.convert_urls = false;
                        var maybeInitPromise = tinymce.init(options);
                        if(maybeInitPromise && typeof maybeInitPromise.then === 'function') {
                            maybeInitPromise.then(function() {
                                toggleDisable(scope.$eval(attrs.ngDisabled));
                            });
                        } else {
                            toggleDisable(scope.$eval(attrs.ngDisabled));
                        }
                    });

                    ngModel.$formatters.unshift(function(modelValue) {
                        return modelValue ? $sce.trustAsHtml(modelValue) : '';
                    });

                    ngModel.$parsers.unshift(function(viewValue) {
                        return viewValue ? $sce.getTrustedHtml(viewValue) : '';
                    });

                    ngModel.$render = function() {
                        ensureInstance();

                        var viewValue = ngModel.$viewValue ?
                            $sce.getTrustedHtml(ngModel.$viewValue) : '';

                        // instance.getDoc() check is a guard against null value
                        // when destruction & recreation of instances happen
                        if (tinyInstance &&
                            tinyInstance.getDoc()
                        ) {
                            tinyInstance.setContent(viewValue);
                            // Triggering change event due to TinyMCE not firing event &
                            // becoming out of sync for change callbacks
                            tinyInstance.fire('change');
                        }
                    };

                    attrs.$observe('disabled', toggleDisable);

                    // This block is because of TinyMCE not playing well with removal and
                    // recreation of instances, requiring instances to have different
                    // selectors in order to render new instances properly
                    var unbindEventListener = scope.$on('$tinymce:refresh', function(e, id) {
                        var eid = attrs.id;
                        if (angular.isUndefined(id) || id === eid) {
                            var parentElement = element.parent();
                            var clonedElement = element.clone();
                            clonedElement.removeAttr('id');
                            clonedElement.removeAttr('style');
                            clonedElement.removeAttr('aria-hidden');
                            tinymce.execCommand('mceRemoveEditor', false, eid);
                            parentElement.append($compile(clonedElement)(scope));
                            unbindEventListener();
                        }
                    });

                    scope.$on('$destroy', function() {
                        ensureInstance();

                        if (tinyInstance) {
                            tinyInstance.remove();
                            tinyInstance = null;
                        }
                    });

                    function ensureInstance() {
                        if (!tinyInstance) {
                            tinyInstance = tinymce.get(attrs.id);
                        }
                    }
                }
            };
        }])
    .service('uiTinymceService', [
        /**
         * A service is used to create unique ID's, this prevents duplicate ID's if there are multiple editors on screen.
         */
        function() {
            var UITinymceService = function() {
                var ID_ATTR = 'ui-tinymce';
                // uniqueId keeps track of the latest assigned ID
                var uniqueId = 0;
                // getUniqueId returns a unique ID
                var getUniqueId = function() {
                    uniqueId ++;
                    return ID_ATTR + '-' + uniqueId;
                };
                // return the function as a public method of the service
                return {
                    getUniqueId: getUniqueId
                };
            };
            // return a new instance of the service
            return new UITinymceService();
        }
    ])
    .factory('ImgTinyService', ['$http',"xnConfig", function ($http,xnConfig) {
        var service = {};

        var url = xnConfig.myUrl+"api/foundation.do";
        var sysUrl=xnConfig.myUrl+"system/api.do";
        var uploadUrl=xnConfig.myUrl+"api/fileUpload.do";

        service.getTenant = function (data) {
            return $http({
                method: 'POST',
                url: sysUrl,
                data: data,
                params: {"method": "api.system.tenant.get"} });
        };

        service.apiFoundationDiskGet = function (data) {
            return $http({
                method: 'POST',
                url: url,
                data: data,
                params: {"method": "api.foundation.disk.get"} });
        };


        service.fileUpload = function (data) {

            return  $http({
                method: 'POST',
                url: uploadUrl,
                headers: {'Content-Type': undefined },
                transformRequest: angular.identity,
                data: data

            });
        };



        return service;
    }]);