frCommenter.js 10.4 KB
import '../vendor/jquery.cookie';
import './comments';
import '../common/directives/imageUploader';
import '../vendor/tiny-pubsub';
import showErrors from '../common/showErrors';

/**
 * FootyRoom Commenter
 */
(function ($) {
    let el;
    let statusText = null;
    let actionMenu;
    let settings;
    let currentMode = 'normal';
    let commenterHash = Math.random().toString(36).substr(2, 5);
    let elCommentInput;
    let elCommentParent;
    let elAddImage;
    let elErrors;
    let elImages;
    let elImagesList;

    let defaults = {
        submit: 'default',
        charsLimit: 800,
        elErrors: '.commenter-errors',
    };

    let images = [];

    $.fn.commenter = function (options) {
        el = this;
        settings = $.extend({}, defaults, options);

        elCommentInput = $('.comment-input', el);
        elCommentParent = $('input[name="parent"]', el);
        elErrors = $(settings.elErrors);
        elImages = $('.images');
        elImagesList = $('.images-list');
        elAddImage = $('.insert-image, .add-image', el);
        elCommentInput.val(window.localStorage.getItem('commentContent'));

        // Change default from submit action.
        // $('.commenter-form', el).submit(onSubmit);

        // Cache some objects.
        actionMenu = $('.right-menu', this);

        // Bind editor menu buttons clicks.
        elAddImage.click(addImageWizard);
        $('.insert-video', this).click(insertVideoWizard);

        // Bind editor menu buttons hover.s
        elAddImage.hover(function () {
            $('.status', el).html('Add Image');
        }, function () {
            $('.status', el).html(statusText);
        });

        $('.insert-video', this).hover(function () {
            $('.status', el).html('Insert Video');
        }, function () {
            $('.status', el).html(statusText);
        });

        el.on('click', '.remove-image', removeImage);

        elCommentInput.on('propertychange input keyup', function () {
            charsLeftUpdate();
            window.localStorage.setItem('commentContent', elCommentInput.val());
        });

        // Insert a "bookmark" for the original location of the commenter.
        $('<div id="commenter-' + commenterHash + '"></div>').insertBefore(el);

        // Subscribe to reply event coming from comments.
        $.subscribe('fr.comments.reply', replyMode);

        // Subscribe to edit event coming from comments.
        $.subscribe('fr.comments.edit', editMode);

        // Build the action buttons.
        buildActionMenu();
    };

    /**
     * Event fired when we enter reply mode.
     * @param  {} _
     * @param  {integer} commentId
     */
    function replyMode(commentId) {
        currentMode = 'reply';
        buildActionMenu();

        $(el).insertAfter($('#comment' + commentId));
        $(el).addClass('reply');
        $('input[name="parent"]', el).val(commentId);
        elCommentInput.focus();
    }

    /**
		 * Event fired when we enter edit mode.
		 * @param  {} _
		 * @param  {integer} commentId
		 */
    function editMode(commentId, discussionId) {
        var commentElement = $('#comment' + commentId + ' .comment-text').first();

        resetCommenter('edit');

        $(el).insertAfter($('#comment' + commentId));
        $(el).addClass('reply');
        $('input[name="comment_id"]', el).val(commentId);
        elCommentInput.focus();

        commentElement.find('img').each(function () {
            addImage($(this).attr('src'));
        });

        elCommentInput.val(
            commentElement.html()
            .replace(/<br ?\/?>/gi, '')
            .replace(/<img.*?\/?>/gi, '')
        );
    }

    function getRange() {
        if (window.getSelection) { // all browsers, except IE before version 9
            var selectionRange = window.getSelection();
            return selectionRange.getRangeAt(0);
        } else if (document.selection.type == 'None') {
            return '';
        }

        return document.selection.createRange();
    }

    /**
		 * Builds action menu items.
		 */
    function buildActionMenu() {
        $(actionMenu)
        .html('')
        .append(function () {
            return $('<li class="submit">SAY IT</li>').one('click', function () {
                submit();
            });
        });

        if (['reply', 'edit'].indexOf(currentMode) > -1) {
            $(actionMenu)
            .append(function () {
                return $('<li class="cancel">CANCEL</li>').click(function () {
                    resetCommenter();
                });
            });
        }
    }

    function submit() {
        // User friendly loading.
        $('.box', el).litelay();
        $('.guest-fields input', el).prop('disabled', true);

        // Don't let post very long posts.
        if (elCommentInput.val().length > settings.charsLimit) {
            showErrors(['Your post is too long. Maximum of ' + settings.charsLimit + ' characters is allowed.'], settings.elErrors);
            $('.box', el).litelay();
            $('.guest-fields input', el).prop('disabled', false);
            buildActionMenu();
            return false;
        }

        // Assign the right submit handler.
        if (currentMode == 'edit') {
            submitEdit();
        } else if (settings.submit == 'default') {
            onSubmit();
        } else {
            eval(settings.submit)(function () {
                // Remove user friendly loading.
                $('.box', el).litelay();
                $('.guest-fields input', el).prop('disabled', false);
                buildActionMenu();
            });
        }
    }

    function modal() {
        return angular.injector(['ng', 'footyroom']).get('$uibModal');
    }

    function addImageWizard() {
        modal().open({
            template: '<image-uploader></image-uploader>',
        })

        .result.then(function (imgUrl) {
            addImage(imgUrl);
        });
    }

    function insertVideoWizard() {
        modal().open({
            templateUrl: '/views/ng/modal/insert-video.html',
        })

        .result.then(function (videoUrl) {
            insertVideo(videoUrl);
        });
    }

    function addImage(url) {
        url = url || $('.image-link-input', el).val();

        images.push(url);

        elImagesList.append(
            '<div class="image" style="background-image: url(' + url + ');">' +
						'<span class="remove-image icn-close pointer"></span>' +
					'</div>'
        );

        elImages.show();

        // Limit to only two images.
        if (images.length >= 2) {
            elAddImage.hide();
        }
    }

    function removeImage() {
        var imageEl = $(this).closest('.image');

        images.splice(elImagesList.find('.image').index(imageEl), 1);

        imageEl.remove();

        if (images.length === 0) {
            elImages.hide();
        }

        // Limit to only two images.
        if (images.length < 2) {
            elAddImage.show();
        }
    }

    /**
		 * Event fired when comment form is submitted.
		 */
    function onSubmit() {
        var comment = elCommentInput.val();
        var commentableId = $('input[name="post_id"]', el).val();
        var parentId = $('input[name="parent"]', el).val();
        var authorName = $('input[name="author"]', el).val();
        var email = $('input[name="email"]', el).val();
        var teamname = $('input[name="teamname"]', el).val();

        var data = {
            comment: comment,
            commentableId: commentableId,
            parent: parentId,
            authorName: authorName,
            email: email,
            teamname: teamname,
            images: images,
        };

        if (authorName) {
            $.cookie('author', authorName, {expires: 3650, path: '/'});
            $.cookie('email', email, {expires: 3650, path: '/'});
            $.cookie('teamname', teamname, {expires: 3650, path: '/'});
        }

        $.ajax({
            url: settings.action,
            type: 'POST',
            data: data,
            dataType: 'json',
        })

        .done(function (response) {
            resetCommenter();

            $.publish('fr.commenter.posted', [response.view, response.commentId, parentId]);

            window.localStorage.removeItem('commentContent');

            if (response.url) {
                window.location = response.url;
            }
        })

        .fail(function (jqXHR) {
            if (jqXHR.responseJSON.errors) {
                showErrors(jqXHR.responseJSON.errors, settings.elErrors);
            }
        })

        .always(function () {
            $('.box', el).litelay();
            $('.guest-fields input', el).prop('disabled', false);

            buildActionMenu();
        });

        return false;
    }

    function submitEdit() {
        var comment = elCommentInput.val();
        var commentId = $('input[name="comment_id"]', el).val();

        var data = {
            comment: comment,
            images: images,
            method: 'PUT',
        };

        $.ajax({
            url: settings.action + '/' + commentId,
            type: 'PUT',
            data: data,
            dataType: 'json',
        })

        .done(function (response) {
            resetCommenter();

            $.publish('fr.commenter.edited', [commentId, response.view]);
        })

        .fail(function (jqXHR) {
            if (jqXHR.responseJSON.errors) {
                showErrors(jqXHR.responseJSON.errors, settings.elErrors);
            }
        })

        .always(function () {
            $('.box', el).litelay();
            buildActionMenu();
        });
    }

    function resetCommenter(mode) {
        currentMode = mode || 'normal';

        elCommentInput.val('');
        elCommentParent.val(0);
        elErrors.html('').hide();
        elImagesList.find('.image').remove();
        elAddImage.show();
        elImages.hide();
        images = [];

        if (currentMode === 'normal') {
            $(el).removeClass('reply');

            elCommentParent.val(0);

            $('#commenter-' + commenterHash).after(el);
        }

        buildActionMenu();
    }

    function charsLeftUpdate() {
        var charsLeft = settings.charsLimit - elCommentInput.val().length;

        if (charsLeft < 0) {
            charsLeft = 0;
        }

        $('.comment-remaining-count', el).text(charsLeft + ' characters remaining');

        if (charsLeft < 100) {
            $('.comment-remaining-count', el).show();
        } else {
            $('.comment-remaining-count', el).hide();
        }
    }
}(jQuery));