izimiky / TLOrderFoodExtension

// ==UserScript==
// @name         TLOrderFoodExtension
// @namespace    travelline.orderfood
// @version      0.3
// @description  Позволяет ставить лайки/дизлайки, загружать и отображать картинки еды. Отображает еду с лайками первыми, а с дизлайками последними.
// @author       ivanov.mikhail
// @license      MIT
// @include      *://food.travelline.lan*
// @grant        none
// ==/UserScript==

var NOT_SELECT_USER_ID = 348,
    MAX_FILE_SIZE_BYTE = 240000,
    EXTENSION_HOST = 'http://orderfoodextension.tlwork.ru.mastertest.ru',
    SELECT_USER_ALERT = 'Для выполнения действия выберите пользователя.',
    SELECTED_CSS_CLASS = 'selected',
    isUserInited = false;

(function() {
    'use strict';

    var userId = getUserId();
    if (typeof(userId) !== "undefined") {
        isUserInited = true;
    }

    initCss();
    initPhotos();
    initLikePanelsAndActions();
    initLikeResult();
    initImgModal();
})();

function initCss() {
    var css = '<style>' +
        '.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}' +
        '.table-dish td { padding: 10px 10px !important }' +

        '.like-dislike-panel { margin: 0 0 5px; font-size: 14px }' +
        '.like-dislike-panel .glyphicon { opacity: 0.3; margin: 0 10px 0 0 }' +
        '.like-dislike-panel .glyphicon:hover { opacity: 1 }' +
        '.like-dislike-panel .glyphicon.selected { opacity: 1 }' +
        '.like-dislike-panel .glyphicon:before { font-size: 20px; position: relative; top: 4px; margin: 0 4px 0 0 }' +
        '.like-dislike-panel .glyphicon-camera, .like-dislike-panel .glyphicon-zoom-in { color: #7da3c9 }' +
        '.like-dislike-panel .glyphicon-thumbs-up.selected { color: #0dba2d }' +
        '.like-dislike-panel .glyphicon-thumbs-up:hover { opacity: 1; color: #0dba2d }' +
        '.like-dislike-panel .glyphicon-thumbs-down.selected { color: #ba0d0d }' +
        '.like-dislike-panel .glyphicon-thumbs-down:hover { opacity: 1; color: #ba0d0d }' +
        'input[type="file"] { width: 1px; height: 0; opacity: 0 }' +
        '.dish-element img { width: 100%; margin: 0 0 5px }' +
        '.like-dislike-panel .pbtn { float: left; margin-bottom: 5px }' +
        '.like-dislike-panel .pbtn:hover { cursor: pointer }' +
        '/* Style the Image Used to Trigger the Modal */ #myImg { border-radius: 5px; cursor: pointer; transition: 0.3s; } #myImg:hover {opacity: 0.7;} /* The Modal (background) */ .modal { display: none; /* Hidden by default */ position: fixed; /* Stay in place */ z-index: 1; /* Sit on top */ padding-top: 100px; /* Location of the box */ left: 0; top: 0; width: 100%; /* Full width */ height: 100%; /* Full height */ overflow: auto; /* Enable scroll if needed */ background-color: rgb(0,0,0); /* Fallback color */ background-color: rgba(0,0,0,0.9); /* Black w/ opacity */ } /* Modal Content (Image) */ .modal-content { margin: auto; display: block; max-width: 1200px; } /* Add Animation - Zoom in the Modal */ .modal-content { -webkit-animation-name: zoom; -webkit-animation-duration: 0.6s; animation-name: zoom; animation-duration: 0.6s; } @-webkit-keyframes zoom { from {-webkit-transform:scale(0)} to {-webkit-transform:scale(1)} } @keyframes zoom { from {transform:scale(0)} to {transform:scale(1)} } /* 100% Image Width on Smaller Screens */ @media only screen and (max-width: 700px){ .modal-content { width: 100%; } }' +
        '</style>';
    $(css).appendTo('body');
}

function initImgModal() {
    var $modal = $('<div id="imgModal" class="modal">').click(function() {
        $(this).hide();
    });
    $modal.append($('<img class="modal-content">'));
    $modal.appendTo('body');

    $(document).keyup(function(e) {
        if (e.keyCode == 27) { // escape key maps to keycode `27`
            $modal.hide();
        }
    });
}

function initLikePanelsAndActions() {
    if (window.location.protocol === 'https:')
        return;

    $dishPanels = $('div[id^="dish"]');
    $.each($dishPanels, function() {
        var dishId = $(this).data("id"),
            $panel = $('<p class="like-dislike-panel clearfix">');
        $panel.append($('<span class="glyphicon glyphicon-thumbs-up pbtn">'));
        $panel.append($('<span class="glyphicon glyphicon-thumbs-down pbtn">'));
        $panel.append($('<span class="glyphicon glyphicon-camera pbtn">'));
        $(this).append($panel);

        $('<input type="FILE" id="file' + dishId + '" data-id="' + dishId + '" accept=".jpg">').appendTo('body');
    });

    $('div[id^="dish"] .like-dislike-panel').click(function(e) {
        e.stopPropagation();
    });
    $('div[id^="dish"] .glyphicon-thumbs-up').click(thumbsUpClick);
    $('div[id^="dish"] .glyphicon-thumbs-down').click(thumbsDownClick);
    $('div[id^="dish"] .glyphicon-camera').click(simulateInputDishFileClick);
    $('input[id^="file"]').change(addPhoto);
}

function simulateInputDishFileClick() {
    if (window.location.protocol === 'https:')
        return;

    var dishId = $(this).parent().parent().data("id");
    $('input[id="file' + dishId + '"]').click();
}

// Добавляем изображения для блюд, если оно существует
function initPhotos() {
    var $dishPanels = $('div[id^="dish"]');
    $.each($dishPanels, function() {
        var dishId = $(this).data("id"),
            imgUrl = EXTENSION_HOST + '/uploads/dish' + dishId + '.jpg', // название изображения соответствует id блюда
            $this = $(this),
            img = new Image();
        img.onload = function() {
            $this.prepend($('<img src="' + imgUrl + '">'));
            $('<span class="glyphicon glyphicon-zoom-in pbtn">')
                .insertAfter($this.find('.like-dislike-panel .glyphicon-camera'))
                .click(zoomClick);
        };
        img.src = imgUrl;
    });
}

function showLikeResult(result) {
    if (window.location.protocol === 'https:')
        return;

    $.each(result, function(index, value) {
        var $thumbsUp = $('#dish' + index + ' .like-dislike-panel .glyphicon-thumbs-up'),
            $thumbsDown = $('#dish' + index + ' .like-dislike-panel .glyphicon-thumbs-down');
        $thumbsUp.text(value.like);
        $thumbsDown.text(value.dislike);

        $thumbsUp.removeClass(SELECTED_CSS_CLASS);
        $thumbsDown.removeClass(SELECTED_CSS_CLASS);
        if (value.my_choice == 1) {
            $thumbsUp.addClass(SELECTED_CSS_CLASS);
        } else if (value.my_choice == -1) {
            $thumbsDown.addClass(SELECTED_CSS_CLASS);
        }
    });
}

function thumbsUpClick() {
    var userId = getUserId();
    if (!isUserInited || userId == NOT_SELECT_USER_ID) {
        alert(SELECT_USER_ALERT);
        return;
    }

    var dishId = $(this).parent().parent().data("id");
    if ($(this).hasClass(SELECTED_CSS_CLASS)) {
        $(this).removeClass(SELECTED_CSS_CLASS);
        saveLikePointResult(dishId, 0, userId);
    } else {
        $(this).addClass(SELECTED_CSS_CLASS);
        $(this).next().removeClass(SELECTED_CSS_CLASS);
        saveLikePointResult(dishId, 1, userId);
    }
}

function thumbsDownClick() {
    var userId = getUserId();
    if (!isUserInited || userId == NOT_SELECT_USER_ID) {
        alert(SELECT_USER_ALERT);
        return;
    }

    var dishId = $(this).parent().parent().data("id");
    if ($(this).hasClass(SELECTED_CSS_CLASS)) {
        $(this).removeClass(SELECTED_CSS_CLASS);
        saveLikePointResult(dishId, 0, userId);
    } else {
        $(this).addClass(SELECTED_CSS_CLASS);
        $(this).prev().removeClass(SELECTED_CSS_CLASS);
        saveLikePointResult(dishId, -1, userId);
    }
}

function addPhoto(e) {
    var dishId = $(this).data("id"),
        fileName = e.target.files[0].name;

    if (MAX_FILE_SIZE_BYTE < e.target.files[0].size) {
        alert('Превышен лимит в 240 Кбайт для изображения.');
        return;
    }

    var formData = new FormData();
    formData.append('file', e.target.files[0]);

    $.ajax({
        url : EXTENSION_HOST + '/upload.php?dish-id=' + dishId,
        type : 'POST',
        data : formData,
        processData: false,  // tell jQuery not to process the data
        contentType: false,  // tell jQuery not to set contentType
        success: function(data) {
            alert('Изображение успешно загружено! Будет отображено после перезагрузки страницы.');
        },
        error: function (request, status, error) {
            console.error(request.responseText);
        }
    });
}

function zoomClick() {
    var dishId = $(this).parent().parent().data("id"),
        src = EXTENSION_HOST + '/uploads/dish' + dishId + '.jpg';

    $('#imgModal img').attr('src', src);
    $('#imgModal').show();
}

function saveLikePointResult(dishId, likePoint, userId) {
    $.ajax({
        url: EXTENSION_HOST + '/api.php?action=set-like-point&user-id=' + userId + '&dish-id=' + dishId + '&like-point=' + likePoint,
        success: function () {
            console.log('action=set-like-point&user-id=' + userId + '&dish-id=' + dishId + '&like-point=' + likePoint);
            initLikeResult();
        },
        error: function (request, status, error) {
            console.error(request.responseText);
        }
    });
}

function initLikeResult() {
    if (window.location.protocol === 'https:')
        return;

    var dishIds = getDishIds(),
        userId = getUserId();
    $.ajax({
        url: EXTENSION_HOST + '/api.php?action=get-dish-info&dish-ids=' + dishIds.join() + '&user-id=' + userId,
        success: function (jsonString) {
            var resultObj = JSON.parse(jsonString);
            showLikeResult(resultObj);
            sortingDishByLikeResult(resultObj);
        },
        error: function (request, status, error) {
            console.error(request.responseText);
        }
    });
}

function sortingDishByLikeResult(result) {
    var $salats = $('.table.table-dish.menu-bg tr td:nth-child(1) .dish-element'),
        $soups = $('.table.table-dish.menu-bg tr td:nth-child(2) .dish-element'),
        $seconds = $('.table.table-dish.menu-bg tr td:nth-child(3) .dish-element'),
        $garnishes = $('.table.table-dish.menu-bg tr td:nth-child(4) .dish-element');

    sortingDishGroup(result, $salats);
    sortingDishGroup(result, $soups);
    sortingDishGroup(result, $seconds);
    sortingDishGroup(result, $garnishes);
}

function sortingDishGroup(result, $dishGroup) {
    $.each($dishGroup, function() {
        var $this = $(this),
            dishId = $this.data("id");
        if (result[dishId] !== undefined) {
            if (result[dishId].my_choice == 1) {
                $dishGroup.parent().prepend($this);
            } else if (result[dishId].my_choice == -1) {
                $dishGroup.parent().append($this);
            }
        }
    });
}

function getDishIds() {
    dishIds = [];
    $dishPanels = $('div[id^="dish"]');
    $.each($dishPanels, function() {
        dishIds.push($(this).data("id"));
    });
    return dishIds;
}

function getUserId() {
    // возвращает cookie с именем name, если есть, если нет, то undefined
    var getCookie = function(name) {
        var matches = document.cookie.match(new RegExp(
            "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
        ));
        return matches ? decodeURIComponent(matches[1]) : undefined;
    };
    return getCookie('id_user');
}