<commit_before>/*
 * Copyright 2016 The CodeWorld Authors. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

goog.provide('Blockly.Blocks.cwEvent');

goog.require('Blockly.Blocks');

Blockly.cwEvent = function(){};
Blockly.cwEvent.generateEventBuiltins = function(xmlList){

  var LeftButton = new Blockly.UserTypes.Product("LeftButton",[]);
  var RightButton = new Blockly.UserTypes.Product("RightButton",[]);
  var MiddleButton = new Blockly.UserTypes.Product("MiddleButton",[]);
  var MouseButton = new Blockly.UserTypes.Sum("MouseButton", [LeftButton,RightButton,MiddleButton]);

  var point = new Blockly.TypeExpr("pair",[new Blockly.TypeExpr("Number"), new Blockly.TypeExpr("Number")]);
  var KeyPress = new Blockly.UserTypes.Product("KeyPress", [new Blockly.TypeExpr("Text") ]);
  var KeyRelease = new Blockly.UserTypes.Product("KeyRelease", [new Blockly.TypeExpr("Text") ]);
  var MousePress = new Blockly.UserTypes.Product("MousePress", [new Blockly.TypeExpr("MouseButton") ]);
  var MouseRelease = new Blockly.UserTypes.Product("MouseRelease", [ new Blockly.TypeExpr("MouseButton")]);
  var MouseMovement = new Blockly.UserTypes.Product("MouseMovement", [point]);
  var Event = new Blockly.UserTypes.Sum("Event",[KeyPress, KeyRelease, MousePress, MouseRelease, MouseMovement]);

  var bs = [MouseButton, Event];

  bs.forEach(function(sum){
    Blockly.UserTypes.generateConstructors_(sum, xmlList);
    Blockly.UserTypes.generateCase_(sum, xmlList);
  });

};

Blockly.cwEvent.eventFlyoutCategory = function(workspace){

  var xmlList = [];

  Blockly.cwEvent.generateEventBuiltins(xmlList);

  return xmlList;
};

<commit_msg>Initial work on having event blocks work with new type system<commit_after>/*
 * Copyright 2016 The CodeWorld Authors. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

goog.provide('Blockly.Blocks.cwEvent');

goog.require('Blockly.Blocks');

Blockly.cwEvent = function(){};
Blockly.cwEvent.generateEventBuiltins = function(xmlList){

  var LeftButton = new Blockly.UserTypes.Product("LeftButton",[]);
  var RightButton = new Blockly.UserTypes.Product("RightButton",[]);
  var MiddleButton = new Blockly.UserTypes.Product("MiddleButton",[]);
  var MouseButton = new Blockly.UserTypes.Sum("MouseButton", [LeftButton,RightButton,MiddleButton]);

  var point = Type.Lit("pair",[ Type.Lit("Number"), Type.Lit("Number")]);
  var KeyPress = new Blockly.UserTypes.Product("KeyPress", [Type.Lit("Text") ]);
  var KeyRelease = new Blockly.UserTypes.Product("KeyRelease", [Type.Lit("Text") ]);
  var MousePress = new Blockly.UserTypes.Product("MousePress", [Type.Lit("MouseButton") ]);
  var MouseRelease = new Blockly.UserTypes.Product("MouseRelease", [ Type.Lit("MouseButton")]);
  var MouseMovement = new Blockly.UserTypes.Product("MouseMovement", [point]);
  var Event = new Blockly.UserTypes.Sum("Event",[KeyPress, KeyRelease, MousePress, MouseRelease, MouseMovement]);

  var bs = [MouseButton, Event];

  bs.forEach(function(sum){
    Blockly.UserTypes.generateConstructors_(sum, xmlList);
    Blockly.UserTypes.generateCase_(sum, xmlList);
  });

};

Blockly.cwEvent.eventFlyoutCategory = function(workspace){

  var xmlList = [];

  Blockly.cwEvent.generateEventBuiltins(xmlList);

  return xmlList;
};

<|endoftext|>


<commit_before>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 Marco Grätsch
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 *
 * @param {jQuery} $
 */
(function($) {
    'use strict';

    var filterMode = 'unlink',
        elementClass = 'lsr-link',
        parentClass = 'lsr-link-parent',
        domainlist = (JSON.parse(localStorage.getItem('domainlist')) || []),

        /**
         * Predefined filters
         */
        filters = {
            unlink: function($el, $parent, url, domain) {
                if ($parent && $parent.length && !$parent.hasClass(parentClass)) {
                    $parent.addClass(parentClass);
                }
                var $span = $('').text($el.text());
                $span.addClass(elementClass);
                $el.replaceWith($span);
            },
            remove: function($el, $parent, url, domain) {
                if ($parent && $parent.length) {
                    $parent.replaceWith('');
                    return;
                }
                $el.replaceWith('');
            },
            marker: function($el, $parent, url, domain) {
                if ($parent && $parent.length && !$parent.hasClass(parentClass)) {
                    $parent.addClass(parentClass);
                }
                if (!$el.hasClass(elementClass)) {
                    $el.addClass(elementClass);
                }
            }
        },

        /**
         * Update List Handler
         *
         * @param {String} url
         * @param {Function} cb
         */
        updateList = function(url, cb) {
            $.get(url, {}, function(data, status, jqXHR) {
                var ts = Math.round(Date.now()/1000);
                localStorage.setItem('domainlist', JSON.stringify(data));
                localStorage.setItem('last-update', ts);
                domainlist = data;
                cb(data, ts, url, status);
            }, 'json');
        },

        /**
         * Check if an update should be performed
         *
         * @param {String} interval
         * @return {Boolean}
         */
        checkUpdates = function(interval) {
            var lastUpdate = localStorage.getItem('last-update') || null,
                intervalTime = 0,
                now = Math.round(Date.now()/1000);

            if (!localStorage.getItem('domainlist')) {
                return true;
            }
            if (!lastUpdate) {
                return true;
            }

            switch (interval) {
                case 'hourly':
                    intervalTime = (60*60);
                    break;

                case 'daily':
                    intervalTime = (60*60*24);
                    break;

                case 'weekly':
                    intervalTime = (60*60*24*7);
                    break;
                    break;

                case 'monthly':
                    intervalTime = (60*60*24*30);
                    break;
            }

            if (now >= lastUpdate + intervalTime) {
                return true;
            }
            return false;
        },

        /**
         * Check if the URL is a link to a specific domain
         */
        match = function(url, domain) {
            return url.indexOf(domain) !== -1;
        },

        /**
         * Filter an element
         *
         * @param {jQuery} $el
         * @param {jQuery} $parent
         * @param {String} domain
         * @param {Function} cb
         */
        filter = function($el, $parent, domain, cb) {
            var url = $el.attr('href');
            if (url) {
                if (match(url, domain)) {
                    cb($el, $parent, url, domain);
                }
                return;
            }

            $el.find('a,link').each(function() {
                filter($(this), $el, domain, cb);
            });
        },

        /**
         * Default onUpdateList-Handler
         *
         * @param {Array} data
         * @param {Number} ts
         * @param {String} url
         * @param {String} status
         */
        onUpdateList = function(data, ts, url, status) {},

        /**
         * Default onFilterMatch-Handler
         *
         * @param {jQuery} $el
         * @param {jQuery} $parent
         * @param {String} url
         * @param {String} domain
         */
        onFilterMatch = function($el, $parent, url, domain) {
            if (filters[filterMode]) {
                filters[filterMode]($el, $parent, url, domain);
            }
        },

        /**
         * Default Options
         */
        defaultOptions = {
            domainlist: 'https://cdn.rawgit.com/magdev/leistungsschutzgelderpresser/master/domains.json',
            updateInterval: 'weekly',
            forceUpdate: false,
            onFilterMatch: onFilterMatch,
            onUpdateList: onUpdateList,
            filterMode: 'unlink',
            parentSelector: null,
            elementClass: 'lsr-link',
            parentClass: 'lsr-link-parent'
        };

    /**
     * jQuery LSR-Filter
     *
     * @param {Object} options
     * @return {jQuery}
     */
    $.fn.lsr = function(options) {
        var opts = $.extend(defaultOptions, options);

        if (checkUpdates(opts.updateInterval) || opts.forceUpdate) {
            updateList(opts.domainlist, opts.onUpdateList);
        }

        filterMode = opts.filterMode;
        elementClass = opts.elementClass;
        parentClass = opts.parentClass;

        return this.each(function() {
            var $this = $(this),
                $parent = $(this).closest(opts.parentSelector);

            domainlist.forEach(function(domain) {
                filter($this, $parent, domain, opts.onFilterMatch);
            });
        });
    };

})(jQuery);<commit_msg>removed unreachable break<commit_after>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 Marco Grätsch
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 *
 * @param {jQuery} $
 */
(function($) {
    'use strict';

    var filterMode = 'unlink',
        elementClass = 'lsr-link',
        parentClass = 'lsr-link-parent',
        domainlist = (JSON.parse(localStorage.getItem('domainlist')) || []),

        /**
         * Predefined filters
         */
        filters = {
            unlink: function($el, $parent, url, domain) {
                if ($parent && $parent.length && !$parent.hasClass(parentClass)) {
                    $parent.addClass(parentClass);
                }
                var $span = $('').text($el.text());
                $span.addClass(elementClass);
                $el.replaceWith($span);
            },
            remove: function($el, $parent, url, domain) {
                if ($parent && $parent.length) {
                    $parent.replaceWith('');
                    return;
                }
                $el.replaceWith('');
            },
            marker: function($el, $parent, url, domain) {
                if ($parent && $parent.length && !$parent.hasClass(parentClass)) {
                    $parent.addClass(parentClass);
                }
                if (!$el.hasClass(elementClass)) {
                    $el.addClass(elementClass);
                }
            }
        },

        /**
         * Update List Handler
         *
         * @param {String} url
         * @param {Function} cb
         */
        updateList = function(url, cb) {
            $.get(url, {}, function(data, status, jqXHR) {
                var ts = Math.round(Date.now()/1000);
                localStorage.setItem('domainlist', JSON.stringify(data));
                localStorage.setItem('last-update', ts);
                domainlist = data;
                cb(data, ts, url, status);
            }, 'json');
        },

        /**
         * Check if an update should be performed
         *
         * @param {String} interval
         * @return {Boolean}
         */
        checkUpdates = function(interval) {
            var lastUpdate = localStorage.getItem('last-update') || null,
                intervalTime = 0,
                now = Math.round(Date.now()/1000);

            if (!localStorage.getItem('domainlist')) {
                return true;
            }
            if (!lastUpdate) {
                return true;
            }

            switch (interval) {
                case 'hourly':
                    intervalTime = (60*60);
                    break;

                case 'daily':
                    intervalTime = (60*60*24);
                    break;

                case 'weekly':
                    intervalTime = (60*60*24*7);
                    break;

                case 'monthly':
                    intervalTime = (60*60*24*30);
                    break;
            }

            if (now >= lastUpdate + intervalTime) {
                return true;
            }
            return false;
        },

        /**
         * Check if the URL is a link to a specific domain
         */
        match = function(url, domain) {
            return url.indexOf(domain) !== -1;
        },

        /**
         * Filter an element
         *
         * @param {jQuery} $el
         * @param {jQuery} $parent
         * @param {String} domain
         * @param {Function} cb
         */
        filter = function($el, $parent, domain, cb) {
            var url = $el.attr('href');
            if (url) {
                if (match(url, domain)) {
                    cb($el, $parent, url, domain);
                }
                return;
            }

            $el.find('a,link').each(function() {
                filter($(this), $el, domain, cb);
            });
        },

        /**
         * Default onUpdateList-Handler
         *
         * @param {Array} data
         * @param {Number} ts
         * @param {String} url
         * @param {String} status
         */
        onUpdateList = function(data, ts, url, status) {},

        /**
         * Default onFilterMatch-Handler
         *
         * @param {jQuery} $el
         * @param {jQuery} $parent
         * @param {String} url
         * @param {String} domain
         */
        onFilterMatch = function($el, $parent, url, domain) {
            if (filters[filterMode]) {
                filters[filterMode]($el, $parent, url, domain);
            }
        },

        /**
         * Default Options
         */
        defaultOptions = {
            domainlist: 'https://cdn.rawgit.com/magdev/leistungsschutzgelderpresser/master/domains.json',
            updateInterval: 'weekly',
            forceUpdate: false,
            onFilterMatch: onFilterMatch,
            onUpdateList: onUpdateList,
            filterMode: 'unlink',
            parentSelector: null,
            elementClass: 'lsr-link',
            parentClass: 'lsr-link-parent'
        };

    /**
     * jQuery LSR-Filter
     *
     * @param {Object} options
     * @return {jQuery}
     */
    $.fn.lsr = function(options) {
        var opts = $.extend(defaultOptions, options);

        if (checkUpdates(opts.updateInterval) || opts.forceUpdate) {
            updateList(opts.domainlist, opts.onUpdateList);
        }

        filterMode = opts.filterMode;
        elementClass = opts.elementClass;
        parentClass = opts.parentClass;

        return this.each(function() {
            var $this = $(this),
                $parent = $(this).closest(opts.parentSelector);

            domainlist.forEach(function(domain) {
                filter($this, $parent, domain, opts.onFilterMatch);
            });
        });
    };

})(jQuery);<|endoftext|>


<commit_before>/**
 * Created by 166878 on 20.09.2016.
 */
function certificateToStr(certificate){
    return  "" +
            "   " + certificate.id + "" +
            "   " + certificate.flight_type +
            " ";
}
function getHourRow(hour){
    var now= new Date();
    var hours_change = -(now.getTimezoneOffset())/60+3;
    var hourToShow=parseInt(hour)+hours_change;
    return  "
" +
            "   " + hourToShow + ":00	" +
            "   " +
            "

" +
            "   	" +
            "
";
}

function showModal(date){
    //Showing modal window with per-day schedule table
    $("#chosen_date").html(date.format("DD.MM.YYYY"));
    $(".current-date").html(date.format("YYYY-MM-DD"));
    $("#time_table").find(".hour-row").remove();
    $("#found_certs").find(".cert_row").remove();
    $(".day-empty").addClass("hidden");
    $("#myModal").modal("show");

    //Retrieving per-day schedule
    var chosen_date = date.unix();
    getTimeTableData(chosen_date);
    findCertificates();
}
function fillTimeTableWithData(table_selector, data){
    //If there is more than one busy hour
    if (Object.keys(data).length > 0) {

        //Iterating over the hours
        for (var hour in data) {
            //Retrieve next hour
            if (!data.hasOwnProperty(hour)) {
                continue;
            }
            var certificates_in_hour = data[hour];

            //If there is more than one flight in that hour
            if (certificates_in_hour.length != 0) {
                //Creating new hour row in table
                $(table_selector).append(getHourRow(hour));

                //Iterating over the flights in this hour and rendering them
                certificates_in_hour.forEach(function(item, i, arr){
                    $(table_selector + " .certificates-in-hour-"+hour).append(certificateToStr(item));
                });
            }
        }
    }
    //Otherwise showing the string telling the day is empty
    else {
        $(table_selector + " .day-empty").removeClass("hidden");
    }
}
function getTimeTableData(date){
    $("#time_table_loader").removeClass("hidden");
    jQuery.getJSON("/admin/show_day_schedule?date="+date, function (data){
        $("#time_table_loader").addClass("hidden");
        fillTimeTableWithData("#time_table", data);
    });
}

function getCertRow(cert) {
    return "
" +
        "   " +
        "       "+cert.ID_Sertificate+"" +
        "   	" +
        "   "+
                cert.name + " " + cert.last_name + "" +
        "   	" +
        "   " +
        "       <button class='btn btn-xs btn-default' data-toggle='collapse' data-target='#" + cert.ID_Sertificate + "'>" +
        "           " +
        "       </button>" +
        "   	" +
        "
" +
        "
" +
        "    " +
        "
" +
        "               <input type='text' class='form-control' placeholder='Часы' id='hours-"+cert.ID_Sertificate+"'>" +
        "               :" +
        "               <input type='text' class='form-control' placeholder='Минуты' id='minutes-"+cert.ID_Sertificate+"'>" +
        "               "+
        "                   <button class='btn btn-default set-use-time-btn' type='button' data-certificate-id='"+ cert.ID_Sertificate +"'>Ok</button>" +
        "               " +
        "
" +
        "   	" +
        "
"
}

function onYesSetTime(event){
    var modal_window = event.data;
    var date = moment(modal_window.data.date).unix();
    var certificate_id = JSON.stringify([modal_window.data.certificate_id]);
    var fieldnames = JSON.stringify(["use_time"]);
    var fieldvalues = JSON.stringify([date]);
    modal_window.showLoader();

    $("#time_table" + " .day-empty").addClass("hidden");
    //TODO: Make post query to set use_time to certificate
    jQuery.post("/certificate/edit", {ids : certificate_id, field_names : fieldnames, field_values: fieldvalues}, function (data) {
        console.log(data);
        $("#time_table").find(".hour-row").remove();
        $("#found_certs").find(".cert_row").remove();
        getTimeTableData(date);
        findCertificates();
    });
    modal_window.hideLoader();
    modal_window.close();

}

function onNoSetTime(event){

}

function onSetUseTime(event){
    var btn = $(this);

    var certificate_id = $(this).data("certificate-id");
    if (certificate_id == "undefined"){
        return false;
    }
    var now= new Date();
    var hours_change = -(now.getTimezoneOffset())/60+3;
    var hours = parseInt($("#hours-"+certificate_id).val())-hours_change;
    var hoursToShow = $("#hours-"+certificate_id).val();
    var minutes = $("#minutes-"+certificate_id).val();
    var seconds = "00";
    var date=$(".current-date").html() + " " + [hours, minutes, seconds].join(":");
    var dateToShow=$(".current-date").html() + " " + [hoursToShow, minutes, seconds].join(":");
    //ToDo check validate time
    var dialog = new YesNoDialog();
    dialog.setModalSelector("#yes-no-modal");
    dialog.show({
        caption: "Установка времеи",
        message: dateToShow,

        yes_caption: "Установить",
        no_caption: "Отмена",

        data: {
            "certificate_id": certificate_id,
            "date": date
        },

        yes_handler: onYesSetTime,
        no_handler: onNoSetTime
    });

    return true;
}

function fillCertsListWithData(table_selector,data){
    data.forEach(function(item) {
       $(table_selector).append(getCertRow(item))
    });
    $(".set-use-time-btn").click(onSetUseTime);
    $("#find_cert").click(data, findByIDCertificate);
    $("#clear_filter").click(data, clearSearchFilter);
}

function findCertificates() {
    $("#found_cert_loader").removeClass("hidden");
    var fields = JSON.stringify(["ID_Sertificate", "flight_type", "cert_link", "name", "last_name"]);
    var criteria = JSON.stringify({ "ID_SertState": [5]});
    jQuery.post("/certificate/select", {field_names : fields, criteria : criteria}, function (data) {
        $("#found_cert_loader").addClass("hidden");
        fillCertsListWithData("#found_certs",data)
    })

}

function findByIDCertificate(data){
    var id = $("#cert_id_for_watching").val();
    var found = false;
    var certificate_list = data.data;

    certificate_list.forEach(function (item) {
        if (item.ID_Sertificate == id){
            $("#found_certs").find(".cert_row").remove();
            $("#found_certs").append(getCertRow(item));
            found = true;
        }
    });
    if (!found){
        $("#found_certs").find(".cert_row").remove();
        $("#found_certs").append("
Сертификат не найдет
");
    }
}

function clearSearchFilter(event){
    var certificate_list = event.data;
    $("#cert_id_for_watching").val("");
    $("#found_certs").find(".cert_row").remove();

    certificate_list.forEach(function (item) {
        $("#found_certs").append(getCertRow(item));
    });
}

$(document).ajaxError(function(event, jqXHR, ajaxSettings, message){
    console.log(message);
});

$(document).ready(function(e){

    $("#calendar").fullCalendar({
        monthNames: ["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],
        header: {
            left: 'title',
            right: 'today, prev, next'
        },
        dayClick: showModal
    });
});<commit_msg>Changed hour change.<commit_after>/**
 * Created by 166878 on 20.09.2016.
 */
function certificateToStr(certificate){
    return  "" +
            "   " + certificate.id + "" +
            "   " + certificate.flight_type +
            " ";
}
function getHourRow(hour){
    var now= new Date();
    var hours_change = -(now.getTimezoneOffset())/60;
    var hourToShow=parseInt(hour)+hours_change;
    return  "
" +
            "   " + hourToShow + ":00	" +
            "   " +
            "

" +
            "   	" +
            "
";
}

function showModal(date){
    //Showing modal window with per-day schedule table
    $("#chosen_date").html(date.format("DD.MM.YYYY"));
    $(".current-date").html(date.format("YYYY-MM-DD"));
    $("#time_table").find(".hour-row").remove();
    $("#found_certs").find(".cert_row").remove();
    $(".day-empty").addClass("hidden");
    $("#myModal").modal("show");

    //Retrieving per-day schedule
    var chosen_date = date.unix();
    getTimeTableData(chosen_date);
    findCertificates();
}
function fillTimeTableWithData(table_selector, data){
    //If there is more than one busy hour
    if (Object.keys(data).length > 0) {

        //Iterating over the hours
        for (var hour in data) {
            //Retrieve next hour
            if (!data.hasOwnProperty(hour)) {
                continue;
            }
            var certificates_in_hour = data[hour];

            //If there is more than one flight in that hour
            if (certificates_in_hour.length != 0) {
                //Creating new hour row in table
                $(table_selector).append(getHourRow(hour));

                //Iterating over the flights in this hour and rendering them
                certificates_in_hour.forEach(function(item, i, arr){
                    $(table_selector + " .certificates-in-hour-"+hour).append(certificateToStr(item));
                });
            }
        }
    }
    //Otherwise showing the string telling the day is empty
    else {
        $(table_selector + " .day-empty").removeClass("hidden");
    }
}
function getTimeTableData(date){
    $("#time_table_loader").removeClass("hidden");
    jQuery.getJSON("/admin/show_day_schedule?date="+date, function (data){
        $("#time_table_loader").addClass("hidden");
        fillTimeTableWithData("#time_table", data);
    });
}

function getCertRow(cert) {
    return "
" +
        "   " +
        "       "+cert.ID_Sertificate+"" +
        "   	" +
        "   "+
                cert.name + " " + cert.last_name + "" +
        "   	" +
        "   " +
        "       <button class='btn btn-xs btn-default' data-toggle='collapse' data-target='#" + cert.ID_Sertificate + "'>" +
        "           " +
        "       </button>" +
        "   	" +
        "
" +
        "
" +
        "    " +
        "
" +
        "               <input type='text' class='form-control' placeholder='Часы' id='hours-"+cert.ID_Sertificate+"'>" +
        "               :" +
        "               <input type='text' class='form-control' placeholder='Минуты' id='minutes-"+cert.ID_Sertificate+"'>" +
        "               "+
        "                   <button class='btn btn-default set-use-time-btn' type='button' data-certificate-id='"+ cert.ID_Sertificate +"'>Ok</button>" +
        "               " +
        "
" +
        "   	" +
        "
"
}

function onYesSetTime(event){
    var modal_window = event.data;
    var date = moment(modal_window.data.date).unix();
    var certificate_id = JSON.stringify([modal_window.data.certificate_id]);
    var fieldnames = JSON.stringify(["use_time"]);
    var fieldvalues = JSON.stringify([date]);
    modal_window.showLoader();

    $("#time_table" + " .day-empty").addClass("hidden");
    //TODO: Make post query to set use_time to certificate
    jQuery.post("/certificate/edit", {ids : certificate_id, field_names : fieldnames, field_values: fieldvalues}, function (data) {
        console.log(data);
        $("#time_table").find(".hour-row").remove();
        $("#found_certs").find(".cert_row").remove();
        getTimeTableData(date);
        findCertificates();
    });
    modal_window.hideLoader();
    modal_window.close();

}

function onNoSetTime(event){

}

function onSetUseTime(event){
    var btn = $(this);

    var certificate_id = $(this).data("certificate-id");
    if (certificate_id == "undefined"){
        return false;
    }
    var now= new Date();
    var hours_change = -(now.getTimezoneOffset())/60;
    var hours = parseInt($("#hours-"+certificate_id).val())-hours_change;
    var hoursToShow = $("#hours-"+certificate_id).val();
    var minutes = $("#minutes-"+certificate_id).val();
    var seconds = "00";
    var date=$(".current-date").html() + " " + [hours, minutes, seconds].join(":");
    var dateToShow=$(".current-date").html() + " " + [hoursToShow, minutes, seconds].join(":");
    //ToDo check validate time
    var dialog = new YesNoDialog();
    dialog.setModalSelector("#yes-no-modal");
    dialog.show({
        caption: "Установка времеи",
        message: dateToShow,

        yes_caption: "Установить",
        no_caption: "Отмена",

        data: {
            "certificate_id": certificate_id,
            "date": date
        },

        yes_handler: onYesSetTime,
        no_handler: onNoSetTime
    });

    return true;
}

function fillCertsListWithData(table_selector,data){
    data.forEach(function(item) {
       $(table_selector).append(getCertRow(item))
    });
    $(".set-use-time-btn").click(onSetUseTime);
    $("#find_cert").click(data, findByIDCertificate);
    $("#clear_filter").click(data, clearSearchFilter);
}

function findCertificates() {
    $("#found_cert_loader").removeClass("hidden");
    var fields = JSON.stringify(["ID_Sertificate", "flight_type", "cert_link", "name", "last_name"]);
    var criteria = JSON.stringify({ "ID_SertState": [5]});
    jQuery.post("/certificate/select", {field_names : fields, criteria : criteria}, function (data) {
        $("#found_cert_loader").addClass("hidden");
        fillCertsListWithData("#found_certs",data)
    })

}

function findByIDCertificate(data){
    var id = $("#cert_id_for_watching").val();
    var found = false;
    var certificate_list = data.data;

    certificate_list.forEach(function (item) {
        if (item.ID_Sertificate == id){
            $("#found_certs").find(".cert_row").remove();
            $("#found_certs").append(getCertRow(item));
            found = true;
        }
    });
    if (!found){
        $("#found_certs").find(".cert_row").remove();
        $("#found_certs").append("
Сертификат не найдет
");
    }
}

function clearSearchFilter(event){
    var certificate_list = event.data;
    $("#cert_id_for_watching").val("");
    $("#found_certs").find(".cert_row").remove();

    certificate_list.forEach(function (item) {
        $("#found_certs").append(getCertRow(item));
    });
}

$(document).ajaxError(function(event, jqXHR, ajaxSettings, message){
    console.log(message);
});

$(document).ready(function(e){

    $("#calendar").fullCalendar({
        monthNames: ["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],
        header: {
            left: 'title',
            right: 'today, prev, next'
        },
        dayClick: showModal
    });
});<|endoftext|>


<commit_before>module.exports = {
    members: {
        currentCountQuery: async (db) => {
            let result = await db.knex('members').count('id', {as: 'count'}).first();
            return result.count;
        }
    },
    staff: {
        currentCountQuery: async (db) => {
            let result = await db.knex('users')
                .select('users.id')
                .leftJoin('roles_users', 'users.id', 'roles_users.user_id')
                .leftJoin('roles', 'roles_users.role_id', 'roles.id')
                .whereNot('roles.name', 'Contributor').andWhereNot('users.status', 'inactive').union([
                    db.knex('invites')
                        .select('invites.id')
                        .leftJoin('roles', 'invites.role_id', 'roles.id')
                        .whereNot('roles.name', 'Contributor')
                ]);

            return result.length;
        }
    },
    customIntegrations: {
        currentCountQuery: async (db) => {
            let result = await db.knex('integrations').count('id', {as: 'count'}).whereNotIn('type', ['internal', 'builtin']).first();
            return result.count;
        }
    },
    customThemes: {}
};
<commit_msg>Improved query formatting<commit_after>module.exports = {
    members: {
        currentCountQuery: async (db) => {
            let result = await db.knex('members').count('id', {as: 'count'}).first();
            return result.count;
        }
    },
    staff: {
        currentCountQuery: async (db) => {
            let result = await db.knex('users')
                .select('users.id')
                .leftJoin('roles_users', 'users.id', 'roles_users.user_id')
                .leftJoin('roles', 'roles_users.role_id', 'roles.id')
                .whereNot('roles.name', 'Contributor').andWhereNot('users.status', 'inactive').union([
                    db.knex('invites')
                        .select('invites.id')
                        .leftJoin('roles', 'invites.role_id', 'roles.id')
                        .whereNot('roles.name', 'Contributor')
                ]);

            return result.length;
        }
    },
    customIntegrations: {
        currentCountQuery: async (db) => {
            let result = await db.knex('integrations')
                .count('id', {as: 'count'})
                .whereNotIn('type', ['internal', 'builtin'])
                .first();

            return result.count;
        }
    },
    customThemes: {}
};
<|endoftext|>


<commit_before>this.mmooc=this.mmooc||{};

this.mmooc.api = function() {
    var _urlToTypeMapping = [];

    _urlToTypeMapping['quizzes'] = 'Quiz';
    _urlToTypeMapping['assignments'] = 'Assignment';
    _urlToTypeMapping['discussion_topics'] = 'Discussion';

    return {
        _ajax: typeof $   !== "undefined" ? $   : {},

        _env:  typeof ENV !== "undefined" ? ENV : {},

        _location: typeof document !== "undefined" ? document.location : {search:"", href:""},

        _uriPrefix: "/api/v1",

        _defaultError: function (event, jqxhr, settings, thrownError) {
            console.log(event, jqxhr, settings, thrownError);
        },

        _sendRequest: function(method, options) {
            var error    = options.error || this._defaultError;
            var uri      = this._uriPrefix + options.uri;
            var params   = options.params || {};
            var callback = options.callback;
            method(uri, params, callback).fail(error);
        },

        _get: function(options) {
            this._sendRequest(this._ajax.get, options);
        },

        _post: function(options) {
            this._sendRequest(this._ajax.post, options);
        },

        /*  FIXME for listModulesForCourse()
         *  This function loads data in a blocking manner no matter how many items and modules are present.
         *  This could potentially pose problems in the future, as page load time increases rapidly when
         *  the number of requests are numerous. This function should be updated to use non-blocking loading
         *  if Canvas is not updated to allow for better data loading through their API.
         */
        listModulesForCourse: function(callback, error, cid)
        {
        	var href= "/api/v1/courses/" + cid + "/modules";
        	$.getJSON(href, function(modules) {
        		var noOfModules = modules.length;
        		var asyncsDone = 0;
        		for (var i = 0; i < noOfModules; i++) {
        			var m = modules[i];
        			var href= "/api/v1/courses/" + cid + "/modules/" + m.id + "/items";
        			$.getJSON(
        				href,
        				(function(j) {
        			    return function(items) {
        						modules[j].items = items;
        						asyncsDone++;

        						if(asyncsDone === noOfModules) {
        							callback(modules);
        						}
        					};
            		}(i)) // calling the function with the current value
        	    );
        		};
        	}
        	);
        },

        getCurrentModuleItemId : function() {
            var paramName = "module_item_id";
            var q = "" + this._location.search;
            if (typeof q === "undefined" || q.indexOf(paramName) == -1) {
                return null;
            }

            var moduleId = q.substring(q.indexOf(paramName) + paramName.length + 1, q.length);
            if (moduleId.indexOf("&") != -1) {
                moduleId = moduleId.substring(0, moduleId.indexOf("&"));
            }

            return parseInt(moduleId, 10);
        },

        getCurrentContentId : function() {
            var q = "" + this._location.pathname;

            var moduleId = q.substring(q.indexOf(paramName) + paramName.length + 1, q.length);
            if (moduleId.indexOf("&") != -1) {
                moduleId = moduleId.substring(0, moduleId.indexOf("&"));
            }

            return parseInt(moduleId, 10);
        },

        getCurrentTypeAndContentId: function() {
            var regexp = /\/courses\/\d+\/\w+\/\d+/;

            if (regexp.test("" + this._location.pathname)) {
                var tmp = this._location.pathname.split("/");
                if (tmp.length >= 5) {
                    var type = _urlToTypeMapping[tmp[3]];
                    var contentId = parseInt(tmp[4], 10);
                    return { contentId: contentId, type: type};
                }
            }
            return null;
        },

        getEnrolledCourses: function(callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/courses",
                "params":   { "include": ["syllabus_body" , "course_progress"], "per_page": "100" }
            });
        },

        /* FIXME Regarding include items: This parameter suggests that
         * Canvas return module items directly in the Module object
         * JSON, to avoid having to make separate API requests for
         * each module when enumerating modules and items. Canvas is
         * free to omit 'items' for any particular module if it deems
         * them too numerous to return inline. Callers must be
         * prepared to use the List Module Items API if items are not
         * returned.
         */
        getModulesForCurrentCourse: function(callback, error) {
            var courseId = this.getCurrentCourseId();
            this.listModulesForCourse(callback, error, courseId);
        },

        getModulesForCourseId: function(callback, error, courseId) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/courses/" + courseId + "/modules",
                "params":   { }
            });
        },

        getItemsForModuleId: function(callback, error, courseId, moduleId) {
          this._get({
            "callback": callback,
            "error": error,
            "uri": "/courses/" + courseId + "/modules/" + moduleId + "/items",
            "params": { }
          });
        },

        getCurrentCourseId: function() {
            var currentUrl = "" + this._location.pathname;
            var matches = currentUrl.match(/\/courses\/(\d+)/);
            if (matches != null) {
                return parseInt(matches[1], 10);
            } else if (this._env.group) {
                // Group pages does not contain course id in URL, but is available via JavaScript variable
                return this._env.group.context_id;
            } else if ($("#section-tabs-header-subtitle").size() > 0) {
                // Group subpages contains course id only in a link
                var tmp = $("#section-tabs-header-subtitle").attr("href").split("/");
                if (tmp.length == 3) {
                    return parseInt(tmp[2], 10);
                }
            }

            return null;
        },

        getCourse: function(courseId, callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/courses/" + courseId,
                "params":   {  }
            });
        },

        getCurrentGroupId: function() {
            var currentUrl = "" + this._location.pathname;
            var matches = currentUrl.match(/\/groups\/(\d+)/);
            if (matches != null) {
                return parseInt(matches[1], 10);
            }
            return null;
        },

        getGroup: function(groupId, callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/groups/" + groupId,
                "params":   {}
            });
        },

        getGroupMembers: function(groupId, callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/groups/" + groupId + "/users",
                "params":   {"include": ["avatar_url"] }
            });
        },

        getCurrentModule: function(callback, error) {
            var currentModuleItemId = this.getCurrentModuleItemId();
            var currentTypeAndContentId = null;
            if (currentModuleItemId == null) {
                currentTypeAndContentId = this.getCurrentTypeAndContentId();
                if (currentTypeAndContentId == null) {
                    return;
                }
            }

            this.getModulesForCurrentCourse(function(modules) {
                for (var i = 0; i < modules.length; i++) {
                    var module = modules[i];
                    var items = module.items;
                    for (var j = 0; j < items.length; j++) {
                        var item = items[j];
                        if (item.id == currentModuleItemId || (currentTypeAndContentId != null && currentTypeAndContentId.contentId == item.content_id && currentTypeAndContentId.type == item.type)) {
                            item.isCurrent = true;
                            callback(module);
                            return;
                        }
                    }
                }

            }, error);
        },

        getRoles : function() {
            return this._env.current_user_roles;
        },

        getUser : function() {
            return this._env.current_user;
        },

        getUserProfile : function(callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/users/self/profile",
                "params":   { }
            });
        },

        getActivityStreamForUser: function(callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/users/self/activity_stream",
                "params":   { }
            });
        },

        currentPageIsAnnouncement: function() {
            return ($("#section-tabs").find("a.announcements.active").size() == 1);
        },

        currentPageIsModuleItem: function() {
            if (this.getCurrentModuleItemId() != null || this.getCurrentTypeAndContentId() != null) {
                return true;
            } else {
                return false;
            }
        },

        getUnreadMessageSize: function() {
          return parseInt(document.getElementsByClassName('unread-messages-count')[0].innerHTML);
        },

        getAccounts: function(callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/accounts",
                "params":   { }
            });

        },

        getUsersForAccount: function(account, callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/accounts/" + account + "/users",
                "params":   { }
            });
        },

        getCoursesForAccount: function(account, callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/accounts/" + account + "/courses",
                "params":   { }
            });
        },

        getGroupCategoriesForAccount: function(account, callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/accounts/" + account + "/group_categories",
                "params":   { }
            });
        },

      getGroupCategoriesForCourse: function(course, callback, error) {
        this._get({
          "callback": callback,
          "error":    error,
          "uri":      "/courses/" + course + "/group_categories",
          "params":   { }
        });
      },

      // Recursively fetch all groups by following the next links
      // found in the Links response header:
      // https://canvas.instructure.com/doc/api/file.pagination.html
      _getGroupsForAccountHelper: function(accumulatedGroups, callback, error) {
        var that = this;
        return function(groups, status, xhr) {
          Array.prototype.push.apply(accumulatedGroups, groups);
          var next = xhr.getResponseHeader('Link').split(',').find(function (e) {
            return e.match("rel=\"next\"");
          });
          if (next === undefined) {
            callback(accumulatedGroups);
          }
          else {
            var fullURI = next.match("<([^>]+)>")[1];
            that._get({
              "callback": that._getGroupsForAccountHelper(accumulatedGroups, callback, error),
              "error":    error,
              "uri":      fullURI.split("api/v1")[1],
              "params":   { }
            });
          }
        };
      },

        getGroupsForAccount: function(account, callback, error) {
            this._get({
              "callback": this._getGroupsForAccountHelper([], callback, error),
              "error":    error,
              "uri":      "/accounts/" + account + "/groups",
              "params":   { per_page: 999 }
            });
        },

        createGroup: function(params, callback, error) {
            this._post({
                "callback": callback,
                "error":    error,
                "uri":      "/group_categories/" + params.category + "/groups",
                "params":   {
                    name: params.name,
                    description: params.description,
                    is_public: false,
                    join_level: 'invitation_only'
                }
            });
        },

        createGroupMembership: function(gid, uid, callback, error) {
            this._post({
                "callback": callback,
                "error":    error,
                "uri":      "/groups/" + gid + "/memberships",
                "params":   { user_id: uid }
            });

        },

      createUserLogin: function(params, callback, error) {
        var account_id = params.account_id;
        delete params.account_id;
        this._post({
          "callback": callback,
          "error":  error,
          "uri": "/accounts/" + account_id + "/logins",
          "params": params
        });
      }
    };
}();

if (typeof module !== "undefined" && module !== null) {
    module.exports = this.mmooc.api;
}
<commit_msg>[MAT-231] Changed to include all avatars<commit_after>this.mmooc=this.mmooc||{};

this.mmooc.api = function() {
    var _urlToTypeMapping = [];

    _urlToTypeMapping['quizzes'] = 'Quiz';
    _urlToTypeMapping['assignments'] = 'Assignment';
    _urlToTypeMapping['discussion_topics'] = 'Discussion';

    return {
        _ajax: typeof $   !== "undefined" ? $   : {},

        _env:  typeof ENV !== "undefined" ? ENV : {},

        _location: typeof document !== "undefined" ? document.location : {search:"", href:""},

        _uriPrefix: "/api/v1",

        _defaultError: function (event, jqxhr, settings, thrownError) {
            console.log(event, jqxhr, settings, thrownError);
        },

        _sendRequest: function(method, options) {
            var error    = options.error || this._defaultError;
            var uri      = this._uriPrefix + options.uri;
            var params   = options.params || {};
            var callback = options.callback;
            method(uri, params, callback).fail(error);
        },

        _get: function(options) {
            this._sendRequest(this._ajax.get, options);
        },

        _post: function(options) {
            this._sendRequest(this._ajax.post, options);
        },

        /*  FIXME for listModulesForCourse()
         *  This function loads data in a blocking manner no matter how many items and modules are present.
         *  This could potentially pose problems in the future, as page load time increases rapidly when
         *  the number of requests are numerous. This function should be updated to use non-blocking loading
         *  if Canvas is not updated to allow for better data loading through their API.
         */
        listModulesForCourse: function(callback, error, cid)
        {
        	var href= "/api/v1/courses/" + cid + "/modules";
        	$.getJSON(href, function(modules) {
        		var noOfModules = modules.length;
        		var asyncsDone = 0;
        		for (var i = 0; i < noOfModules; i++) {
        			var m = modules[i];
        			var href= "/api/v1/courses/" + cid + "/modules/" + m.id + "/items";
        			$.getJSON(
        				href,
        				(function(j) {
        			    return function(items) {
        						modules[j].items = items;
        						asyncsDone++;

        						if(asyncsDone === noOfModules) {
        							callback(modules);
        						}
        					};
            		}(i)) // calling the function with the current value
        	    );
        		};
        	}
        	);
        },

        getCurrentModuleItemId : function() {
            var paramName = "module_item_id";
            var q = "" + this._location.search;
            if (typeof q === "undefined" || q.indexOf(paramName) == -1) {
                return null;
            }

            var moduleId = q.substring(q.indexOf(paramName) + paramName.length + 1, q.length);
            if (moduleId.indexOf("&") != -1) {
                moduleId = moduleId.substring(0, moduleId.indexOf("&"));
            }

            return parseInt(moduleId, 10);
        },

        getCurrentContentId : function() {
            var q = "" + this._location.pathname;

            var moduleId = q.substring(q.indexOf(paramName) + paramName.length + 1, q.length);
            if (moduleId.indexOf("&") != -1) {
                moduleId = moduleId.substring(0, moduleId.indexOf("&"));
            }

            return parseInt(moduleId, 10);
        },

        getCurrentTypeAndContentId: function() {
            var regexp = /\/courses\/\d+\/\w+\/\d+/;

            if (regexp.test("" + this._location.pathname)) {
                var tmp = this._location.pathname.split("/");
                if (tmp.length >= 5) {
                    var type = _urlToTypeMapping[tmp[3]];
                    var contentId = parseInt(tmp[4], 10);
                    return { contentId: contentId, type: type};
                }
            }
            return null;
        },

        getEnrolledCourses: function(callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/courses",
                "params":   { "include": ["syllabus_body" , "course_progress"], "per_page": "100" }
            });
        },

        /* FIXME Regarding include items: This parameter suggests that
         * Canvas return module items directly in the Module object
         * JSON, to avoid having to make separate API requests for
         * each module when enumerating modules and items. Canvas is
         * free to omit 'items' for any particular module if it deems
         * them too numerous to return inline. Callers must be
         * prepared to use the List Module Items API if items are not
         * returned.
         */
        getModulesForCurrentCourse: function(callback, error) {
            var courseId = this.getCurrentCourseId();
            this.listModulesForCourse(callback, error, courseId);
        },

        getModulesForCourseId: function(callback, error, courseId) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/courses/" + courseId + "/modules",
                "params":   { }
            });
        },

        getItemsForModuleId: function(callback, error, courseId, moduleId) {
          this._get({
            "callback": callback,
            "error": error,
            "uri": "/courses/" + courseId + "/modules/" + moduleId + "/items",
            "params": { }
          });
        },

        getCurrentCourseId: function() {
            var currentUrl = "" + this._location.pathname;
            var matches = currentUrl.match(/\/courses\/(\d+)/);
            if (matches != null) {
                return parseInt(matches[1], 10);
            } else if (this._env.group) {
                // Group pages does not contain course id in URL, but is available via JavaScript variable
                return this._env.group.context_id;
            } else if ($("#section-tabs-header-subtitle").size() > 0) {
                // Group subpages contains course id only in a link
                var tmp = $("#section-tabs-header-subtitle").attr("href").split("/");
                if (tmp.length == 3) {
                    return parseInt(tmp[2], 10);
                }
            }

            return null;
        },

        getCourse: function(courseId, callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/courses/" + courseId,
                "params":   {  }
            });
        },

        getCurrentGroupId: function() {
            var currentUrl = "" + this._location.pathname;
            var matches = currentUrl.match(/\/groups\/(\d+)/);
            if (matches != null) {
                return parseInt(matches[1], 10);
            }
            return null;
        },

        getGroup: function(groupId, callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/groups/" + groupId,
                "params":   {}
            });
        },

        getGroupMembers: function(groupId, callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/groups/" + groupId + "/users",
                "params":   {"include": ["avatar_url"], "per_page": 999 }
            });
        },

        getCurrentModule: function(callback, error) {
            var currentModuleItemId = this.getCurrentModuleItemId();
            var currentTypeAndContentId = null;
            if (currentModuleItemId == null) {
                currentTypeAndContentId = this.getCurrentTypeAndContentId();
                if (currentTypeAndContentId == null) {
                    return;
                }
            }

            this.getModulesForCurrentCourse(function(modules) {
                for (var i = 0; i < modules.length; i++) {
                    var module = modules[i];
                    var items = module.items;
                    for (var j = 0; j < items.length; j++) {
                        var item = items[j];
                        if (item.id == currentModuleItemId || (currentTypeAndContentId != null && currentTypeAndContentId.contentId == item.content_id && currentTypeAndContentId.type == item.type)) {
                            item.isCurrent = true;
                            callback(module);
                            return;
                        }
                    }
                }

            }, error);
        },

        getRoles : function() {
            return this._env.current_user_roles;
        },

        getUser : function() {
            return this._env.current_user;
        },

        getUserProfile : function(callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/users/self/profile",
                "params":   { }
            });
        },

        getActivityStreamForUser: function(callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/users/self/activity_stream",
                "params":   { }
            });
        },

        currentPageIsAnnouncement: function() {
            return ($("#section-tabs").find("a.announcements.active").size() == 1);
        },

        currentPageIsModuleItem: function() {
            if (this.getCurrentModuleItemId() != null || this.getCurrentTypeAndContentId() != null) {
                return true;
            } else {
                return false;
            }
        },

        getUnreadMessageSize: function() {
          return parseInt(document.getElementsByClassName('unread-messages-count')[0].innerHTML);
        },

        getAccounts: function(callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/accounts",
                "params":   { }
            });

        },

        getUsersForAccount: function(account, callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/accounts/" + account + "/users",
                "params":   { }
            });
        },

        getCoursesForAccount: function(account, callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/accounts/" + account + "/courses",
                "params":   { }
            });
        },

        getGroupCategoriesForAccount: function(account, callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/accounts/" + account + "/group_categories",
                "params":   { }
            });
        },

      getGroupCategoriesForCourse: function(course, callback, error) {
        this._get({
          "callback": callback,
          "error":    error,
          "uri":      "/courses/" + course + "/group_categories",
          "params":   { }
        });
      },

      // Recursively fetch all groups by following the next links
      // found in the Links response header:
      // https://canvas.instructure.com/doc/api/file.pagination.html
      _getGroupsForAccountHelper: function(accumulatedGroups, callback, error) {
        var that = this;
        return function(groups, status, xhr) {
          Array.prototype.push.apply(accumulatedGroups, groups);
          var next = xhr.getResponseHeader('Link').split(',').find(function (e) {
            return e.match("rel=\"next\"");
          });
          if (next === undefined) {
            callback(accumulatedGroups);
          }
          else {
            var fullURI = next.match("<([^>]+)>")[1];
            that._get({
              "callback": that._getGroupsForAccountHelper(accumulatedGroups, callback, error),
              "error":    error,
              "uri":      fullURI.split("api/v1")[1],
              "params":   { }
            });
          }
        };
      },

        getGroupsForAccount: function(account, callback, error) {
            this._get({
              "callback": this._getGroupsForAccountHelper([], callback, error),
              "error":    error,
              "uri":      "/accounts/" + account + "/groups",
              "params":   { per_page: 999 }
            });
        },

        createGroup: function(params, callback, error) {
            this._post({
                "callback": callback,
                "error":    error,
                "uri":      "/group_categories/" + params.category + "/groups",
                "params":   {
                    name: params.name,
                    description: params.description,
                    is_public: false,
                    join_level: 'invitation_only'
                }
            });
        },

        createGroupMembership: function(gid, uid, callback, error) {
            this._post({
                "callback": callback,
                "error":    error,
                "uri":      "/groups/" + gid + "/memberships",
                "params":   { user_id: uid }
            });

        },

      createUserLogin: function(params, callback, error) {
        var account_id = params.account_id;
        delete params.account_id;
        this._post({
          "callback": callback,
          "error":  error,
          "uri": "/accounts/" + account_id + "/logins",
          "params": params
        });
      }
    };
}();

if (typeof module !== "undefined" && module !== null) {
    module.exports = this.mmooc.api;
}
<|endoftext|>


<commit_before>/**
 * Created by rubenschmidt on 26.12.2016.
 */
var GISApp = new Vue({
    el: '#gisapp',
    // Custom delimiters so we do not interfere with django natives.
    delimiters: ["[[", "]]"],
    // Add the gisoperationsmixin so we can use the operations api.
    mixins: [gisOperationsMixin],
    data: {
        defaultStyle: {
            "color": "#4b7eff",
            "weight": 5,
            "opacity": 1,
            "fillOpacity": 0.7
        },
        newLayerName: '',
        loadingLayers: false,
        file: null,
        bufferSize: null,
        layers: [],
        selectedFeatures: [],
        lineStringLayer: null,
        polygonLayer: null,
        geoJson: null,
        map: null,
        dialogs: {
            'buffer': false,
            'intersect': false,
            'completed': false,
            'mergeSelected': false,
            'union': false,
            'difference': false,
            'upload': false,
            'error': false
        },
        operations: []

    },
    mounted: function () {
        // When the app is ready. Add the map.
        this.map = L.map('map').setView([0, 0], 2);

        // Add OSM tilelayer as basemap.
        L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
            attribution: '© OpenStreetMap contributors'
        }).addTo(this.map);

        this.map.on('click', function (e) {
            GISApp.resetSelectedFeatures();
        });
    },
    computed: {
        selectedLayers: function () {
            var layers = [];
            for (var i = 0; i < this.layers.length; i++) {
                var obj = this.layers[i];
                if (obj.checked) layers.push(obj);
            }
            return layers
        }
    },
    methods: {
        setCenter: function (lat, lng, zoom) {
            this.map.setView([lat, lng], zoom)
        },
        addData: function (layers) {
            for (var i = 0; i < layers.length; i++) {
                var layer = layers[i];

                var style = {
                    "color": this.getRandomColor(),
                    "weight": 5,
                    "opacity": 1,
                    "fillOpacity": 0.7
                };
                var geoJson = L.geoJSON(layer.points.features, {
                    style: style,
                    onEachFeature: this.onEachFeature
                })
                geoJson.addData(layer.polygons.features);
                geoJson.addData(layer.linestrings.features);
                layer.leafletLayer = geoJson;
                layer.checked = false;
                geoJson.addTo(this.map);
            }
            this.layers = this.layers.concat(layers);
        },
        getRandomColor: function () {
            var letters = '0123456789ABCDEF'.split('');
            var color = '#';
            for (var i = 0; i < 6; i++) {
                color += letters[Math.round(Math.random() * 15)];
            }
            return color;
        },
        onEachFeature: function (feature, layer) {

            var props = feature.properties;
            if (props) {
                var body = "
";
                for (var key in props) {
                    if (props.hasOwnProperty(key)) {
                        body +=
                            ('
' + key + '	' + props[key] + '
');
                    }
                }
                body += "
";
                layer.bindPopup(body);
            }
            //bind click and mouse events.
            layer.on({
                click: this.whenClicked,
                mouseover: this.onMouseOver,
                mouseout: this.onMouseOut
            });
        },
        whenClicked: function (e) {
            // Stop propagation so only the feature click is fired and not the map click.
            L.DomEvent.stopPropagation(e);
            this.addOrRemoveFeatureFromList(e.target);
        },

        onMouseOver: function (e) {
            e.target.openPopup();
            this.highlightFeature(e.target);
        },
        onMouseOut: function (e) {
            e.target.closePopup();
            this.resetHighlight(e.target);
        },
        highlightFeature: function (layer) {
            if (layer._icon) {
                // Points cant be resized stock
                // TODO implement
            } else {
                layer.setStyle({
                    weight: 5,
                    color: '#23c6ff',
                    dashArray: '',
                    fillOpacity: 0.7
                });
            }
        },
        resetHighlight: function (target) {
            for (var i = 0; i < this.layers.length; i++) {
                var layer = this.layers[i];
                if (this.selectedFeatures.indexOf(target) === -1) {
                    layer.leafletLayer.resetStyle(target);
                }
            }
        },
        resetSelectedFeatures: function () {
            // When the map is clicked we want to reset the selected features
            var resetFeatures = GISApp.selectedFeatures.slice();
            GISApp.selectedFeatures = [];

            for (var i = 0; i < resetFeatures.length; i++) {
                var feature = resetFeatures[i];
                GISApp.resetHighlight(feature);
            }

        },
        addOrRemoveFeatureFromList: function (layer) {
            var index = this.selectedFeatures.indexOf(layer);
            if (index === -1) {
                this.selectedFeatures.push(layer);
                this.highlightFeature(layer);

            } else {
                this.selectedFeatures.splice(index, 1);
            }
        },
        toggleDialog: function (dialogName) {
            this.dialogs[dialogName] = !this.dialogs[dialogName];
        },
        clearDialogs: function () {
            for (var property in this.dialogs) {
                if (this.dialogs.hasOwnProperty(property)) {
                    this.dialogs[property] = false;
                }
            }
        },
        deleteSelectedLayers: function () {
            for (var i = 0; i < this.layers.length; i++) {
                var layer = this.layers[i];
                if (!layer.checked || !layer.user) continue;
                this.map.removeLayer(layer.leafletLayer);

                // Remove the layer from the layers list
                this.layers.splice(i, 1);
                this.deleteLayer(layer);
            }
        },
        bringSelectedLayersToFront: function () {
            for (var i = 0; i < this.layers.length; i++) {
                var layer = this.layers[i];
                if (!layer.checked) continue;
                var lf = layer.leafletLayer;
                lf.bringToFront();
            }
        },
        setFile: function (e) {
            var file = e.target.files[0];
            this.file = file;
        },
        addLayerFromFile: function () {
            if (!this.file) return;

            var fileReader = new FileReader();
            if (this.file.name.split('.')[1] == 'zip') {
                fileReader.onload = function () {
                    shp(this.result).then(function (geojson) {
                        console.log(geojson);
                        GISApp.toggleDialog('upload');
                        GISApp.importJson(geojson, GISApp.newLayerName);
                    });
                };
                fileReader.readAsArrayBuffer(this.file);
            }
            else if (this.file.name.split('.')[1] == 'geojson') {
                fileReader.onload = function () {
                    var geojson = JSON.parse(this.result);
                    console.log(geojson);
                    GISApp.toggleDialog('upload');
                    GISApp.importJson(geojson, GISApp.newLayerName);
                };
                fileReader.readAsText(this.file);
            }
        },
        handleError: function () {

        }
    }
});
<commit_msg>popup opens on click<commit_after>/**
 * Created by rubenschmidt on 26.12.2016.
 */
var GISApp = new Vue({
    el: '#gisapp',
    // Custom delimiters so we do not interfere with django natives.
    delimiters: ["[[", "]]"],
    // Add the gisoperationsmixin so we can use the operations api.
    mixins: [gisOperationsMixin],
    data: {
        defaultStyle: {
            "color": "#4b7eff",
            "weight": 5,
            "opacity": 1,
            "fillOpacity": 0.7
        },
        newLayerName: '',
        loadingLayers: false,
        file: null,
        bufferSize: null,
        layers: [],
        selectedFeatures: [],
        lineStringLayer: null,
        polygonLayer: null,
        geoJson: null,
        map: null,
        dialogs: {
            'buffer': false,
            'intersect': false,
            'completed': false,
            'mergeSelected': false,
            'union': false,
            'difference': false,
            'upload': false,
            'error': false
        },
        operations: []

    },
    mounted: function () {
        // When the app is ready. Add the map.
        this.map = L.map('map').setView([0, 0], 2);

        // Add OSM tilelayer as basemap.
        L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
            attribution: '© OpenStreetMap contributors'
        }).addTo(this.map);

        this.map.on('click', function (e) {
            GISApp.resetSelectedFeatures();
        });
    },
    computed: {
        selectedLayers: function () {
            var layers = [];
            for (var i = 0; i < this.layers.length; i++) {
                var obj = this.layers[i];
                if (obj.checked) layers.push(obj);
            }
            return layers
        }
    },
    methods: {
        setCenter: function (lat, lng, zoom) {
            this.map.setView([lat, lng], zoom)
        },
        addData: function (layers) {
            for (var i = 0; i < layers.length; i++) {
                var layer = layers[i];

                var style = {
                    "color": this.getRandomColor(),
                    "weight": 5,
                    "opacity": 1,
                    "fillOpacity": 0.7
                };
                var geoJson = L.geoJSON(layer.points.features, {
                    style: style,
                    onEachFeature: this.onEachFeature
                })
                geoJson.addData(layer.polygons.features);
                geoJson.addData(layer.linestrings.features);
                layer.leafletLayer = geoJson;
                layer.checked = false;
                geoJson.addTo(this.map);
            }
            this.layers = this.layers.concat(layers);
        },
        getRandomColor: function () {
            var letters = '0123456789ABCDEF'.split('');
            var color = '#';
            for (var i = 0; i < 6; i++) {
                color += letters[Math.round(Math.random() * 15)];
            }
            return color;
        },
        onEachFeature: function (feature, layer) {

            var props = feature.properties;
            if (props) {
                var body = "
";
                for (var key in props) {
                    if (props.hasOwnProperty(key)) {
                        body +=
                            ('
' + key + '	' + props[key] + '
');
                    }
                }
                body += "
";
                layer.bindPopup(body);
            }
            //bind click and mouse events.
            layer.on({
                click: this.whenClicked,
                mouseover: this.onMouseOver,
                mouseout: this.onMouseOut
            });
        },
        whenClicked: function (e) {
            // Stop propagation so only the feature click is fired and not the map click.
            L.DomEvent.stopPropagation(e);
            e.target.openPopup();
            this.addOrRemoveFeatureFromList(e.target);
        },

        onMouseOver: function (e) {
            this.highlightFeature(e.target);
        },
        onMouseOut: function (e) {
            e.target.closePopup();
            this.resetHighlight(e.target);
        },
        highlightFeature: function (layer) {
            if (layer._icon) {
                // Points cant be resized stock
                // TODO implement
            } else {
                layer.setStyle({
                    weight: 5,
                    color: '#23c6ff',
                    dashArray: '',
                    fillOpacity: 0.7
                });
            }
        },
        resetHighlight: function (target) {
            for (var i = 0; i < this.layers.length; i++) {
                var layer = this.layers[i];
                if (this.selectedFeatures.indexOf(target) === -1) {
                    layer.leafletLayer.resetStyle(target);
                }
            }
        },
        resetSelectedFeatures: function () {
            // When the map is clicked we want to reset the selected features
            var resetFeatures = GISApp.selectedFeatures.slice();
            GISApp.selectedFeatures = [];

            for (var i = 0; i < resetFeatures.length; i++) {
                var feature = resetFeatures[i];
                GISApp.resetHighlight(feature);
            }

        },
        addOrRemoveFeatureFromList: function (layer) {
            var index = this.selectedFeatures.indexOf(layer);
            if (index === -1) {
                this.selectedFeatures.push(layer);
                this.highlightFeature(layer);

            } else {
                this.selectedFeatures.splice(index, 1);
            }
        },
        toggleDialog: function (dialogName) {
            this.dialogs[dialogName] = !this.dialogs[dialogName];
        },
        clearDialogs: function () {
            for (var property in this.dialogs) {
                if (this.dialogs.hasOwnProperty(property)) {
                    this.dialogs[property] = false;
                }
            }
        },
        deleteSelectedLayers: function () {
            for (var i = 0; i < this.layers.length; i++) {
                var layer = this.layers[i];
                if (!layer.checked || !layer.user) continue;
                this.map.removeLayer(layer.leafletLayer);

                // Remove the layer from the layers list
                this.layers.splice(i, 1);
                this.deleteLayer(layer);
            }
        },
        bringSelectedLayersToFront: function () {
            for (var i = 0; i < this.layers.length; i++) {
                var layer = this.layers[i];
                if (!layer.checked) continue;
                var lf = layer.leafletLayer;
                lf.bringToFront();
            }
        },
        setFile: function (e) {
            var file = e.target.files[0];
            this.file = file;
        },
        addLayerFromFile: function () {
            if (!this.file) return;

            var fileReader = new FileReader();
            if (this.file.name.split('.')[1] == 'zip') {
                fileReader.onload = function () {
                    shp(this.result).then(function (geojson) {
                        console.log(geojson);
                        GISApp.toggleDialog('upload');
                        GISApp.importJson(geojson, GISApp.newLayerName);
                    });
                };
                fileReader.readAsArrayBuffer(this.file);
            }
            else if (this.file.name.split('.')[1] == 'geojson') {
                fileReader.onload = function () {
                    var geojson = JSON.parse(this.result);
                    console.log(geojson);
                    GISApp.toggleDialog('upload');
                    GISApp.importJson(geojson, GISApp.newLayerName);
                };
                fileReader.readAsText(this.file);
            }
        },
        handleError: function () {

        }
    }
});
<|endoftext|>


<commit_before>/*
 * Swipe 1.0
 *
 * Brad Birdsall, Prime
 * Copyright 2011, Licensed GPL & MIT
 *
*/

window.Swipe = function(element, options) {

  // return immediately if element doesn't exist
  if (!element) return null;

  var _this = this;

  // retreive options
  this.options = options || {};
  this.index = this.options.startSlide || 0;
  this.speed = this.options.speed || 300;
  this.callback = this.options.callback || function() {};
  this.delay = this.options.auto || 0;

  // reference dom elements
  this.container = element;
  this.element = this.container.children[0]; // the slide pane

  // static css
  this.container.style.overflow = 'hidden';
  this.element.style.listStyle = 'none';

  // trigger slider initialization
  this.setup();

  // begin auto slideshow
  this.begin();

  // add event listeners
  if (this.element.addEventListener) {
    this.element.addEventListener('touchstart', this, false);
    this.element.addEventListener('touchmove', this, false);
    this.element.addEventListener('touchend', this, false);
    this.element.addEventListener('webkitTransitionEnd', this, false);
    this.element.addEventListener('msTransitionEnd', this, false);
    this.element.addEventListener('oTransitionEnd', this, false);
    this.element.addEventListener('transitionend', this, false);
    window.addEventListener('resize', this, false);
  }

};

Swipe.prototype = {

  setup: function() {

    // get and measure amt of slides
    this.slides = this.element.children;
    this.length = this.slides.length;

    // return immediately if their are less than two slides
    if (this.length < 2) return null;

    // determine width of each slide
    this.width = this.container.getBoundingClientRect().width;

    // return immediately if measurement fails
    if (!this.width) return null;

    // hide slider element but keep positioning during setup
    this.container.style.visibility = 'hidden';

    // dynamic css
    this.element.style.width = (this.slides.length * this.width) + 'px';
    var index = this.slides.length;
    while (index--) {
      var el = this.slides[index];
      el.style.width = this.width + 'px';
      el.style.display = 'table-cell';
      el.style.verticalAlign = 'top';
    }

    // set start position and force translate to remove initial flickering
    this.slide(this.index, 0);

    // show slider element
    this.container.style.visibility = 'visible';

  },

  slide: function(index, duration) {

    var style = this.element.style;

    // fallback to default speed
    if (duration == undefined) {
        duration = this.speed;
    }

    // set duration speed (0 represents 1-to-1 scrolling)
    style.webkitTransitionDuration = style.MozTransitionDuration = style.msTransitionDuration = style.OTransitionDuration = style.transitionDuration = duration + 'ms';

    // translate to given index position
    style.MozTransform = style.webkitTransform = 'translate3d(' + -(index * this.width) + 'px,0,0)';
    style.msTransform = style.OTransform = 'translateX(' + -(index * this.width) + 'px)';

    // set new index to allow for expression arguments
    this.index = index;

  },

  getPos: function() {

    // return current index position
    return this.index;

  },

  prev: function(delay) {

    // cancel next scheduled automatic transition, if any
    this.delay = delay || 0;
    clearTimeout(this.interval);

    // if not at first slide
    if (this.index) this.slide(this.index-1, this.speed);

  },

  next: function(delay) {

    // cancel next scheduled automatic transition, if any
    this.delay = delay || 0;
    clearTimeout(this.interval);

    if (this.index < this.length - 1) this.slide(this.index+1, this.speed); // if not last slide
    else this.slide(0, this.speed); //if last slide return to start

  },

  begin: function() {

    var _this = this;

    this.interval = (this.delay)
      ? setTimeout(function() {
        _this.next(_this.delay);
      }, this.delay)
      : 0;

  },

  stop: function() {
    this.delay = 0;
    clearTimeout(this.interval);
  },

  resume: function() {
    this.delay = this.options.auto || 0;
    this.begin();
  },

  handleEvent: function(e) {
    switch (e.type) {
      case 'touchstart': this.onTouchStart(e); break;
      case 'touchmove': this.onTouchMove(e); break;
      case 'touchend': this.onTouchEnd(e); break;
      case 'webkitTransitionEnd':
      case 'msTransitionEnd':
      case 'oTransitionEnd':
      case 'transitionend': this.transitionEnd(e); break;
      case 'resize': this.setup(); break;
    }
  },

  transitionEnd: function(e) {

    if (this.delay) this.begin();

    this.callback(e, this.index, this.slides[this.index]);

  },

  onTouchStart: function(e) {

    this.start = {

      // get touch coordinates for delta calculations in onTouchMove
      pageX: e.touches[0].pageX,
      pageY: e.touches[0].pageY,

      // set initial timestamp of touch sequence
      time: Number( new Date() )

    };

    // used for testing first onTouchMove event
    this.isScrolling = undefined;

    // reset deltaX
    this.deltaX = 0;

    // set transition time to 0 for 1-to-1 touch movement
    this.element.style.MozTransitionDuration = this.element.style.webkitTransitionDuration = 0;

  },

  onTouchMove: function(e) {

    // ensure swiping with one touch and not pinching
    if(e.touches.length > 1 || e.scale && e.scale !== 1) return;

    this.deltaX = e.touches[0].pageX - this.start.pageX;

    // determine if scrolling test has run - one time test
    if ( typeof this.isScrolling == 'undefined') {
      this.isScrolling = !!( this.isScrolling || Math.abs(this.deltaX) < Math.abs(e.touches[0].pageY - this.start.pageY) );
    }

    // if user is not trying to scroll vertically
    if (!this.isScrolling) {

      // prevent native scrolling
      e.preventDefault();

      // cancel slideshow
      clearTimeout(this.interval);

      // increase resistance if first or last slide
      this.deltaX =
        this.deltaX /
          ( (!this.index && this.deltaX > 0               // if first slide and sliding left
            || this.index == this.length - 1              // or if last slide and sliding right
            && this.deltaX < 0                            // and if sliding at all
          ) ?
          ( Math.abs(this.deltaX) / this.width + 1 )      // determine resistance level
          : 1 );                                          // no resistance if false

      // translate immediately 1-to-1
      this.element.style.MozTransform = this.element.style.webkitTransform = 'translate3d(' + (this.deltaX - this.index * this.width) + 'px,0,0)';

    }

  },

  onTouchEnd: function(e) {

    // determine if slide attempt triggers next/prev slide
    var isValidSlide =
          Number(new Date()) - this.start.time < 250      // if slide duration is less than 250ms
          && Math.abs(this.deltaX) > 20                   // and if slide amt is greater than 20px
          || Math.abs(this.deltaX) > this.width/2,        // or if slide amt is greater than half the width

    // determine if slide attempt is past start and end
        isPastBounds =
          !this.index && this.deltaX > 0                          // if first slide and slide amt is greater than 0
          || this.index == this.length - 1 && this.deltaX < 0;    // or if last slide and slide amt is less than 0

    // if not scrolling vertically
    if (!this.isScrolling) {

      // call slide function with slide end value based on isValidSlide and isPastBounds tests
      this.slide( this.index + ( isValidSlide && !isPastBounds ? (this.deltaX < 0 ? 1 : -1) : 0 ), this.speed );

    }

  }

};
<commit_msg>Bug fix on iOS 3 that does not support getBoundingClientRec method<commit_after>/*
 * Swipe 1.0
 *
 * Brad Birdsall, Prime
 * Copyright 2011, Licensed GPL & MIT
 *
*/

window.Swipe = function(element, options) {

  // return immediately if element doesn't exist
  if (!element) return null;

  var _this = this;

  // retreive options
  this.options = options || {};
  this.index = this.options.startSlide || 0;
  this.speed = this.options.speed || 300;
  this.callback = this.options.callback || function() {};
  this.delay = this.options.auto || 0;

  // reference dom elements
  this.container = element;
  this.element = this.container.children[0]; // the slide pane

  // static css
  this.container.style.overflow = 'hidden';
  this.element.style.listStyle = 'none';

  // trigger slider initialization
  this.setup();

  // begin auto slideshow
  this.begin();

  // add event listeners
  if (this.element.addEventListener) {
    this.element.addEventListener('touchstart', this, false);
    this.element.addEventListener('touchmove', this, false);
    this.element.addEventListener('touchend', this, false);
    this.element.addEventListener('webkitTransitionEnd', this, false);
    this.element.addEventListener('msTransitionEnd', this, false);
    this.element.addEventListener('oTransitionEnd', this, false);
    this.element.addEventListener('transitionend', this, false);
    window.addEventListener('resize', this, false);
  }

};

Swipe.prototype = {

  setup: function() {

    // get and measure amt of slides
    this.slides = this.element.children;
    this.length = this.slides.length;

    // return immediately if their are less than two slides
    if (this.length < 2) return null;

    // determine width of each slide
    if("getBoundingClientRect" in this.container) {
        this.width = this.container.getBoundingClientRect().width ;
    }else {
        this.width = this.container.offsetWidth;    //http://help.dottoro.com/ljvmcrrn.php
    }

    // return immediately if measurement fails
    if (!this.width) return null;

    // hide slider element but keep positioning during setup
    this.container.style.visibility = 'hidden';

    // dynamic css
    this.element.style.width = (this.slides.length * this.width) + 'px';
    var index = this.slides.length;
    while (index--) {
      var el = this.slides[index];
      el.style.width = this.width + 'px';
      el.style.display = 'table-cell';
      el.style.verticalAlign = 'top';
    }

    // set start position and force translate to remove initial flickering
    this.slide(this.index, 0);

    // show slider element
    this.container.style.visibility = 'visible';

  },

  slide: function(index, duration) {

    var style = this.element.style;

    // fallback to default speed
    if (duration == undefined) {
        duration = this.speed;
    }

    // set duration speed (0 represents 1-to-1 scrolling)
    style.webkitTransitionDuration = style.MozTransitionDuration = style.msTransitionDuration = style.OTransitionDuration = style.transitionDuration = duration + 'ms';

    // translate to given index position
    style.MozTransform = style.webkitTransform = 'translate3d(' + -(index * this.width) + 'px,0,0)';
    style.msTransform = style.OTransform = 'translateX(' + -(index * this.width) + 'px)';

    // set new index to allow for expression arguments
    this.index = index;

  },

  getPos: function() {

    // return current index position
    return this.index;

  },

  prev: function(delay) {

    // cancel next scheduled automatic transition, if any
    this.delay = delay || 0;
    clearTimeout(this.interval);

    // if not at first slide
    if (this.index) this.slide(this.index-1, this.speed);

  },

  next: function(delay) {

    // cancel next scheduled automatic transition, if any
    this.delay = delay || 0;
    clearTimeout(this.interval);

    if (this.index < this.length - 1) this.slide(this.index+1, this.speed); // if not last slide
    else this.slide(0, this.speed); //if last slide return to start

  },

  begin: function() {

    var _this = this;

    this.interval = (this.delay)
      ? setTimeout(function() {
        _this.next(_this.delay);
      }, this.delay)
      : 0;

  },

  stop: function() {
    this.delay = 0;
    clearTimeout(this.interval);
  },

  resume: function() {
    this.delay = this.options.auto || 0;
    this.begin();
  },

  handleEvent: function(e) {
    switch (e.type) {
      case 'touchstart': this.onTouchStart(e); break;
      case 'touchmove': this.onTouchMove(e); break;
      case 'touchend': this.onTouchEnd(e); break;
      case 'webkitTransitionEnd':
      case 'msTransitionEnd':
      case 'oTransitionEnd':
      case 'transitionend': this.transitionEnd(e); break;
      case 'resize': this.setup(); break;
    }
  },

  transitionEnd: function(e) {

    if (this.delay) this.begin();

    this.callback(e, this.index, this.slides[this.index]);

  },

  onTouchStart: function(e) {

    this.start = {

      // get touch coordinates for delta calculations in onTouchMove
      pageX: e.touches[0].pageX,
      pageY: e.touches[0].pageY,

      // set initial timestamp of touch sequence
      time: Number( new Date() )

    };

    // used for testing first onTouchMove event
    this.isScrolling = undefined;

    // reset deltaX
    this.deltaX = 0;

    // set transition time to 0 for 1-to-1 touch movement
    this.element.style.MozTransitionDuration = this.element.style.webkitTransitionDuration = 0;

  },

  onTouchMove: function(e) {

    // ensure swiping with one touch and not pinching
    if(e.touches.length > 1 || e.scale && e.scale !== 1) return;

    this.deltaX = e.touches[0].pageX - this.start.pageX;

    // determine if scrolling test has run - one time test
    if ( typeof this.isScrolling == 'undefined') {
      this.isScrolling = !!( this.isScrolling || Math.abs(this.deltaX) < Math.abs(e.touches[0].pageY - this.start.pageY) );
    }

    // if user is not trying to scroll vertically
    if (!this.isScrolling) {

      // prevent native scrolling
      e.preventDefault();

      // cancel slideshow
      clearTimeout(this.interval);

      // increase resistance if first or last slide
      this.deltaX =
        this.deltaX /
          ( (!this.index && this.deltaX > 0               // if first slide and sliding left
            || this.index == this.length - 1              // or if last slide and sliding right
            && this.deltaX < 0                            // and if sliding at all
          ) ?
          ( Math.abs(this.deltaX) / this.width + 1 )      // determine resistance level
          : 1 );                                          // no resistance if false

      // translate immediately 1-to-1
      this.element.style.MozTransform = this.element.style.webkitTransform = 'translate3d(' + (this.deltaX - this.index * this.width) + 'px,0,0)';

    }

  },

  onTouchEnd: function(e) {

    // determine if slide attempt triggers next/prev slide
    var isValidSlide =
          Number(new Date()) - this.start.time < 250      // if slide duration is less than 250ms
          && Math.abs(this.deltaX) > 20                   // and if slide amt is greater than 20px
          || Math.abs(this.deltaX) > this.width/2,        // or if slide amt is greater than half the width

    // determine if slide attempt is past start and end
        isPastBounds =
          !this.index && this.deltaX > 0                          // if first slide and slide amt is greater than 0
          || this.index == this.length - 1 && this.deltaX < 0;    // or if last slide and slide amt is less than 0

    // if not scrolling vertically
    if (!this.isScrolling) {

      // call slide function with slide end value based on isValidSlide and isPastBounds tests
      this.slide( this.index + ( isValidSlide && !isPastBounds ? (this.deltaX < 0 ? 1 : -1) : 0 ), this.speed );

    }

  }

};
<|endoftext|>