Spade

Mini Shell

Directory:~$ /proc/self/root/home/lmsyaran/public_html/joomla5/plugins/fabrik_element/fileupload/
Upload File

[Home] [System Details] [Kill Me]
Current File:~$ //proc/self/root/home/lmsyaran/public_html/joomla5/plugins/fabrik_element/fileupload/fileupload.js

/**
 * File Upload Element
 *
 * @copyright: Copyright (C) 2005-2016  Media A-Team, Inc. - All rights
reserved.
 * @license: GNU/GPL http://www.gnu.org/copyleft/gpl.html
 */


define(['jquery', 'fab/fileelement'], function (jQuery,
FbFileElement) {
    window.FbFileUpload = new Class({
        Extends   : FbFileElement,
        options : {
            folderSelect: false,
            ajax_upload: false,
            ajax_show_widget: true,
            isCarousel: false
        },
        initialize: function (element, options) {
            var self = this;
            this.setPlugin('fileupload');
            this.parent(element, options);
            this.container = jQuery(this.container);
            this.toppath = this.options.dir;
            if (this.options.folderSelect === '1' &&
this.options.editable === true) {
                this.ajaxFolder();
            }

            this.doBrowseEvent = null;
            this.watchBrowseButton();

            if (this.options.ajax_upload && this.options.editable
!== false) {
               
Fabrik.fireEvent('fabrik.fileupload.plupload.build.start', this);
                this.watchAjax();
                if (Object.keys(this.options.files).length !== 0) {
                    this.uploader.trigger('FilesAdded',
this.options.files);
                    jQuery.each(this.options.files, function (key, file) {
                        var response = {
                                filepath  : file.path,
                                uri       : file.url,
                                showWidget: false
                            },
                            newBar =
jQuery(Fabrik.jLayouts['fabrik-progress-bar-success'])[0],
                            bar = jQuery('#' +
file.id).find('.bar')[0];
                        self.uploader.trigger('UploadProgress',
file);
                        self.uploader.trigger('FileUploaded',
file, {
                            response: JSON.stringify(response)
                        });

                        jQuery(bar).replaceWith(newBar);
                    });
                }
                this.redraw();
            }

            this.doDeleteEvent = null;
            this.watchDeleteButton();
            this.watchTab();

            if (this.options.isCarousel)
            {
                jQuery('.slickCarousel').slick();
               
jQuery('.slickCarouselImage').css('opacity',
'1');
            }

            if (this.options.isZoom) {
               
jQuery('.slick-active').find('img').ezPlus({
                    zoomType: 'lens',
                    lensShape: 'round',
                    lensSize: 200
                });

               
jQuery('.slickCarousel').on('beforeChange',
function(event, slick, currentSlide, nextSlide){
                   
jQuery('.zoomWindowContainer,.zoomContainer').remove();
                });

               
jQuery('.slickCarousel').on('afterChange',
function(event, slick, currentSlide){
                   
jQuery('.slick-active').find('img').ezPlus({
                        zoomType: 'lens',
                        lensShape: 'round',
                        lensSize: 200
                    });
                });
            }
        },

        /**
         * Reposition the hidden input field over the 'add'
button. Called on initiate and if in a tab
         * and the tab is activated. Triggered from element.watchTab()
         */
        redraw: function () {
            var el = jQuery(this.element);
            if (this.options.editable && this.options.ajax_upload)
{
                var browseButton = jQuery('#' +
el.prop('id') + '_browseButton'),
                    c = jQuery('#' + this.options.element +
'_container'),
                    diff = browseButton.position().left -
c.position().left;
                // $$$ hugh - working on some IE issues
                var file_element =
c.closest('.fabrikElement').find('input[type=file]');
                if (file_element.length > 0) {
                    var fileContainer = file_element.parent();
                    fileContainer.css({
                        'width' : browseButton.width(),
                        'height': browseButton.height()
                    });
                    fileContainer.css('top', diff);
                }
            }

            if (this.options.isCarousel)
            {
               
jQuery('.slickCarousel').slick('resize');
            }
        },

        doBrowse: function (evt) {
            if (window.File && window.FileReader &&
window.FileList && window.Blob) {
                var reader, self = this,
                    files = evt.target.files,
                    f = files[0];

                // Only process image files.
                if (f.type.match('image.*')) {
                    reader = new FileReader();
                    // Closure to capture the file information.
                    reader.onload = (function (theFile) {
                        return function (e) {
                            var c = jQuery(self.getContainer()),
                                b = c.find('img');
                            b.attr('src', e.target.result);
                            var d = b.closest('.fabrikHide');
                            d.removeClass('fabrikHide');
                            var db = c.find('[data-file]');
                            db.addClass('fabrikHide');
                        };
                    }.bind(this))(f);
                    // Read in the image file as a data URL.
                    reader.readAsDataURL(f);
                }
                else if (f.type.match('video.*')) {
                    var c = jQuery(this.getContainer()),
                        video = c.find('video');
                    if (video.length > 0) {
                        video = this.makeVideoPreview();
                        video.appendTo(c);
                    }

                    reader = new window.FileReader();
                    var url;

                    reader = window.URL || window.webKitURL;

                    if (reader && reader.createObjectURL) {
                        url = reader.createObjectURL(f);
                        video.attr('src', url);
                        return;
                    }

                    if (!window.FileReader) {
                        console.log('Sorry, not so much');
                        return;
                    }

                    reader = new window.FileReader();
                    reader.onload = function (eo) {
                        video.attr('src', eo.target.result);
                    };
                    reader.readAsDataURL(f);
                }
            }
        },

        watchBrowseButton: function () {
            var el = jQuery(this.element);
            if (this.options.useWIP && !this.options.ajax_upload
&& this.options.editable !== false) {
                el.off('change', this.doBrowseEvent);
                this.doBrowseEvent = this.doBrowse.bind(this);
                el.on('change', this.doBrowseEvent);
            }
        },

        /**
         * Called from watchDeleteButton
         *
         * @param {Event} e
         */
        doDelete: function (e) {
            e.preventDefault();
            var c = jQuery(this.getContainer()),
                self = this,
                b = c.find('[data-file]');
            if
(window.confirm(Joomla.JText._('PLG_ELEMENT_FILEUPLOAD_CONFIRM_SOFT_DELETE')))
{
                var joinPkVal = b.data('join-pk-val');
                new jQuery.ajax({
                    url : '',
                    data: {
                        'option'    : 'com_fabrik',
                        'format'    : 'raw',
                        'task'      :
'plugin.pluginAjax',
                        'plugin'    : 'fileupload',
                        'method'    :
'ajax_clearFileReference',
                        'element_id': this.options.id,
                        'formid'    : this.form.id,
                        'rowid'     : this.form.options.rowid,
                        'joinPkVal' : joinPkVal
                    }
                }).done(function () {
                   
Fabrik.trigger('fabrik.fileupload.clearfileref.complete', self);
                });

                if
(window.confirm(Joomla.JText._('PLG_ELEMENT_FILEUPLOAD_CONFIRM_HARD_DELETE')))
{
                    this.makeDeletedImageField(this.groupid,
b.data('file')).appendTo(c);
                   
Fabrik.fireEvent('fabrik.fileupload.delete.complete', this);
                }

                b.remove();
	            var el = jQuery(this.element);
	            var i =
el.closest('.fabrikElement').find('img');
	            i.attr('src', this.options.defaultImage !==
'' ? Fabrik.liveSite + this.options.defaultImage : '');
            }
        },

        /**
         * Single file uploads can allow the user to delete the reference
and/or file
         */
        watchDeleteButton: function () {
            var c = jQuery(this.getContainer()),
                b = c.find('[data-file]');
            b.off('click', this.doDeleteEvent);
            this.doDeleteEvent = this.doDelete.bind(this);
            b.on('click', this.doDeleteEvent);
        },

        /**
         * Sets the element key used in Fabrik.blocks.form_X.formElements
overwritten by dbjoin rendered as checkbox
         *
         * @since 3.0.7
         *
         * @return string
         */
        getFormElementsKey: function (elId) {
            this.baseElementId = elId;
            if (!this.options.inRepeatGroup &&
this.options.ajax_upload && this.options.ajax_max > 1) {
                return this.options.listName + '___' +
this.options.elementShortName;
            } else {
                return this.parent(elId);
            }
        },

        /**
         * When in ajax form, on submit the list will call this, so we can
remove the submit event if we dont do that, upon a second form submission
the
         * original submitEvent is used causing a js error as it still
references the files uploaded in the first form
         */
        removeCustomEvents: function () {
            // Fabrik.removeEvent('fabrik.form.submit.start',
this.submitEvent);
        },

        cloned: function (c) {
            if (this.options.ajax_upload) {
               
jQuery(this.getContainer()).find('.plupload_container').prop('id',
this.element.id + '_container');
               
jQuery(this.getContainer()).find('.plupload').prop('id',
this.element.id + '_dropList_container');
               
jQuery(this.getContainer()).find('.plupload_filelist').prop('id',
this.element.id + '_dropList');
               
jQuery(this.getContainer()).find('.plupload_browsebutton').prop('id',
this.element.id + '_browseButton');
               
jQuery(this.getContainer()).find('input').remove();
                this.watchAjax();
            }
            else {
                var el = jQuery(this.element);
                // replaced cloned image with default image
                if (el.closest('.fabrikElement').length === 0) {
                    return;
                }
                var i =
el.closest('.fabrikElement').find('img');
                i.attr('src', this.options.defaultImage !==
'' ? Fabrik.liveSite + this.options.defaultImage : '');
               
jQuery(this.getContainer()).find('[data-file]').remove();
                this.watchBrowseButton();
            }
            this.parent(c);
        },

        decloned: function (groupid) {
            var i = jQuery('#form_' +
this.form.id).find('input[name="fabrik_deletedimages[' +
groupid + ']"]');
            if (i.length > 0) {
                this.makeDeletedImageField(groupid,
this.options.value).inject(this.form.form);
            }
            this.parent(groupid);
        },

        decreaseName: function (delIndex) {
            var f = this.getOrigField();
            if (typeOf(f) !== 'null') {
                f.name = this._decreaseName(f.name, delIndex);
                f.id = this._decreaseId(f.id, delIndex);
            }
            return this.parent(delIndex);
        },

        getOrigField: function () {
            var p = this.element.getParent('.fabrikElement');
            var f = p.getElement('input[name^=' + this.origId +
'_orig]');
            if (typeOf(f) === 'null') {
                f = p.getElement('input[id^=' + this.origId +
'_orig]');
            }
            return f;
        },

        /**
         * Create a hidden input which will tell fabrik, upon form
submission, to delete the file
         *
         * @param {int} groupId group id
         * @param {string} value file to delete
         *
         * @return Element DOM Node - hidden input
         */
        makeDeletedImageField: function (groupId, value) {
            return jQuery(document.createElement('input')).attr({
                'type' : 'hidden',
                'name' :
'fabrik_fileupload_deletedfile[' + groupId + '][]',
                'value': value
            });
        },

        makeVideoPreview: function () {
            var el = jQuery(this.element);
            return jQuery(document.createElement('video')).attr({
                'id'      : el.prop('id') +
'_video_preview',
                'controls': true
            });
        },

        update: function (val) {
            if (this.element) {
                var el = jQuery(this.element);
                if (val === '') {
                    if (this.options.ajax_upload) {
                        this.uploader.files = [];
                        el.parent().find('[id$=_dropList]
tr').remove();
                    } else {
                        el.val('');
                    }
                } else {
                    var img =
el.closest('div.fabrikSubElementContainer').find('img');
                    if (img) {
                        img.prop('src', val);
                    }
                }
            }
        },

        addDropArea: function () {
            if (!Fabrik.bootstraped) {
                return;
            }
            var dropTxt =
this.container.find('tr.plupload_droptext'), tr;
            if (dropTxt.length > 0) {
                dropTxt.show();
            } else {
                tr =
jQuery(document.createElementget('tr')).addClass('plupload_droptext').html('<td
colspan="4"><i class="icon-move"></i>
' + Joomla.JText
                       
._('PLG_ELEMENT_FILEUPLOAD_DRAG_FILES_HERE') + '
</td>');
                this.container.find('tbody').append(tr);
            }
            this.container.find('thead').hide();
        },

        removeDropArea: function () {
            this.container.find('tr.plupload_droptext').hide();
        },

        watchAjax: function () {
            if (this.options.editable === false) {
                return;
            }
            var a, self = this,
                elementId = jQuery(this.element).prop('id'),
                el = jQuery(this.getElement());
            if (el.length === 0) {
                return;
            }
            var c = el.closest('.fabrikSubElementContainer');
            this.container = c;

            if (this.options.ajax_show_widget &&
this.options.canvasSupport !== false) {
                this.widget = new ImageWidget(this.options.modalId, {

                    'imagedim': {
                        x: 200,
                        y: 200,
                        w: this.options.winWidth,
                        h: this.options.winHeight
                    },

                    'cropdim': {
                        w: this.options.cropwidth,
                        h: this.options.cropheight,
                        x: this.options.winWidth / 2,
                        y: this.options.winHeight / 2
                    },
                    crop     : this.options.crop,
                    modalId  : this.options.modalId,
                    quality  : this.options.quality
                });
            }
            this.pluploadContainer =
c.find('.plupload_container');
            this.pluploadFallback = c.find('.plupload_fallback');
            this.droplist = c.find('.plupload_filelist');
            var url =
'index.php?option=com_fabrik&format=raw&task=plugin.pluginAjax';
            url += '&plugin=fileupload&' +
this.options.ajaxToken + '=1';
            url += '&method=ajax_upload&element_id=' +
this.options.elid;

            if (this.options.isAdmin) {
                url = 'administrator/' + url;
            }

            var plupopts = {
                runtimes           : this.options.ajax_runtime,
                browse_button      : elementId + '_browseButton',
                container          : elementId + '_container',
                drop_element       : elementId +
'_dropList_container',
                url                : url,
                max_file_size      : this.options.max_file_size +
'kb',
                unique_names       : false,
                flash_swf_url      : this.options.ajax_flash_path,
                silverlight_xap_url: this.options.ajax_silverlight_path,
                chunk_size         : this.options.ajax_chunk_size +
'kb',
                dragdrop           : true,
                multipart          : true,
                filters            : this.options.filters,
                page_url           : this.options.page_url
            };
            this.uploader = new plupload.Uploader(plupopts);

            // (1) INIT ACTIONS
            this.uploader.bind('Init', function (up, params) {
                // FORCEFULLY NUKE GRACEFUL DEGRADING FALLBACK ON INIT
                self.pluploadFallback.remove();
                self.pluploadContainer.removeClass('fabrikHide');

                if (up.features.dragdrop && up.settings.dragdrop) {
                    self.addDropArea();
                }

            });

            /*
             */
            this.uploader.bind('FilesRemoved', function (up,
files) {
            });

            // (2) ON FILES ADDED ACTION
            this.uploader.bind('FilesAdded', function (up, files)
{
                self.removeDropArea();
                var rElement = Fabrik.bootstrapped ? 'tr' :
'li', count;
                self.lastAddedFiles = files;
                if (Fabrik.bootstrapped) {
                   
self.container.find('thead').css('display',
'');
                }
                count = self.droplist.find(rElement).length;
                jQuery.each(files, function (key, file) {
                    //files.each(function (file, idx) {
                    if (file.size > self.options.max_file_size * 1000) {
                       
window.alert(Joomla.JText._('PLG_ELEMENT_FILEUPLOAD_FILE_TOO_LARGE_SHORT'));
                    } else {
                        if (count >= self.options.ajax_max) {
                           
window.alert(Joomla.JText._('PLG_ELEMENT_FILEUPLOAD_MAX_UPLOAD_REACHED'));
                        } else {
                            count++;
                            var a, title, innerLi;
                            if (self.isImage(file)) {
                                a = self.editImgButton();
                                if (self.options.crop) {
                                    a.html(self.options.resizeButton);
                                } else {
                                    a.html(self.options.previewButton);
                                }
                                title =
jQuery(document.createElement('span')).text(file.name);
                            } else {
                                a =
jQuery(document.createElement('span'));
                                title =
jQuery(document.createElement('a')).attr({
                                    'href': file.url,
                                    'target': '_blank'
                                }).text(file.name);
                            }

                            innerLi = self.imageCells(file, title, a);

                           
self.droplist.append(jQuery(document.createElement(rElement)).attr({
                                id     : file.id,
                                'class':
'plupload_delete'
                            }).append(innerLi));
                        }
                    }
                });

                // Automatically start the upload - need delay to ensure
up.files is populated
                setTimeout(function () {
                    up.start();
                }, 100);
            });

            // (3) ON FILE UPLOAD PROGRESS ACTION
            this.uploader.bind('UploadProgress', function (up,
file) {
                var f = jQuery('#' + file.id);
                if (f.length > 0) {
                    if (Fabrik.bootstrapped) {
                        var bar = f.find('.plupload_file_status
.bar');
                        bar.css('width', file.percent +
'%');
                        if (file.percent === 100) {
                            var newBar =
jQuery(Fabrik.jLayouts['fabrik-progress-bar-success']);
                            bar.replaceWith(newBar);
                        }
                    } else {
                       
f.find('.plupload_file_status').text(file.percent +
'%');
                    }
                }
            });

            this.uploader.bind('Error', function (up, err) {
                self.lastAddedFiles.each(function (file) {
                    var row = jQuery('#' + file.id);
                    if (row.length > 0) {
                        row.remove();
                        window.alert(err.message);
                    }
                    self.addDropArea();
                });
            });

            this.uploader.bind('ChunkUploaded', function (up,
file, response) {
                response = JSON.parse(response.response);
                if (typeof(response) === 'object') {
                    if (response.error) {
                        fconsole(response.error.message);
                    }
                }
            });

            this.uploader.bind('FileUploaded', function (up,
file, response) {
                var name, showWidget, f, resizeButton, idValue,
                    f = jQuery('#' + file.id)
                response = JSON.parse(response.response);
                if (response.error) {
                    window.alert(response.error);
                    f.remove();
                    return;
                }

                if (f.length === 0) {
                    fconsole('Filuploaded didnt find: ' +
file.id);
                    return;
                }
                resizeButton = f.find('.plupload_resize a');
                resizeButton.show();
                resizeButton.attr({
                    href: response.uri,
                    id  : 'resizebutton_' + file.id
                });

                resizeButton.data('filepath', response.filepath);

                if (self.widget) {
                    showWidget = response.showWidget === false ? false :
true;
                    self.widget.setImage(response.uri, response.filepath,
file.params, showWidget);
                }

                if (self.options.inRepeatGroup) {
                    name = self.options.elementName.replace(/\[\d*\]/,
'[' + self.getRepeatNum() + ']');
                } else {
                    name = self.options.elementName;
                }
                // Stores the cropparams which we need to reload the crop
widget in the correct state (rotation, zoom, etc)
                jQuery(document.createElement('input')).attr({
                    'type' : 'hidden',
                    name   : name + '[crop][' + response.filepath
+ ']',
                    'id'   : 'coords_' + file.id,
                    'value': JSON.stringify(file.params)
                }).insertAfter(self.pluploadContainer);


                // Stores the actual crop image data retrieved from the
canvas
                jQuery(document.createElement('input')).attr({
                    type: 'hidden',
                    name: name + '[cropdata][' +
response.filepath + ']',
                    'id': 'data_' + file.id
                }).insertAfter(self.pluploadContainer);

                // Stores the image id if > 1 fileupload
                idValue = [file.recordid, '0'].pick();
                jQuery(document.createElement('input')).attr({
                    'type' : 'hidden',
                    name   : name + '[id][' + response.filepath +
']',
                    'id'   : 'id_' + file.id,
                    'value': idValue
                }).insertAfter(self.pluploadContainer);

               
f.removeClass('plupload_file_action').addClass('plupload_done');

                self.isSubmitDone();
            });

            // (5) KICK-START PLUPLOAD
            this.uploader.init();
        },

        /**
         * Create an array of the dom elements to inject into a row
representing an uploaded file
         *
         * @return {array}
         */
        imageCells: function (file, title, a) {
            var del = this.deleteImgButton(), filename, status, progress,
icon;
            if (Fabrik.bootstrapped) {
                icon =
jQuery(document.createElement('td')).addClass(this.options.spanNames[1]
+ ' plupload_resize').append(a);
                progress =
Fabrik.jLayouts['fabrik-progress-bar'];
                status =
jQuery(document.createElement('td')).addClass(this.options.spanNames[5]
+ ' plupload_file_status').html(progress);
                filename =
jQuery(document.createElement('td')).addClass(this.options.spanNames[6]
+ ' plupload_file_name').append(title);

                return [filename, icon, status, del];
            } else {
                filename = new Element('div', {
                    'class': 'plupload_file_name'
                }).adopt([title, new Element('div', {
                    'class': 'plupload_resize',
                    style  : 'display:none'
                }).adopt(a)]);
                status = new Element('div', {
                    'class': 'plupload_file_status'
                }).set('text', '0%');
                var size = new Element('div', {
                    'class': 'plupload_file_size'
                }).set('text', file.size);

                return [filename, del, status, size, new
Element('div', {
                    'class': 'plupload_clearer'
                })];
            }
        },

        /**
         * Create edit image button
         *
         * @return {jQuery}
         */
        editImgButton: function () {
            var self = this;
            if (Fabrik.bootstrapped) {
                return
jQuery(document.createElement('a')).addClass('editImage').attr({
                    'href': '#',
                    alt   :
Joomla.JText._('PLG_ELEMENT_FILEUPLOAD_RESIZE')
                }).css({
                    'display': 'none'
                }).on('click', function (e) {
                    e.preventDefault();
                    //var a = e.target.getParent();
                    self.pluploadResize(jQuery(this));
                });

            } else {
                return new Element('a', {
                    'href': '#',
                    alt   :
Joomla.JText._('PLG_ELEMENT_FILEUPLOAD_RESIZE'),
                    events: {
                        'click': function (e) {
                            e.stop();
                            var a = e.target.getParent();
                            this.pluploadResize(jQuery(a));
                        }.bind(this)
                    }
                });
            }
        },

        /**
         * Create delete image button
         *
         * @return {jQuery}
         */
        deleteImgButton: function () {
            if (Fabrik.bootstrapped) {

                var icon = Fabrik.jLayouts['fabrik-icon-delete'],
                    self = this;
                return
jQuery(document.createElement('td')).addClass(this.options.spanNames[1]
+ ' plupload_file_action').append(
                    jQuery(document.createElement('a'))
                        .html(icon)
                        .attr({
                            'href' : '#'
                        })
                        .on('click', function (e) {
                            e.stopPropagation();
                            self.pluploadRemoveFile(e);
                        })
                );

            } else {
                return new Element('div', {
                    'class': 'plupload_file_action'
                }).adopt(new Element('a', {
                    'href' : '#',
                    'style': 'display:block',
                    events : {
                        'click': function (e) {
                            this.pluploadRemoveFile(e);
                        }.bind(this)
                    }
                }));
            }
        },

        /**
         * Test if the plupload file object contains an image.
         * @param {object} file
         * @returns {*}
         */
        isImage: function (file) {
            if (file.type !== undefined) {
                return file.type === 'image';
            }
            var ext = file.name.split('.').pop().toLowerCase();
            return ['jpg', 'jpeg', 'png',
'gif'].contains(ext);
        },

        pluploadRemoveFile: function (e) {
            e.stopPropagation();
            if
(!window.confirm(Joomla.JText._('PLG_ELEMENT_FILEUPLOAD_CONFIRM_HARD_DELETE')))
{
                return;
            }

            var id =
jQuery(e.target).closest('tr').prop('id').split('_').pop();//
alreadyuploaded_8_13
            // $$$ hugh - removed ' span' from the find(), as
this blows up on some templates
            var f =
jQuery(e.target).closest('tr').find('.plupload_file_name').text();

            // Get a list of all of the uploaders files except the one to
be deleted
            var newFiles = [];
            this.uploader.files.each(function (f) {
                if (f.id !== id) {
                    newFiles.push(f);
                }
            });

            // Update the uploader's files with the new list.
            this.uploader.files = newFiles;

            // Send a request to delete the file from the server.
            var self = this;
            var data = {
                'option'       : 'com_fabrik',
                    'format'       : 'raw',
                    'task'         :
'plugin.pluginAjax',
                    'plugin'       : 'fileupload',
                    'method'       : 'ajax_deleteFile',
                    'element_id'   : this.options.id,
                    'file'         : f,
                    'recordid'     : id,
                    'repeatCounter': this.options.repeatCounter
            }

            data[this.options.ajaxToken] = 1;

            jQuery.ajax({
                url : '',
                data: data
            }).done(function (r) {
                r = JSON.parse(r);
                if (r.error === '') {
                   
Fabrik.trigger('fabrik.fileupload.delete.complete', self);
                    var li =
jQuery(e.target).closest('.plupload_delete');
                    li.remove();

                    // Remove hidden fields as well
                    jQuery('#id_alreadyuploaded_' +
self.options.id + '_' + id).remove();
                    jQuery('#coords_alreadyuploaded_' +
self.options.id + '_' + id).remove();

                    if (jQuery(self.getContainer()).find('table tbody
tr.plupload_delete').length === 0) {
                        self.addDropArea();
                    }
                }
            });
        },

        /**
         *
         * @param {jQuery} a
         */
        pluploadResize: function (a) {
            if (this.widget) {
                this.widget.setImage(a.attr('href'),
a.data('filepath'), {}, true);
            }
        },

        /**
         * Once the upload fires a FileUploaded bound function we test if
all images for this element have been
         * uploaded If they have then we save the
         * crop widget state and fire the callback - which is handled by
FbFormSubmit()
         */
        isSubmitDone: function () {
            if (this.allUploaded() && typeof (this.submitCallBack)
=== 'function') {
                this.saveWidgetState();
                this.submitCallBack(true);
                delete this.submitCallBack;
            }
        },

        /**
         * Called from FbFormSubmit.submit() handles testing. If not yet
uploaded, triggers the
         * upload and defers the callback until the upload is
         * complete. If complete then saves widget state and calls parent
onsubmit().
         */
        onsubmit: function (cb) {
            this.submitCallBack = cb;
            if (!this.allUploaded()) {
                this.uploader.start();
            } else {
                this.saveWidgetState();
                this.parent(cb);
            }
        },

        /**
         * Save the crop widget state as a json object
         */
        saveWidgetState: function () {
            if (this.widget !== undefined) {
                jQuery.each(this.widget.images, function (key, image) {
                    key = key.split('\\').pop();
                    var f = jQuery('input[name*="' + key +
'"]').filter(function (i, fld) {
                        return fld.name.contains('[crop]');
                    });
                    f = f.last();

                    // $$$ rob - seems reloading ajax fileupload element in
ajax form (e.g. from db join add record)
                    // is producing odd effects where old fileupload object
contains info to previously uploaded image?
                    if (f.length > 0) {

                        // Avoid circular reference in chrome when saving
in ajax form
                        var i = image.img;
                        delete (image.img);
                        f.val(JSON.stringify(image));
                        image.img = i;
                    }
                });
            }
        },

        allUploaded: function () {
            var uploaded = true;
            if (this.uploader) {
                this.uploader.files.each(function (file) {
                    if (file.loaded === 0) {
                        uploaded = false;
                    }
                });
            }
            return uploaded;
        }
    });

    var ImageWidget = new Class({

        initialize: function (modalId, opts) {
            this.modalId = modalId;

            // When element is in modal window it renders fine the first
time. But the second time
            // the original window is still there - so we end up with 2 dom
structures and one window object.
            // To get round this set the first window to be destroyed and
close it.
            if (Fabrik.Windows[this.modalId]) {
                Fabrik.Windows[this.modalId].options.destroy = true;
                Fabrik.Windows[this.modalId].close();
            }

            this.imageDefault = {
                'rotation': 0,
                'scale'   : 100,
                'imagedim': {
                    x: 200,
                    y: 200,
                    w: 400,
                    h: 400
                },
                'cropdim' : {
                    x: 75,
                    y: 25,
                    w: 150,
                    h: 50
                }
            };

            jQuery.extend(this.imageDefault, opts);

            this.windowopts = {
                'id'             : this.modalId,
                'type'           : 'modal',
                loadMethod       : 'html',
                width            : parseInt(this.imageDefault.imagedim.w,
10) + 40,
                height           : parseInt(this.imageDefault.imagedim.h,
10) + 170,
                storeOnClose     : true,
                createShowOverLay: false,
                crop             : opts.crop,
                destroy          : false,
                modalId          : opts.modalId,
                quality          : opts.quality,
                onClose          : function () {
                    this.storeActiveImageData();
                }.bind(this),
                onContentLoaded  : function () {
                    this.center();
                },
                onOpen           : function () {
                    this.center();
                }
            };
            this.windowopts.title = opts.crop ?
Joomla.JText._('PLG_ELEMENT_FILEUPLOAD_CROP_AND_SCALE') :
Joomla.JText
                ._('PLG_ELEMENT_FILEUPLOAD_PREVIEW');
            this.showWin();

            this.canvas = jQuery(this.window).find('canvas')[0];

            this.images = {};
            this.CANVAS = new FbCanvas({
                canvasElement: this.canvas,
                enableMouse  : true,
                cacheCtxPos  : false
            });

            this.CANVAS.layers.add(new Layer({
                id: 'bg-layer'
            }));
            this.CANVAS.layers.add(new Layer({
                id: 'image-layer'
            }));
            if (opts.crop) {
                this.CANVAS.layers.add(new Layer({
                    id: 'overlay-layer'
                }));
                this.CANVAS.layers.add(new Layer({
                    id: 'crop-layer'
                }));
            }
            var bg = new CanvasItem({
                id    : 'bg',
                scale : 1,
                events: {
                    onDraw: function (ctx) {
                        if (ctx === undefined) {
                            ctx = this.CANVAS.ctx;
                        }
                        ctx.fillStyle = '#DFDFDF';
                        ctx.fillRect(0, 0, this.imageDefault.imagedim.w /
this.scale, this.imageDefault.imagedim.h / this.scale);
                    }.bind(this)
                }
            });

            this.CANVAS.layers.get('bg-layer').add(bg);
            if (opts.crop) {
                this.overlay = new CanvasItem({
                    id    : 'overlay',
                    events: {
                        onDraw: function (ctx) {
                            if (ctx === undefined) {
                                ctx = this.CANVAS.ctx;
                            }
                            //this.withinCrop = true;
                            if (this.overlay.withinCrop) {
                                var top = {
                                    x: 0,
                                    y: 0
                                };
                                var bottom = {
                                    x: this.imageDefault.imagedim.w,
                                    y: this.imageDefault.imagedim.h
                                };
                                ctx.fillStyle = 'rgba(0, 0, 0,
0.3)';
                                var cropper = this.cropperCanvas;
                                ctx.fillRect(top.x, top.y, bottom.x,
cropper.y - (cropper.h / 2));// top
                                ctx.fillRect(top.x - (cropper.w / 2), top.y
+ cropper.y - (cropper.h / 2), top.x + cropper.x, cropper.h);// left
                                ctx.fillRect(top.x + cropper.x + cropper.w
- (cropper.w / 2), top.y + cropper.y - (cropper.h / 2), bottom.x,
cropper.h);// right
                                ctx.fillRect(top.x, top.y + (cropper.y +
cropper.h) - (cropper.h / 2), bottom.x, bottom.y);// bottom
                            }
                        }.bind(this)
                    }
                });

               
this.CANVAS.layers.get('overlay-layer').add(this.overlay);
            }

            this.imgCanvas = this.makeImgCanvas();

           
this.CANVAS.layers.get('image-layer').add(this.imgCanvas);

            this.cropperCanvas = this.makeCropperCanvas();
            if (opts.crop) {
                // add an item
               
this.CANVAS.layers.get('crop-layer').add(this.cropperCanvas);
            }
            this.makeThread();
            this.watchZoom();
            this.watchRotate();
            this.watchClose();
            this.win.close();
        },

        /**
         * Add or make active an image in the editor
         *
         * @param {string} uri Image URI
         * @param {string} filepath Path to file
         * @param {object} params Initial parameters
         * @param {Boolean} showWin
         */
        setImage: function (uri, filepath, params, showWin) {
            showWin = showWin ? showWin : false;
            this.activeFilePath = filepath;
            if (!this.images.hasOwnProperty(filepath)) {

                // Needed to ensure they are available in onLoad
                var tmpParams = params;

                // New image
                var img = Asset.image(uri, {
                    crossOrigin: 'anonymous',
                    onLoad: function () {

                        var params = this.storeImageDimensions(filepath,
jQuery(img), tmpParams);
                        this.img = params.img;
                        this.setInterfaceDimensions(params);
                        this.showWin();
                        this.storeActiveImageData(filepath);
                        if (!showWin) {
                            this.win.close();
                        }
                    }.bind(this)
                });
            } else {

                // Previously set up image
                params = this.images[filepath];
                this.img = params.img;
                this.setInterfaceDimensions(params);
                if (showWin) {
                    this.showWin();
                }
            }
        },

        /**
         * Set rotate, scale, image and crop values for a given image
         *
         * @param object params Image parameters
         */
        setInterfaceDimensions: function (params) {
            if (this.scaleSlide) {
                this.scaleSlide.set(params.scale);
            }
            if (this.rotateSlide) {
                this.rotateSlide.set(params.rotation);
            }

            if (this.cropperCanvas && params.cropdim) {
                this.cropperCanvas.x = params.cropdim.x;
                this.cropperCanvas.y = params.cropdim.y;
                this.cropperCanvas.w = params.cropdim.w;
                this.cropperCanvas.h = params.cropdim.h;
            }
            this.imgCanvas.w = params.mainimagedim.w;
            this.imgCanvas.h = params.mainimagedim.h;
            this.imgCanvas.x = params.imagedim !== undefined ?
params.imagedim.x : 0;
            this.imgCanvas.y = params.imagedim !== undefined ?
params.imagedim.y : 0;
        },

        /**
         * One time call to store initial image crop info in this.images
         *
         * @param {string} filepath Path to image
         * @param {jQuery} img Image - just created
         * @param {object} params object Image parameters
         *
         * @return object Update image parameters
         */

        storeImageDimensions: function (filepath, img, params) {
            // .hide() not working in UIKit
            img.appendTo(document.body).css({'display':
'none'});
            params = params ? params : new CloneObject(this.imageDefault,
true, []);
            var s = img[0].getDimensions(true);
            if (!params.imagedim) {
                params.mainimagedim = {};
            } else {
                params.mainimagedim = params.imagedim;
            }
            params.mainimagedim.w = s.width;
            params.mainimagedim.h = s.height;
            params.img = img[0];
            this.images[filepath] = params;

            return params;
        },

        makeImgCanvas: function () {
            var parent = this;
            return new CanvasItem({
                id         : 'imgtocrop',
                w          : this.imageDefault.imagedim.w,
                h          : this.imageDefault.imagedim.h,
                x          : 200,
                y          : 200,
                interactive: true,
                rotation   : 0,
                scale      : 1,
                offset     : [0, 0],
                events     : {
                    onMousemove: function (x, y) {
                        if (this.dragging) {
                            var w = this.w * this.scale;
                            var h = this.h * this.scale;
                            this.x = x - this.offset[0] + w * 0.5;
                            this.y = y - this.offset[1] + h * 0.5;
                        }
                    },
                    onDraw     : function (ctx) {
                        ctx = parent.CANVAS.ctx;
                        if (parent.img === undefined) {
                            // console.log('no parent img',
parent);
                            return;
                        }

                        var w = this.w * this.scale;
                        var h = this.h * this.scale;
                        var x = this.x - w * 0.5;
                        var y = this.y - h * 0.5;

                        // standard Canvas rotation operation
                        ctx.save();
                        ctx.translate(this.x, this.y);
                        ctx.rotate(this.rotation * Math.PI / 180);

                        this.hover ? ctx.strokeStyle = '#f00' :
ctx.strokeStyle = '#000';
                        ctx.strokeRect(w * -0.5, h * -0.5, w, h);
                        if (parent.img !== undefined) {
                            try {
                                ctx.drawImage(parent.img, w * -0.5, h *
-0.5, w, h);
                            } catch (err) {
                                // only show this for debugging as if we
upload a pdf then we get shown lots of these errors.
                                // fconsole(err, parent.img, w * -0.5, h *
-0.5, w, h);
                            }
                        }
                        ctx.restore();
                        if (parent.img !== undefined &&
parent.images.hasOwnProperty(parent.activeFilePath)) {
                            parent.images[parent.activeFilePath].imagedim =
{
                                x: this.x,
                                y: this.y,
                                w: w,
                                h: h
                            };

                        }
                        this.setDims(x, y, w, h);
                    },

                    onMousedown: function (x, y) {
                        parent.CANVAS.setDrag(this);
                        this.offset = [x - this.dims[0], y - this.dims[1]];
                        this.dragging = true;
                    },

                    onMouseup: function () {
                        parent.CANVAS.clearDrag();
                        this.dragging = false;
                    },

                    onMouseover: function () {
                        parent.overImg = true;
                        document.body.style.cursor = "move";
                    },

                    onMouseout: function () {
                        parent.overImg = false;
                        if (!parent.overCrop) {
                            document.body.style.cursor =
"default";
                        }
                    }
                }
            });
        },

        makeCropperCanvas: function () {
            var parent = this;
            return new CanvasItem({
                id         : 'item',
                x          : 175,
                y          : 175,
                w          : 150,
                h          : 50,
                interactive: true,
                offset     : [0, 0],
                events     : {
                    onDraw: function (ctx) {
                        ctx = parent.CANVAS.ctx;
                        if (ctx === undefined) {
                            return;
                        }
                        /*
                         * calculate dimensions locally because they are
have to be translated in order to use translate and rotate with the desired
                         * effect: rotate the item around its visual center
                         */

                        var w = this.w;
                        var h = this.h;
                        var x = this.x - w * 0.5;
                        var y = this.y - h * 0.5;

                        // standard Canvas rotation operation

                        ctx.save();
                        ctx.translate(this.x, this.y);

                        this.hover ? ctx.strokeStyle = '#f00' :
ctx.strokeStyle = '#000';
                        ctx.strokeRect(w * -0.5, h * -0.5, w, h);
                        ctx.restore();

                        /*
                         * used to determine the whether the mouse is over
an item or not.
                         */

                        if (parent.img !== undefined &&
parent.images.hasOwnProperty(parent.activeFilePath)) {
                            parent.images[parent.activeFilePath].cropdim =
{
                                x: this.x,
                                y: this.y,
                                w: w,
                                h: h
                            };
                        }
                        this.setDims(x, y, w, h);
                    },

                    onMousedown: function (x, y) {
                        parent.CANVAS.setDrag(this);
                        this.offset = [x - this.dims[0], y - this.dims[1]];
                        this.dragging = true;
                        parent.overlay.withinCrop = true;
                    },

                    onMousemove: function (x, y) {
                        document.body.style.cursor = "move";
                        if (this.dragging) {
                            var w = this.w;
                            var h = this.h;
                            this.x = x - this.offset[0] + w * 0.5;
                            this.y = y - this.offset[1] + h * 0.5;
                        }
                    },

                    onMouseup: function () {
                        parent.CANVAS.clearDrag();
                        this.dragging = false;
                        parent.overlay.withinCrop = false;
                    },

                    onMouseover: function () {
                        this.hover = true;
                        parent.overCrop = true;

                    },

                    onMouseout: function () {
                        if (!parent.overImg) {
                            document.body.style.cursor =
'default';
                        }
                        parent.overCrop = false;
                        this.hover = false;
                    }
                }
            });
        },

        makeThread: function () {
            var self = this;
            this.CANVAS.addThread(new Thread({
                id    : 'myThread',
                onExec: function () {
                    if (self.CANVAS !== undefined) {
                        if (self.CANVAS.ctxEl !== undefined) {
                            self.CANVAS.clear().draw();
                        }
                    }
                }
            }));
        },

        /**
         * watch the close button
         */
        watchClose: function () {
            var self = this;
           
this.window.find('input[name=close-crop]').on('click',
function (e) {
                self.storeActiveImageData();
                self.win.close();
            });
        },

        /**
         * Takes the current active image and creates cropped image data
via a canvas element
         *
         * @param {string} filepath File path to image to crop. If blank
use this.activeFilePath
         */
        storeActiveImageData: function (filepath) {
            filepath = filepath ? filepath : this.activeFilePath;
            if (filepath === undefined) {
                return;
            }
            var x = this.cropperCanvas.x;
            var y = this.cropperCanvas.y;
            var w = this.cropperCanvas.w - 2;
            var h = this.cropperCanvas.h - 2;
            x = x - (w / 2);
            y = y - (h / 2);

            var win = jQuery('#' + this.windowopts.id);
            if (win.length === 0) {
                fconsole('storeActiveImageData no window found for
' + this.windowopts.id);
                return;
            }
            var canvas = win.find('canvas');

            var target =
jQuery(document.createElement('canvas')).attr({
                'width' : w + 'px',
                'height': h + 'px'
            }).appendTo(document.body);
            var ctx = target[0].getContext('2d');

            var file = filepath.split('\\').pop();
            var f = jQuery('input[name*="' + file +
'"]').filter(function (index, fld) {
                return fld.name.contains('cropdata');
            });

            ctx.drawImage(canvas[0], x, y, w, h, 0, 0, w, h);
            f.val(target[0].toDataURL('image/jpeg',
this.windowopts.quality));
            target.remove();
        },

        /**
         * Set up and watch the zoom slide and input field
         */
        watchZoom: function () {
            var self = this;

            if (!this.windowopts.crop) {
                return;
            }
            var scaleField =
this.window.find('input[name=zoom-val]');
            this.scaleSlide = new
Slider(this.window.find('.fabrikslider-line')[0],
this.window.find('.knob')[0], {
                range   : [20, 300],
                onChange: function (pos) {
                    self.imgCanvas.scale = pos / 100;
                    if (self.img !== undefined) {
                        try {
                            self.images[self.activeFilePath].scale = pos;
                        } catch (err) {
                            fconsole('didnt get active file
path:' + self.activeFilePath);
                        }
                    }
                    scaleField.val(pos);
                }
            }).set(100);

            scaleField.on('change', function (e) {
                self.scaleSlide.set(jQuery(this).val());
            });
        },

        /**
         * Set up and watch the rotate slide and input field
         */
        watchRotate: function () {
            if (!this.windowopts.crop) {
                return;
            }
            var self = this,
                r = this.window.find('.rotate'),
                rotateField =
this.window.find('input[name=rotate-val]');
            this.rotateSlide = new
Slider(r.find('.fabrikslider-line')[0],
r.find('.knob')[0], {
                onChange: function (pos) {
                    self.imgCanvas.rotation = pos;
                    if (self.img !== undefined) {
                        try {
                            self.images[self.activeFilePath].rotation =
pos;
                        } catch (err) {
                            fconsole('rorate err' +
self.activeFilePath);
                        }
                    }
                    rotateField.val(pos);
                },
                steps   : 360
            }).set(0);
            rotateField.on('change', function () {
                self.rotateSlide.set(jQuery(this).val());
            });
        },

        /**
         * Show the window - creating it if its not found
         */
        showWin: function () {
            this.win = Fabrik.getWindow(this.windowopts);
            this.window = jQuery('#' + this.modalId);
            if (this.CANVAS === undefined) {
                return;
            }
            if (this.CANVAS.ctxEl !== undefined) {
                this.CANVAS.ctxPos =
document.id(this.CANVAS.ctxEl).getPosition();
            }

            if (this.CANVAS.threads !== undefined) {
                if (this.CANVAS.threads.get('myThread') !==
undefined) {

                    // Fixes issue where sometime canvas thread is not
started/running so nothing is drawn
                    this.CANVAS.threads.get('myThread').start();
                }
            }
            this.win.drawWindow();
            this.win.center();
        }
    });

    return  window.FbFileUpload;
});