Raw Source
galago / DartIT tracker-tweaker revo

'use strict';

// ==UserScript==
// @name DartIT tracker-tweaker revo
// @updateURL https://openuserjs.org/meta/galago/DartIT_tracker-tweaker_revo.meta.js
// @downloadURL https://dl.dropboxusercontent.com/u/11456758/DartUserScript/dart-support.user.js
// @description индивидуальные настройки для support.dartit.ru, support.alamics.ru;
// @include https://support.dartit.ru/*
// @include https://support.alamics.ru/*
// @grant unsafeWindow
// @author mann
// @license MIT
// @version 0.0.5.2

// ==/UserScript==
console.info('start userscript');
// [1] Оборачиваем скрипт в замыкание, для кроссбраузерности (opera, ie)
(function (window, undefined) {  // [2] нормализуем window
    var w;
    if (typeof unsafeWindow != undefined) {
        w = unsafeWindow
    } else {
        w = window;
    }
    //------------------------------------------

    //--------------------------------------------
    // [3] не запускаем скрипт во фреймах
    // без этого условия скрипт будет запускаться несколько раз на странице с фреймами
    if (w.self != w.top) {
        return;
    }


    // [4] дополнительная проверка наряду с @include
    var location_test = function () {
        if (/https:\/\/support.dartit.ru/.test(w.location.href) || /https:\/\/support.alamics.ru/.test(w.location.href)) {
            return true;
        }
        return false;
    };

    if (location_test) document.addEventListener("DOMContentLoaded", function () {

        var redirectLostTask = function () {
            var td = document.querySelectorAll('td.content');
            var content = td[1].innerHTML;

            if (content.indexOf('Задачи с номером №') > 0 && content.indexOf('не существует') > 0) {
                var link = document.createElement('A');
                link.href = 'https://support.alamics.ru/' + window.location.search;
                link.textContent = 'Возможно задача перенесена в трекер Алмикс. Перейти?';
                td[1].appendChild(link);
            }
        };

        redirectLostTask();

        //добавим новые стили
        var custom_css = ".onoff-opt{margin: 0 6px 0 10px}";
        custom_css += ".none{display: none !important}";
        custom_css += ".none.view{display: block !important}";
        custom_css += ".ch_addr{margin: 10px 10px 10px 0; vertical-align: top}";
        custom_css += ".totop > input {margin: 10px 0 0}";
        custom_css += ".label_head{display: block; margin: 0 0 20px}";
        custom_css += ".clearfix:before, .clearfix:after { content:''; display:table; clear: both }";
        custom_css += ".alist{float: right} .alist p{margin: 0 0 10px; line-height: 1; text-align: right}";
        custom_css += ".bar-wrap{padding:8px 15px;background:#2d2d2d}";
        custom_css += "#custom-project-list > li{width: 20%; float: left; cursor: pointer}";
        custom_css += "#custom-workers-list > li{width: 20%; float: left; cursor: pointer}";
        custom_css += "#custom-project-list > li:first-child{display:none}";
        custom_css += ".user-list > li{line-height: 1.5}";
        custom_css += ".selected{color: green}";
        custom_css += "#settings-btn{margin: 0 0 20px 0}";
        custom_css += "#settings-box{display: none; margin: 20px 0; padding: 20px 0; outline: 1px solid #414141}";
        custom_css += "#settings-box.is-open{display: block}";
        custom_css += ".user-title{color:#000;margin:0 0 .6em;font-size:20px;padding:0}";
        custom_css += ".regular-link{color:#0054b9}";
        custom_css += ".time-list p{margin: 5px 0; display:flex; justify-content:space-between;}";
        custom_css += ".time-list > p > span:first-child{padding-right: 1em; cursor: pointer;}";
        custom_css += ":root .time-list-total{margin-top: 1em; border-top: 1px solid;}";
        custom_css += ".comment-collapsed{max-height: 70px; overflow: hidden;}";
        custom_css += ".long-comment{width: 100% !important;position: relative; padding-top: 30px;}";
        custom_css += ".btn-collapse{position: absolute; top: 0; right: 0;}";
        custom_css += ".btn-collapse-all{position: fixed; top: 10; right: 10;}";
        custom_css += ":root .dates-list{width: 150px; display: inline-block; margin: 0 20px 0 0}";
        custom_css += ".user-toolbar{margin: 20px 0; padding: 20px 10px; border-top: 1px solid rgba(0,0,0,.7); overflow: hidden; display: flex; flex-wrap: wrap;}";
        custom_css += ".user-toolbar__item{padding: 10px 15px; background: rgba(255,255,255,.6); box-shadow: 0 1px 1px rgba(0,0,0,.6)}";
        custom_css += ":root .user-toolbar-title{margin: 0 0 1em; padding: 0; color: #000;}";

        addcss(custom_css);

        var action_page = getURLAction();

        //объект элементами которого будут функции
        //реализующие функционал модулей
        var modules = {};

        //сюда добаляются элементы страницы в которые вставляются созданые скриптом блоки
        //и.или они модифицируются скриптом
        var obj_page_elems = {};

        modules.createInterfaceObjects = function () {
            var $content_cell = document.querySelector('form[name="theForm"]');
            $content_cell.setAttribute('id', 'main-content');
            obj_page_elems.content_cell = $content_cell;

            var $comments_tbl = $content_cell.getElementsByTagName("TABLE")[0];
            $comments_tbl.setAttribute('id', 'comments-tbl');
            obj_page_elems.comments_tbl = $comments_tbl;

            obj_page_elems.comments_tbl_rows = $comments_tbl.querySelectorAll('tr');

            var input_div = document.querySelector('div.input_box'); //есть на странице задачи

            if (input_div) {
                var $user_toolbar = document.createElement('DIV');
                $user_toolbar.setAttribute('id', 'user-toolbar');
                $user_toolbar.classList.add('user-toolbar');

                input_div.appendChild($user_toolbar);
                obj_page_elems.user_toolbar = $user_toolbar;
            }

        };

        modules.userSettings = function () {
            var $content_cell = obj_page_elems.content_cell;

            //создание блока в котором будут все элементы управления настройками

            var $user_settings_box = document.createElement('div');
            $user_settings_box.setAttribute('id', 'settings-box');
            $content_cell.insertBefore($user_settings_box, $content_cell.firstChild);


            //создание кнопки показать/скрыть пользовательские настройки
            var $settings_btn = document.createElement('button');
            $settings_btn.innerHTML = 'Показать/скрыть пользовательские настройки';
            $settings_btn.setAttribute('id', 'settings-btn');
            $settings_btn.setAttribute('type', 'button');

            $content_cell.insertBefore($settings_btn, $content_cell.firstChild);

            $settings_btn.addEventListener('click', function () {
                $user_settings_box.classList.toggle('is-open');
            });

            //создание кастомного списка проектов
            //id`s array
            var params_user_projects = JSON.parse(localStorage.getItem('params_user_projects'));

            if (params_user_projects === null) {
                params_user_projects = [];
            }

            var createTaskListHTML = function () {
                var $custom_projects_list = document.createElement('ul');
                $custom_projects_list.setAttribute('id', 'custom-project-list');
                $custom_projects_list.setAttribute('class', 'user-list clearfix');

                obj_page_elems.dart_projects_list = document.getElementById('project_id');
                obj_page_elems.dart_projects_list_opts = obj_page_elems.dart_projects_list.options;

                var $custom_list_title = document.createElement('h2');
                $custom_list_title.innerHTML = 'Собственный список проектов';
                $custom_list_title.classList.add('user-title');
                $custom_projects_list.appendChild($custom_list_title);

                var $custiom_list_item;

                Object.keys(obj_page_elems.dart_projects_list_opts).forEach(function (key) {
                    if (obj_page_elems.dart_projects_list_opts[key].value < 0) {
                        return false;
                    }
                    $custiom_list_item = document.createElement('li');
                    $custiom_list_item.innerHTML = obj_page_elems.dart_projects_list_opts[key].text;
                    $custiom_list_item.setAttribute('data-project-id', obj_page_elems.dart_projects_list_opts[key].value);
                    $custom_projects_list.appendChild($custiom_list_item);
                    $custiom_list_item.addEventListener('click', createIdArrayCustomTaskList);
                });

                $user_settings_box.insertBefore($custom_projects_list, $user_settings_box.firstChild);
                obj_page_elems.custom_project_list = $custom_projects_list;

                if (params_user_projects.length) {
                    var node;
                    Object.keys($custom_projects_list.childNodes).forEach(function (key) {
                        node = $custom_projects_list.childNodes[key];
                        if (params_user_projects.indexOf(node.getAttribute('data-project-id')) >= 0) {
                            node.classList.add('selected');
                        }
                    });
                }
            };

            createTaskListHTML();

            function createIdArrayCustomTaskList() {
                //var params_user_projects = JSON.parse(localStorage.getItem('params_user_projects'));
                var id = this.getAttribute("data-project-id");
                var index;

                if (params_user_projects.indexOf(id) === -1) {
                    params_user_projects.push(id);
                    this.classList.add('selected');
                } else {
                    index = params_user_projects.indexOf(id);
                    params_user_projects.splice(index, 1);
                    this.classList.remove('selected');
                }

                localStorage.setItem('params_user_projects', JSON.stringify(params_user_projects));

                elemsModification.modifyProjectList();

                console.log(JSON.parse(localStorage.getItem('params_user_projects')));
            }

            //создание кастомного списка исполнителей
            //id`s array

            var params_user_workers = JSON.parse(localStorage.getItem('params_user_workers'));

            if (params_user_workers === null) {
                params_user_workers = [];
            }

            var createWorkersListHTML = function () {
                var $custom_workers_list = document.createElement('ul');
                $custom_workers_list.setAttribute('id', 'custom-workers-list');
                $custom_workers_list.setAttribute('class', 'user-list clearfix');

                obj_page_elems.dart_workers_list = document.getElementById('internal_worker');
                obj_page_elems.dart_workers_list_opts = obj_page_elems.dart_workers_list.options;

                var $custom_list_title = document.createElement('h2');
                $custom_list_title.innerHTML = 'Собственный список исполнителей';
                $custom_list_title.classList.add('user-title');
                $custom_workers_list.appendChild($custom_list_title);

                var $custiom_list_item;

                Object.keys(obj_page_elems.dart_workers_list_opts).forEach(function (key) {
                    if (obj_page_elems.dart_workers_list_opts[key].value <= 0) {
                        return false;
                    }
                    $custiom_list_item = document.createElement('li');
                    $custiom_list_item.innerHTML = obj_page_elems.dart_workers_list_opts[key].text;
                    $custiom_list_item.setAttribute('data-worker-id', obj_page_elems.dart_workers_list_opts[key].value);
                    $custom_workers_list.appendChild($custiom_list_item);
                    $custiom_list_item.addEventListener('click', createIdArrayCustomWorkersList);
                });

                $user_settings_box.insertBefore($custom_workers_list, $user_settings_box.firstChild);
                obj_page_elems.custom_workers_list = $custom_workers_list;

                if (params_user_workers.length) {
                    var node;
                    Object.keys($custom_workers_list.childNodes).forEach(function (key) {
                        node = $custom_workers_list.childNodes[key];
                        if (params_user_workers.indexOf(node.getAttribute('data-worker-id')) >= 0) {
                            node.classList.add('selected');
                        }
                    });
                }
            };

            createWorkersListHTML();

            function createIdArrayCustomWorkersList() {
                var id = this.getAttribute("data-worker-id");
                var index;

                if (params_user_workers.indexOf(id) === -1) {
                    params_user_workers.push(id);
                    this.classList.add('selected');
                } else {
                    index = params_user_workers.indexOf(id);
                    params_user_workers.splice(index, 1);
                    this.classList.remove('selected');
                }

                localStorage.setItem('params_user_workers', JSON.stringify(params_user_workers));

                elemsModification.modifyWorkersList();

                console.log(JSON.parse(localStorage.getItem('params_user_workers')));
            }
        };

        //project list
        //сравниваем список проектов с сохраненным в настройках
        //проекты которых нет в настройка скрываем
        modules.elemsModification = function () {

            //сравниваем список проектов с сохраненным в настройках
            //проекты которых нет в настройка скрываем
            this.modifyProjectList = function () {
                var params_user_projects = JSON.parse(localStorage.getItem('params_user_projects'));

                if (params_user_projects === null) {
                    console.info('Нет собственного списка проектов');
                    return false;
                }

                var dart_projects_list = document.getElementById('project_id') || document.getElementById('client_id');
                var options = dart_projects_list.options;
                console.log(options);
                var list_tag = dart_projects_list.tagName.toLowerCase();

                switch (list_tag) {
                    case 'select':
                        modifySelectOptionsList(options, params_user_projects);
                        break;
                    case 'a':
                        var $list = dart_projects_list.nextSibling;
                        var $list_labels = $list.childNodes;
                        var $list_check;

                        Object.keys($list_labels).forEach(function (key) {
                            $list_labels[key].classList.remove('none');
                            $list_check = $list_labels[key].childNodes[0];

                            if (params_user_projects.indexOf($list_check.value) === -1) {
                                $list_labels[key].classList.add('none');
                            }
                        });

                        $list.style.height = 'auto';
                        break;
                }
            };

            //сравниваем список исполнителей с сохраненным в настройках
            //исполнителей которых нет в настройка скрываем
            this.modifyWorkersList = function () {

                var params_user_workers = JSON.parse(localStorage.getItem('params_user_workers'));

                if (params_user_workers === null) {
                    console.info('Нет собственного списка сотрудников');
                    params_user_workers = [];
                }

                var dart_workers_list = document.getElementById('internal_worker');
                //добавлю в объект с элементами DOM
                obj_page_elems.dart_workers_list = dart_workers_list;

                var options = dart_workers_list.options; //список всех сотрудников из селекта на странице

                var list_tag = dart_workers_list.tagName.toLowerCase();

                switch (list_tag) {
                    case 'select':
                        //если пользовательский список сотрудников не пуст
                        //и если в задаче участвует сотрудник которого нет в списке оставляю его открытым
                        if(params_user_workers.length){
                            //получаю список всех участников задачи
                            var task_workers = getAllWorkers();
                            var task_workers_id = [];

                            //сравнение списков, если работника нет в списке из настроек пользователя - добавляю
                            //сначала нужно получить соответсвие имя сотрудника -> option.value т.е. логин сотрудника на англицком
                            for(var i = 0; i < options.length; i++){
                                var if_find = findInArray(task_workers, options[i].text);

                                if(if_find > -1){
                                    task_workers_id.push(options[i].value)
                                }
                            }

                            //затем сравнить со списком из настроек
                            //и добавить работника если его нет в списке
                            for(i = 0; i < task_workers_id.length; i++){
                                if_find = findInArray(params_user_workers, task_workers_id[i]);

                                if(if_find < 0){
                                    params_user_workers.push(task_workers_id[i]);
                                    //console.info('В список добавлен '+ task_workers[i]);
                                }
                            }

                            modifySelectOptionsList(options, params_user_workers);
                        }
                        break;
                    case 'a':
                        var $list = dart_workers_list.nextSibling;
                        var $list_labels = $list.childNodes;
                        var $list_check;

                        Object.keys($list_labels).forEach(function (key) {
                            $list_labels[key].classList.remove('none');
                            $list_check = $list_labels[key].childNodes[0];

                            if (params_user_workers.indexOf($list_check.value) === -1) {
                                $list_labels[key].classList.add('none');
                            }
                        });

                        $list.style.height = 'auto';
                        break;
                }
            };

            //в списке исполнителей отмечаю selected работника оставившего последний комментрий в задаче
            this.setSelectedInWorkersList = function () {
               var last_row = getAllCommentsRows();
                last_row = last_row[last_row.length - 1];
                var last_worker = last_row.children[4].textContent;

                for(var i = 0; i < obj_page_elems.dart_workers_list.options.length; i++){
                    if(last_worker === obj_page_elems.dart_workers_list.options[i].text){
                        obj_page_elems.dart_workers_list.options[i].setAttribute('selected','');
                    }
                }

            };

            if (document.getElementById('internal_worker')) {
                this.modifyWorkersList();
                this.setSelectedInWorkersList();
            }

            if (document.getElementById('project_id') || document.getElementById('client_id')) {
                this.modifyProjectList();
            }

        };

        //поиск ссылок в тексте комментариев и оборачивание их в <a>
        //сворачивание длинных комментариев, добавление кнопки Свренуть.развернуть все
        modules.modyfiComments = function () {
            function replaceURLWithHTMLLinks(text) {
                var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
                return text.replace(exp, '<a href="$1" class="regular-link">$1</a>');
            }

            var td, div, txt;
            var rows = obj_page_elems.comments_tbl_rows;
            var rows_num = rows.length;
            var rows5end = rows_num - 5;
            var collapse_btn;

            obj_page_elems.collapse_btns = [];

            for (var i = 1; i < rows_num; i++) {
                td = rows[i].getElementsByTagName('TD')[5];
                div = td.getElementsByTagName('DIV')[0];
                txt = div.innerHTML;
                txt = replaceURLWithHTMLLinks(txt);
                div.innerHTML = '';
                div.innerHTML = txt;

                if (i < rows5end) {
                    if (div.offsetHeight > 200) {
                        div.classList.add('comment-collapsed');
                        div.classList.add('long-comment');
                        collapse_btn = document.createElement('BUTTON');
                        collapse_btn.setAttribute('type', 'button');
                        collapse_btn.innerHTML = 'Развернуть';
                        collapse_btn.classList.add('btn-collapse');
                        collapse_btn.classList.add('is-close');
                        div.appendChild(collapse_btn);
                        //collapse_btn.addEventListener('click',collapseComment);
                        collapse_btn.addEventListener('click', function () {
                            collapseComment(this)
                        });
                        obj_page_elems.collapse_btns.push(collapse_btn);
                    }
                }
            }

            if (!!document.querySelector('.comment-collapsed')) {
                collapse_btn = document.createElement('BUTTON');
                collapse_btn.setAttribute('type', 'button');
                collapse_btn.innerHTML = 'Развернуть все';
                collapse_btn.classList.add('btn-collapse-all');
                collapse_btn.classList.add('is-close');
                collapse_btn.addEventListener('click', collapseAllComment);
                obj_page_elems.content_cell.appendChild(collapse_btn);
            }

            function collapseComment(el, state) {
                //el - node || nodeList
                //state - string || check contains class is-close
                state = state || el.classList.contains('is-close');

                if (Array.isArray(el)) {
                    for (var i = 0; i < el.length; i++) {
                        if (state === 'expand') {
                            setExpand(el[i]);
                            continue;
                        }
                        setCollapse(el[i]);
                    }
                } else {
                    if (state) {
                        setExpand(el);
                    } else {
                        setCollapse(el);
                    }
                }

                function setExpand(el) {
                    el.classList.remove('is-close');
                    el.innerHTML = '';
                    el.innerHTML = 'Свернуть';
                    el.parentNode.classList.remove('comment-collapsed');
                }

                function setCollapse(el) {
                    el.classList.add('is-close');
                    el.innerHTML = '';
                    el.innerHTML = 'Развернуть';
                    el.parentNode.classList.add('comment-collapsed')
                }
            }

            function collapseAllComment() {
                if (this.classList.contains('is-close')) {
                    this.classList.remove('is-close');
                    this.innerHTML = '';
                    this.innerHTML = 'Свернуть все';

                    collapseComment(obj_page_elems.collapse_btns, 'expand');

                } else {
                    this.classList.add('is-close');
                    this.innerHTML = '';
                    this.innerHTML = 'Развернуть все';

                    collapseComment(obj_page_elems.collapse_btns, 'collapse');
                }
            }
        };

        //подсчет общего времени в задаче для каждого исполнителя
        modules.countWorkerTime = function () {
            var $input_box = obj_page_elems.user_toolbar;
            var rows = getAllCommentsRows();
            var workers = getAllWorkers();
            var dates_collection = [];
            var date_str;

            for (var i = 0; i < rows.length; i++) {
                date_str = rows[i].children[3].textContent;
                date_str = date_str.split(' ');
                dates_collection.push(createISODate(date_str[0]));
            }

            var dates_arr = eliminateDuplicates(dates_collection);

            var createDatesList = function (input_box, dates) {

                function createList(css_id, css_class) {
                    var list = document.createElement('SELECT');
                    list.setAttribute('id', css_id);
                    list.classList.add(css_class);
                    return list;
                }

                var box = document.createElement('DIV');
                box.classList.add('user-toolbar__item');

                var start_list = createList('date-start-list', 'dates-list');

                var end_list = createList('date-end-list', 'dates-list');

                var btn = document.createElement('BUTTON');
                btn.setAttribute('type', 'button');
                btn.textContent = 'Посчитать';

                var option, cln_option, listdate;

                for (var i = 0; i < dates.length; i++) {
                    listdate = dateFormatter(parseInt(dates[i], 10));
                    option = document.createElement('OPTION');
                    option.setAttribute('value', dates[i]);
                    option.innerHTML = listdate.toLocaleString('ru');
                    cln_option = option.cloneNode(true);
                    start_list.appendChild(option);
                    end_list.appendChild(cln_option);
                }
                box.appendChild(start_list);
                box.appendChild(end_list);
                box.appendChild(btn);

                var title = document.createElement('H3');
                title.textContent = 'За выбранный период';
                title.classList.add('user-toolbar-title');
                box.insertBefore(title, box.firstChild);

                input_box.insertBefore(box, input_box.lastChild);

                return {
                    'box': box,
                    'start_list': start_list,
                    'end_list': end_list,
                    'btn': btn
                }
            };

            var timelist = createTimeList(workers, rows);

            var $timelist = createTimeListView(timelist);

            $timelist.classList.add('user-toolbar__item');

            //добавляем строку с общим временм всех сотрудников
            //третий параметр true - ставит класс-маркер выбранных работников
            insertTotalTime($timelist,timelist,true);

            // добавляем клик по строке для подсчета времени выбранных работников
            $timelist.addEventListener('click', function (e) {
                countSelectedWorkersTime(this, e);
            });

            var $title = document.createElement('H3');
            $title.textContent = 'Вся задача';
            $title.classList.add('user-toolbar-title');
            $timelist.insertBefore($title, $timelist.firstChild);
            $timelist.classList.add('user-toolbar__item');

            var date_lists = createDatesList($input_box, dates_arr);

            // добавляю селекты с датами - подсчет времени за выбранный период
            findTimeInDatesRange(date_lists, workers, rows);

            $input_box.insertBefore($timelist, $input_box.lastChild);

            //http://stackoverflow.com/questions/2558977/ajax-cross-domain-call
        };

        //калькулятор в поле ввода затраченного времени
        modules.calculateElapsedTime = function () {
            var timeElapsedField = document.getElementById('spended_time');

            // Удаление обработчика нажатия клавиш для поля 'spended_time'
            timeElapsedField.onkeyup = null;

            // Добавление события для вычисления затраченного времени для поля 'spended_time'
            timeElapsedField.addEventListener('change', function () {
                var cur_value = this.value;

                try {
                    cur_value = eval(cur_value);
                } catch (e) {
                    alert("Ошибка вычисления затраченного времени. Используйте числа и знаки «+», «-», «*», «/» и скобки");

                    cur_value = null;
                } finally {
                    if ((cur_value !== null) && (!isNaN(cur_value))) {

                        cur_value = Math.round(cur_value);

                        if (cur_value <= 0) {
                            alert("Отрицательное или нулевое значение времени");
                            cur_value = null;
                        }
                    }
                    this.value = cur_value;
                    minToDays(cur_value);
                }
            });
        };

        //Сохранение комментария в localStorage
        //на случай внезапного звершения сессии
        modules.saveNewComment = function () {
            var $field = document.getElementById('text');

            var query = window.location.search.substring(1);
            var task_id = query.split("=")[2];

            //добавлю кнопку для вставки сохраненного текста
            var btn = document.createElement('BUTTON');
            btn.setAttribute('type', 'button');
            btn.classList.add('label_head');
            btn.innerHTML = 'Вставить сохраненный текст';
            btn.classList.add('none'); //по умолчанию скрыта
            $field.parentNode.insertBefore(btn, $field);

            //если есть сохраненный текст - показать кнопку
            showPasteBtn(btn, task_id);

            //вставить текст по клику
            btn.addEventListener('click', function (e) {
                $field.value = localStorage.getItem('task' + task_id);
                e.preventDefault();
            });

            //Сохранить текст из поля при наборе или потере фокуса
            $field.addEventListener('keyup', saveTaskComment);

            //если есть сохраненный текст - показать кнопку
            $field.addEventListener('blur', function () {
                showPasteBtn(btn, task_id);
            });

            function saveTaskComment() {
                localStorage.setItem('task' + task_id, this.value);
            }

            function showPasteBtn(button, id) {
                if (localStorage.getItem('task' + id) !== '' && localStorage.getItem('task' + id) !== null) {
                    button.classList.remove('none');
                }
            }
        };

        //start modules
        modules.createInterfaceObjects();

        switch (action_page) {
            case 'new':
                modules.userSettings();
                break;
            case 'red':
            case 'user_page':
                var elemsModification = new modules.elemsModification();
                modules.modyfiComments();
                modules.countWorkerTime();
                modules.saveNewComment();
                modules.calculateElapsedTime();
                break;
            default:

                break;
        }

        //----------
        //утилиты
        //----------
        //добавить стили в head
        function addcss(css) {
            var head = document.getElementsByTagName('head')[0];
            var s = document.createElement('style');
            s.setAttribute('type', 'text/css');
            s.setAttribute('data-name', 'user-script-css');
            s.appendChild(document.createTextNode(css));
            head.appendChild(s);
            console.info('add custom css complete');
        }

        //определение страницы по get параметру a, например ?a=user_page
        function getURLAction() {
            var query = window.location.search.substring(1);
            var get_action = query.split("=");
            get_action = get_action[1].split('&');
            return get_action[0];
        }

        //удаление дубликатов
        function eliminateDuplicates(arr) {
            var obj = {};

            for (var i = 0; i < arr.length; i++) {
                var str = arr[i];
                obj[str] = true; // запомнить строку в виде свойства объекта
            }

            return Object.keys(obj); // или собрать ключи перебором для IE8-
        }

        //создание даты из строки
        function createISODate(str) {
            var date_str = str.split('.');
            var day_str = date_str[0];
            var month_str = date_str[1];
            var year_str = date_str[2];
            var date_iso_str = year_str + '-' + month_str + '-' + day_str;
            date_iso_str = Date.parse(date_iso_str);
            return date_iso_str;
        }

        // получение строки с датой из таблицы с комментарими задачи
        function getRowDateString(row) {
            var t = row.children[3].textContent;
            t = t.split(' ');
            return createISODate(t[0]);
        }

        //форматирование даты
        function dateFormatter(date) {
            var formatter = new Intl.DateTimeFormat("ru");
            date = new Date(parseInt(date, 10));
            date = formatter.format(date);
            return date;
        }

        // получение строки с времнем из таблицы с комментарими задачи
        function getRowTimeString(row) {
            var t = row.children[10].textContent;
            t = t.split('/');
            return parseInt(t[0]);
        }

        // скрыть/показать опреденные option в select
        function modifySelectOptionsList(list, params) {
            Array.from(list).forEach(function (item) {
                item.removeAttribute('hidden');

                if (params.indexOf(item.value) === -1) {
                    item.setAttribute('hidden', '');
                }
            });
        }

        // пересчет минут в дни
        function minToDays(timeInMinutes, dayInHours) {
            var dayInHours = dayInHours || 8;
            var retStr = "";

            if ((timeInMinutes !== null) && (!isNaN(timeInMinutes)) && (timeInMinutes > 0)) {
                dayInHours = dayInHours << 0;
                if ((dayInHours === undefined) || (dayInHours === null) || (isNaN(dayInHours)) || (dayInHours < 1)) dayInHours = 24;
                var tD, tH, tM;
                tD = (timeInMinutes / dayInHours / 60) << 0;
                retStr += tD > 0 ? tD + " д. " : "";
                timeInMinutes -= tD * dayInHours * 60;
                tH = (timeInMinutes / 60) << 0;
                retStr += tH > 0 ? tH + " ч. " : "";
                timeInMinutes -= tH * 60;
                tM = timeInMinutes << 0;
                retStr += tM + " мин." + " (" + dayInHours + "-часовой день)";
            } else {
                retStr += "Что-то со временем не так :(";
            }
            return retStr;
        }

        // создание объекта со списком сотруднков и времени каждого в задаче
        function createTimeList(workers, rows) {
            var ntime, name, tsum;
            var timelist = {};

            for (var s = 0; s < workers.length; s++) {
                tsum = 0;

                for (var i = 0; i < rows.length; i++) {
                    ntime = getRowTimeString(rows[i]);

                    name = rows[i].children[4].textContent;

                    if (workers[s] === name) {
                        tsum += ntime;
                        timelist[name] = tsum;
                    }
                }
            }

            return timelist;
        }

        // создание html элемента со списком сотруднков и времени каждого в задаче
        function createTimeListView(data) {
            var $timelist = document.createElement('DIV');
            $timelist.classList.add('time-list');
            $timelist.id = 'workers-time';

            var list_item;
            var workertime;
            var totaltime = 0;

            for (var k in data) {
                workertime = data[k];
                totaltime += workertime;
                list_item = document.createElement('p');
                list_item.dataset.workertime = workertime;
                list_item.innerHTML = '<span>'+ k + '</span> <span>' + workertime + '</span>';
                $timelist.insertBefore(list_item, $timelist.lastChild);
            }

            return $timelist;
        }

        // подсчет общего времени всех сотрудников для списка сотрудник-время
        function insertTotalTime(timelist,data,addmarker) {
            var totaltime = 0;
            var total = document.createElement('p');

            for (var k in data) {
                totaltime += data[k];
            }

            if(addmarker){
                var list_items = timelist.querySelectorAll('p');
                //по умолчанию все работники выбраны, считается общее время по всем
                //всем добавляем класс selected нужный для фильтрации списка
                //и чтобы визуально отметить выбранных в списке
                for(var i = 0; i < list_items.length; i++){
                    list_items[i].classList.add('selected');
                }
            }

            total.innerHTML = '<span>Всего:</span> <span id="workers-time-total" data-totaltime="'+totaltime+'">' + totaltime + '</span>';
            total.classList.add('time-list-total');
            timelist.appendChild(total);

            return totaltime;
        }

        // получить список отмеченных сотрудников - из списка всех сотрудников задачи

        function getSelectedWorkers() {
            var selected_workers = document.getElementById('workers-time').querySelectorAll('.selected');
            var selected_names = [];

            for(var i = 0; i < selected_workers.length; i++){
                selected_names.push(selected_workers[i].firstElementChild.textContent);
            }

            return selected_names;
        }

        // получить все строки с каментами в задаче

        function getAllCommentsRows() {
            var rows = Array.from(obj_page_elems.comments_tbl_rows);
            rows = rows.splice(1, rows.length); //исключить первую строку с заголовками столбцов
            return rows;
        }

        // получить список всех сотрудников в задаче
        function getAllWorkers() {
            var rows = getAllCommentsRows();

            var workers = [];

            for (var i = 0; i < rows.length; i++) {
                workers.push(rows[i].children[4].textContent);
            }

            return eliminateDuplicates(workers);
        }

        function findInArray(arr, val) {
            return arr.indexOf(val);
        }

        //----------------------
        //доп. функции модулей
        //----------------------

        //подсчет времени выбранных участников задачи (из списка всех участников)

        function countSelectedWorkersTime(list, event) {
            var target = event.target;
            var $total = document.getElementById('workers-time-total');
            var total = parseInt($total.dataset.totaltime);

            while (target != list) {
                if (target.tagName == 'P') {
                    recountTotal(target,$total,total);
                    return;
                }

                target = target.parentNode;
            }

            function recountTotal(elem, total, totaltime) {
                var elemtime = parseInt(elem.dataset.workertime);

                //класс excluded нужен для фильтрации списка работников
                //в выводе времни за период - вывод только по выбранным (selected) работникам
                if(elem.classList.contains('selected')){
                    elem.classList.remove('selected');
                    elem.classList.add('excluded');
                    totaltime = totaltime - elemtime;
                }else{
                    elem.classList.add('selected');
                    elem.classList.remove('excluded');
                    totaltime = totaltime + elemtime;
                }

                total.innerHTML = totaltime;
                total.dataset.totaltime = totaltime;
            }
        }


        // подсчет времени за выбранный период

        function findTimeInDatesRange(lists, workers, rows) {
            var $start_list = lists.start_list;
            var $end_list = lists.end_list;
            var $box = lists.box;
            var $btn = lists.btn;

            function findRowsInRange(rows, start, end) {
                return rows.filter(function (item) {
                    var item_date = getRowDateString(item);

                    if (item_date >= start && item_date <= end) {
                        return item;
                    }
                });
            }

            // $start_list.addEventListener('change', function(){
            //     var val = this.value;
            //
            //     Array.from($end_list.options).forEach(function (item) {
            //         if(item.value <= val){
            //             item.setAttribute('disabled', true);
            //             item.setAttribute('hidden', true);
            //         }
            //     });
            //
            // });
            //
            // $end_list.addEventListener('change', function(){
            //     var find_rows = findRowsInRange(rows, $start_list.value, this.value);
            //     createTimeList(workers, find_rows);
            // });

            $btn.addEventListener('click', function () {
                var find_rows = findRowsInRange(rows, $start_list.value, $end_list.value);

                var range_timelist = createTimeList(getSelectedWorkers(), find_rows);
                var $range_timelist = createTimeListView(range_timelist);

                if ($box.querySelector('#range-timelist')) {
                    $box.removeChild(document.getElementById('range-timelist'));
                }

                $range_timelist.setAttribute('id', 'range-timelist');

                $box.appendChild($range_timelist);

                insertTotalTime($range_timelist,range_timelist);
            });
        }

    });
})(window);