<commit_before>var spinner;
var sourcesSelect;
var mangaGrid;
var scrollBox;
var searchBox;

var loginDialog;
var loginDialogTitle;
var loginDialogUsername;
var loginDialogPassword;
var loginDialogClose;
var loginDialogLogin;
var dialogSpinner;

var currentRequest = null;
var currentSources = [];

var typingTimer;
var doneTypingInterval = 250;

var scrollEndPadding = 1000;

var searchState;
function resetSearchState() {
    searchState = {
        query: null,
        lastUrl: null,
        page: 1
    };
}
resetSearchState();

function onLoad() {
    spinner = $(".loading_spinner");
    sourcesSelect = $("#sources_select");
    mangaGrid = $("#manga_grid");
    scrollBox = $("#page_wrapper");
    searchBox = $("#search_box");

    loginDialog = $("#login_dialog");
    loginDialogTitle = $("#login_dialog_title");
    loginDialogUsername = $("#login_dialog_username");
    loginDialogPassword = $("#login_dialog_password");
    loginDialogClose = $("#login_dialog_close");
    loginDialogLogin = $("#login_dialog_login");
    dialogSpinner = $("#login_loading_spinner");

    setupLoginDialog();
    setupSourcesSelect();
    setupScrollBox();
    setupSearchBox();
    refreshSources();
}

function setupLoginDialog() {
    if (!rawElement(loginDialog).showModal) {
        dialogPolyfill.registerDialog(rawElement(loginDialog));
    }
    loginDialogClose.click(function() {
        rawElement(loginDialog).close();
    });
    loginDialogLogin.click(function() {
        loginDialogClose.prop("disabled", true);
        loginDialogLogin.prop("disabled", true);
        loginDialogUsername.prop("disabled", true);
        loginDialogPassword.prop("disabled", true);
        dialogSpinner.css("display", "initial");
        var xhr = new XMLHttpRequest();
        xhr.open("GET", buildLoginUrl(), true);
        xhr.onload = function () {
            try {
                var res = JSON.parse(xhr.responseText);
                if (res.success) {
                    refreshSources();
                } else {
                    sourceLoginError(res.error);
                    selectLoggedInSource();
                }
            } catch (e) {
                sourceLoginError("Unknown Javascript error");
                console.error(e);
                selectLoggedInSource();
            }
            rawElement(loginDialog).close();
        };
        xhr.onerror = function () {
            sourceLoginError("Unknown error");
            rawElement(loginDialog).close();
            selectLoggedInSource();
        };
        xhr.send();
    })
}

function buildLoginUrl() {
    return sourceLoginRoot + "/" + rawElement(sourcesSelect).value + "?username=" + encodeURIComponent(loginDialogUsername.val()) + "&password=" + encodeURIComponent(loginDialogPassword);
}

function setupSearchBox() {
    /** http://stackoverflow.com/questions/4220126/run-javascript-function-when-user-finishes-typing-instead-of-on-key-up **/
    searchBox.on("keyup", function() {
        clearTimeout(typingTimer);
        typingTimer = setTimeout(performSearch, doneTypingInterval);
    });
    searchBox.on("keydown", function() {
        clearTimeout(typingTimer);
    });
}

function performSearch() {
    searchState.page = 1;
    searchState.lastUrl = null;
    var searchText = rawElement(searchBox).value;
    if(searchText.trim() !== "") {
        searchState.query = searchText;
    } else {
        //Set to null if no query
        searchState.query = null;
    }
    scrollBox.scrollTop(0);
    clearElement(mangaGrid);
    refreshCatalogue();
}

function setupScrollBox() {
    scrollBox.on('scroll', function() {
        if(scrollBox.scrollTop() + scrollBox.innerHeight() >= rawElement(scrollBox).scrollHeight - scrollEndPadding) {
            if(hasNextPage() && !isRefreshing()) {
                searchState.page++;
                refreshCatalogue();
            }
        }
    });
}

function selectLoggedInSource() {
    for(var i = 0; i < currentSources.length; i++) {
        var source = currentSources[i];
        if(isLoggedIn(source)) {
            selectSource(source);
            refreshCatalogue();
            return;
        }
    }
}

function selectSource(source) {
    var rawSourcesSelect = rawElement(sourcesSelect);
    for ( var i = 0; i < rawSourcesSelect.options.length; i++ ) {
        if ( rawSourcesSelect.options[i].value == source.id ) {
            rawElement(rawSourcesSelect).selectedIndex = i;
            return;
        }
    }
}

function isLoggedIn(source) {
    if(!valid(source["logged_in"])) {
        return true;
    }
    return source["logged_in"];
}

function setupSourcesSelect() {
    sourcesSelect.change(function() {
        var selectedSource = getCurrentSource();
        if(valid(selectedSource) && !isLoggedIn(selectedSource)) {
            showLoginBox(selectedSource);
        } else {
            searchState.page = 1;
            searchState.lastUrl = null;
            scrollBox.scrollTop(0);
            clearElement(mangaGrid);
            refreshCatalogue();
        }
    });
}

function showLoginBox(source) {
    loginDialogTitle.text(source.name + " Login");
    loginDialogUsername.val("");
    loginDialogPassword.val("");
    loginDialogClose.prop('disabled', false);
    loginDialogLogin.prop('disabled', false);
    loginDialogUsername.prop("disabled", false);
    loginDialogPassword.prop("disabled", false);
    loginDialog.data("source", source);
    dialogSpinner.css("display", "");
    rawElement(loginDialog).showModal();
}

function getCurrentSource() {
    var currentSourceID = parseInt(rawElement(sourcesSelect).value);
    for(var i = 0; i < currentSources.length; i++) {
        var currentSource = currentSources[i];
        if(currentSource.id === currentSourceID) {
            return currentSource;
        }
    }
    return null;
}

function showSpinner() {
    spinner.css("opacity", 1);
}

function hideSpinner() {
    spinner.css("opacity", 0);
}

function refreshSources() {
    showSpinner();
    var xhr = new XMLHttpRequest();
    xhr.open("GET", sourcesRoot, true);
    xhr.onload = function () {
        try {
            var res = JSON.parse(xhr.responseText);
            if (res.success) {
                currentSources = res.content;
                updateSourcesUI();
                selectLoggedInSource();
            } else {
                sourcesRefreshError();
            }
        } catch (e) {
            console.error(e);
            sourcesRefreshError();
        }
        hideSpinner();
    };
    xhr.onerror = function () {
        sourcesRefreshError();
        hideSpinner();
    };
    xhr.send();
}

function buildCatalogueURL() {
    var currentUrl = catalogueRoot + "/" + rawElement(sourcesSelect).value + "/" + searchState.page;
    var usedQuestionMark = false;
    if(valid(searchState.lastUrl)) {
        currentUrl += usedQuestionMark ? "&" : "?";
        currentUrl += "lurl=" + encodeURIComponent(searchState.lastUrl);
        usedQuestionMark = true;
    }
    if(valid(searchState.query)) {
        currentUrl += usedQuestionMark ? "&" : "?";
        currentUrl += "query=" + encodeURIComponent(searchState.query);
    }
    return currentUrl;
}
function isRefreshing() {
    return valid(currentRequest) && !currentRequest.completed;
}

function hasNextPage() {
    return !!(valid(searchState.lastUrl) && searchState.lastUrl !== "");
}

//TODO Pages and search
function refreshCatalogue(oldRequest) {
    var request;
    if (valid(oldRequest)) {
        request = oldRequest;
    } else {
        request = new Request();
    }
    if(currentRequest === request) {
        currentRequest.cancel();
    }
    request.completed = false;
    currentRequest = request;
    showSpinner();
    var xhr = new XMLHttpRequest();
    xhr.open("GET", buildCatalogueURL(), true);
    xhr.onload = function () {
        if (request.canceled) {
            return;
        }
        try {
            var res = JSON.parse(xhr.responseText);
            if(res.success) {
                //Clear catalogue if page 1
                if(searchState.page === 1) {
                    clearElement(mangaGrid);
                }
                //Set new search state
                searchState.lastUrl = res.lurl;
                //Add on new manga
                updateCatalogueUI(res.content);
            } else {
                catalogueRefreshError(request);
            }
        }
        catch (e) {
            console.error(e);
            catalogueRefreshError(request);
        }
        hideSpinner();
        request.completed = true;
    };
    xhr.onerror = function () {
        if (request.canceled) {
            return;
        }
        catalogueRefreshError(request);
        hideSpinner();
        request.completed = true;
    };
    xhr.send();
    return request;
}

function updateSourcesUI() {
    clearElement(sourcesSelect);
    $.each(currentSources, function (index, value) {
        sourcesSelect.append($('<option/>', {
            value: value.id,
            text : value.name
        }));
    });
}

function updateCatalogueUI(manga) {
    $.each(manga, function (index, value) {
        appendManga(value, mangaGrid, true);
    });
}

/**
 * Basic cancelable request
 **/
function Request() {
    var that = this;
    this.canceled = false;
    this.cancel = function () {
        that.canceled = true;
    };
    this.completed = false;
}

function sourcesRefreshError() {
    snackbar.showSnackbar({
        message: "Error getting sources!",
        timeout: 2000,
        actionText: "Retry",
        actionHandler: function () {
            refreshSources();
        }
    });
}

function catalogueRefreshError(request) {
    snackbar.showSnackbar({
        message: "Error getting catalogue!",
        timeout: 2000,
        actionText: "Retry",
        actionHandler: function () {
            refreshCatalogue(request);
        }
    });
}

function sourceLoginError(message) {
    snackbar.showSnackbar({
        message: "Error logging in (" + message + ")!",
        timeout: 2000
    });
}<commit_msg>Cancelling log in now selects a logged source.<commit_after>var spinner;
var sourcesSelect;
var mangaGrid;
var scrollBox;
var searchBox;

var loginDialog;
var loginDialogTitle;
var loginDialogUsername;
var loginDialogPassword;
var loginDialogClose;
var loginDialogLogin;
var dialogSpinner;

var currentRequest = null;
var currentSources = [];

var typingTimer;
var doneTypingInterval = 250;

var scrollEndPadding = 1000;

var searchState;
function resetSearchState() {
    searchState = {
        query: null,
        lastUrl: null,
        page: 1
    };
}
resetSearchState();

function onLoad() {
    spinner = $(".loading_spinner");
    sourcesSelect = $("#sources_select");
    mangaGrid = $("#manga_grid");
    scrollBox = $("#page_wrapper");
    searchBox = $("#search_box");

    loginDialog = $("#login_dialog");
    loginDialogTitle = $("#login_dialog_title");
    loginDialogUsername = $("#login_dialog_username");
    loginDialogPassword = $("#login_dialog_password");
    loginDialogClose = $("#login_dialog_close");
    loginDialogLogin = $("#login_dialog_login");
    dialogSpinner = $("#login_loading_spinner");

    setupLoginDialog();
    setupSourcesSelect();
    setupScrollBox();
    setupSearchBox();
    refreshSources();
}

function setupLoginDialog() {
    if (!rawElement(loginDialog).showModal) {
        dialogPolyfill.registerDialog(rawElement(loginDialog));
    }
    loginDialogClose.click(function() {
        rawElement(loginDialog).close();
        selectLoggedInSource();
    });
    loginDialogLogin.click(function() {
        loginDialogClose.prop("disabled", true);
        loginDialogLogin.prop("disabled", true);
        loginDialogUsername.prop("disabled", true);
        loginDialogPassword.prop("disabled", true);
        dialogSpinner.css("display", "initial");
        var xhr = new XMLHttpRequest();
        xhr.open("GET", buildLoginUrl(), true);
        xhr.onload = function () {
            try {
                var res = JSON.parse(xhr.responseText);
                if (res.success) {
                    refreshSources();
                } else {
                    sourceLoginError(res.error);
                    selectLoggedInSource();
                }
            } catch (e) {
                sourceLoginError("Unknown Javascript error");
                console.error(e);
                selectLoggedInSource();
            }
            rawElement(loginDialog).close();
        };
        xhr.onerror = function () {
            sourceLoginError("Unknown error");
            rawElement(loginDialog).close();
            selectLoggedInSource();
        };
        xhr.send();
    })
}

function buildLoginUrl() {
    return sourceLoginRoot + "/" + rawElement(sourcesSelect).value + "?username=" + encodeURIComponent(loginDialogUsername.val()) + "&password=" + encodeURIComponent(loginDialogPassword);
}

function setupSearchBox() {
    /** http://stackoverflow.com/questions/4220126/run-javascript-function-when-user-finishes-typing-instead-of-on-key-up **/
    searchBox.on("keyup", function() {
        clearTimeout(typingTimer);
        typingTimer = setTimeout(performSearch, doneTypingInterval);
    });
    searchBox.on("keydown", function() {
        clearTimeout(typingTimer);
    });
}

function performSearch() {
    searchState.page = 1;
    searchState.lastUrl = null;
    var searchText = rawElement(searchBox).value;
    if(searchText.trim() !== "") {
        searchState.query = searchText;
    } else {
        //Set to null if no query
        searchState.query = null;
    }
    scrollBox.scrollTop(0);
    clearElement(mangaGrid);
    refreshCatalogue();
}

function setupScrollBox() {
    scrollBox.on('scroll', function() {
        if(scrollBox.scrollTop() + scrollBox.innerHeight() >= rawElement(scrollBox).scrollHeight - scrollEndPadding) {
            if(hasNextPage() && !isRefreshing()) {
                searchState.page++;
                refreshCatalogue();
            }
        }
    });
}

function selectLoggedInSource() {
    for(var i = 0; i < currentSources.length; i++) {
        var source = currentSources[i];
        if(isLoggedIn(source)) {
            selectSource(source);
            refreshCatalogue();
            return;
        }
    }
}

function selectSource(source) {
    var rawSourcesSelect = rawElement(sourcesSelect);
    for ( var i = 0; i < rawSourcesSelect.options.length; i++ ) {
        if ( rawSourcesSelect.options[i].value == source.id ) {
            rawElement(rawSourcesSelect).selectedIndex = i;
            return;
        }
    }
}

function isLoggedIn(source) {
    if(!valid(source["logged_in"])) {
        return true;
    }
    return source["logged_in"];
}

function setupSourcesSelect() {
    sourcesSelect.change(function() {
        var selectedSource = getCurrentSource();
        if(valid(selectedSource) && !isLoggedIn(selectedSource)) {
            showLoginBox(selectedSource);
        } else {
            searchState.page = 1;
            searchState.lastUrl = null;
            scrollBox.scrollTop(0);
            clearElement(mangaGrid);
            refreshCatalogue();
        }
    });
}

function showLoginBox(source) {
    loginDialogTitle.text(source.name + " Login");
    loginDialogUsername.val("");
    loginDialogPassword.val("");
    loginDialogClose.prop('disabled', false);
    loginDialogLogin.prop('disabled', false);
    loginDialogUsername.prop("disabled", false);
    loginDialogPassword.prop("disabled", false);
    loginDialog.data("source", source);
    dialogSpinner.css("display", "");
    rawElement(loginDialog).showModal();
}

function getCurrentSource() {
    var currentSourceID = parseInt(rawElement(sourcesSelect).value);
    for(var i = 0; i < currentSources.length; i++) {
        var currentSource = currentSources[i];
        if(currentSource.id === currentSourceID) {
            return currentSource;
        }
    }
    return null;
}

function showSpinner() {
    spinner.css("opacity", 1);
}

function hideSpinner() {
    spinner.css("opacity", 0);
}

function refreshSources() {
    showSpinner();
    var xhr = new XMLHttpRequest();
    xhr.open("GET", sourcesRoot, true);
    xhr.onload = function () {
        try {
            var res = JSON.parse(xhr.responseText);
            if (res.success) {
                currentSources = res.content;
                updateSourcesUI();
                selectLoggedInSource();
            } else {
                sourcesRefreshError();
            }
        } catch (e) {
            console.error(e);
            sourcesRefreshError();
        }
        hideSpinner();
    };
    xhr.onerror = function () {
        sourcesRefreshError();
        hideSpinner();
    };
    xhr.send();
}

function buildCatalogueURL() {
    var currentUrl = catalogueRoot + "/" + rawElement(sourcesSelect).value + "/" + searchState.page;
    var usedQuestionMark = false;
    if(valid(searchState.lastUrl)) {
        currentUrl += usedQuestionMark ? "&" : "?";
        currentUrl += "lurl=" + encodeURIComponent(searchState.lastUrl);
        usedQuestionMark = true;
    }
    if(valid(searchState.query)) {
        currentUrl += usedQuestionMark ? "&" : "?";
        currentUrl += "query=" + encodeURIComponent(searchState.query);
    }
    return currentUrl;
}
function isRefreshing() {
    return valid(currentRequest) && !currentRequest.completed;
}

function hasNextPage() {
    return !!(valid(searchState.lastUrl) && searchState.lastUrl !== "");
}

//TODO Pages and search
function refreshCatalogue(oldRequest) {
    var request;
    if (valid(oldRequest)) {
        request = oldRequest;
    } else {
        request = new Request();
    }
    if(currentRequest === request) {
        currentRequest.cancel();
    }
    request.completed = false;
    currentRequest = request;
    showSpinner();
    var xhr = new XMLHttpRequest();
    xhr.open("GET", buildCatalogueURL(), true);
    xhr.onload = function () {
        if (request.canceled) {
            return;
        }
        try {
            var res = JSON.parse(xhr.responseText);
            if(res.success) {
                //Clear catalogue if page 1
                if(searchState.page === 1) {
                    clearElement(mangaGrid);
                }
                //Set new search state
                searchState.lastUrl = res.lurl;
                //Add on new manga
                updateCatalogueUI(res.content);
            } else {
                catalogueRefreshError(request);
            }
        }
        catch (e) {
            console.error(e);
            catalogueRefreshError(request);
        }
        hideSpinner();
        request.completed = true;
    };
    xhr.onerror = function () {
        if (request.canceled) {
            return;
        }
        catalogueRefreshError(request);
        hideSpinner();
        request.completed = true;
    };
    xhr.send();
    return request;
}

function updateSourcesUI() {
    clearElement(sourcesSelect);
    $.each(currentSources, function (index, value) {
        sourcesSelect.append($('<option/>', {
            value: value.id,
            text : value.name
        }));
    });
}

function updateCatalogueUI(manga) {
    $.each(manga, function (index, value) {
        appendManga(value, mangaGrid, true);
    });
}

/**
 * Basic cancelable request
 **/
function Request() {
    var that = this;
    this.canceled = false;
    this.cancel = function () {
        that.canceled = true;
    };
    this.completed = false;
}

function sourcesRefreshError() {
    snackbar.showSnackbar({
        message: "Error getting sources!",
        timeout: 2000,
        actionText: "Retry",
        actionHandler: function () {
            refreshSources();
        }
    });
}

function catalogueRefreshError(request) {
    snackbar.showSnackbar({
        message: "Error getting catalogue!",
        timeout: 2000,
        actionText: "Retry",
        actionHandler: function () {
            refreshCatalogue(request);
        }
    });
}

function sourceLoginError(message) {
    snackbar.showSnackbar({
        message: "Error logging in (" + message + ")!",
        timeout: 2000
    });
}<|endoftext|>


<commit_before>// Karma configuration
// Generated on Thu Nov 24 2016 13:10:00 GMT-0800 (PST)

module.exports = function (config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: "",

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ["mocha", "chai", "fixture"],

    // list of files / patterns to load in the browser
    files: [
      "https://code.jquery.com/jquery-1.12.4.js",
      "https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js",
      "node_modules/clipboard/dist/clipboard.js",
      "test/**/*.js"
    ],

    // list of files to exclude
    exclude: [
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ["progress"],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values:
    // config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ["Chrome", "Firefox"],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  });
};
<commit_msg>now it dies because I don't have the fixtures actually being loaded before the tests...<commit_after>// Karma configuration
// Generated on Thu Nov 24 2016 13:10:00 GMT-0800 (PST)

module.exports = function (config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: "",

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ["mocha", "chai", "fixture"],

    // list of files / patterns to load in the browser
    files: [
      "https://code.jquery.com/jquery-1.12.4.js",
      "https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js",
      "node_modules/clipboard/dist/clipboard.js",
      "add-heading-anchors.js",
      "test/**/*.js"
    ],

    // list of files to exclude
    exclude: [
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ["progress"],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values:
    // config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ["Chrome", "Firefox"],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  });
};
<|endoftext|>


<commit_before>/* globals ajax updateFrameCount dom listenCanvas canvas getState setState setMoatUI dialogPolyfill QRCode timeago*/

(function(global) {
  "use strict";

  // CONFIGURATION
  let params = new URLSearchParams(new URL(window.location).search);

  const USE_MOAT = params.has('moat');

  const MOAT_URL = window.location.host.includes('glitch') ? "https://sd-moat.glitch.me/": "http://launchpad.yourlibrary.com:34071";

  var defaultCanvas = `<svg id="canvas" width="2560px" height="1116px" data-tool="pen" data-stroke-width="2" data-do-onionskin="true" data-fps="10" data-palette="0" data-color="#000000" data-bgcolor="#FFFFFF" data-color1="#FF0000" data-color2="#FFFF00" data-color3="#00FF00" data-color4="#00FFFF" data-color5="#0000FF" data-color6="#666666" data-color7="#000000" data-color8="#FFFFFF" data-tab_file="false" data-tab_draw="true" data-tab_frames="true" data-tab_animate="false"><g class="frame selected"></g></svg>`;

  // polyfill for dialog
  const dialog = document.querySelector('dialog');
  dialogPolyfill.registerDialog(dialog);

  function saveLocal() {
    localStorage._currentWork = saveFormat();
  }

  function updateSavedState() {
    let state = getState();
    for (let key in state) {
      canvas.dataset[key] = state[key];
    }
  }

  function restoreSavedState() {
    let state = {};
    for (let key in canvas.dataset) {
      state[key] = canvas.dataset[key];
    }
    setState(state);
  }

  function saveFormat() {
    if (canvas) {
      updateSavedState();
      return canvas.outerHTML;
    } else {
      return "";
    }
  }

  window.canvas = null;

  function restoreFormat(savetext) {
    window.canvas = document.querySelector("#canvas");
    if (!canvas) {
      canvas = dom.svg("svg");
      document.body.prepend(canvas);
    }
    if (!savetext) {
      savetext = defaultCanvas;
    }
    canvas.outerHTML = savetext;
    canvas = document.querySelector("#canvas");
    updateFrameCount();
    canvas.setAttribute("width", document.body.clientWidth + "px");
    canvas.setAttribute("height", document.body.clientHeight + "px");
    listenCanvas();
    restoreSavedState();
  }

  function restore() {
    var path = location.href.split("?");
    var query = location.search;
    if (query) {
      var queryparts = query.slice(1).split("=");
      if (queryparts[0] === "gist") {
        loadScriptsFromGistId(queryparts[1]);
        return;
      }
    }
    restoreLocal();
  }

  function restoreLocal() {
    restoreFormat(localStorage._currentWork || defaultCanvas);
  }

  function clear() {
    restoreFormat(defaultCanvas);
  }

  function saveFile(evt) {
    if (evt) {
      evt.preventDefault();
    }
    var title = prompt("Save file as: ");
    if (!title) {
      return;
    }
    saveAs(saveFormat(), `${title}.svg`);
  }

  const filetypes = {
    svg: "image/svg+xml",
    png: "image/png",
    gif: "image/gif"
  };

  function saveToCallback(data, filename, cb) {
    // Callback is shaped cb(blob, filename);
    console.log('saveToCallback(%s)', filename);
    let ext = filename.split(".").pop();
    let filetype = filetypes[ext];
    if (data.toBlob) {
      // ex: canvas.toBlob()
      data.toBlob(blob => cb(blob, filename), filetype);
    } else {
      cb(new Blob([data], { type: filetype }), filename);
    }
  }

  function sendToMoat(progid) {
    console.log('sendToMoat(%s)', progid);
    saveToCallback(saveFormat(), "shimmy.svg", (blob, filename) =>
      sendToMoatCB(blob, filename, progid)
    );
  }

  function sendToMoatCB(blob, filename, progid) {
    console.log('sendToMoatCB(%s)', filename);
    let formData = new FormData();
    formData.append("program", progid);
    formData.append("file", blob, filename);
    let request = new XMLHttpRequest();
    request.open("POST", MOAT_URL + 'file/create');
    request.setRequestHeader('X-Requested-With', 'XMLHTTPRequest');
    request.send(formData);
    request.onload = () => showFilePage(request.response);
    request.onerror = () => handleError('send file');
    request.ontimeout = () => handleTimeout('send file');
  }

  function handleError(step) {
    alert("Error uploading to Moat during " + step + " step, please try again.");
  }

  function handleTimeout(step) {
    alert("Timeout uploading to Moat during " + step + ", please try again.");
  }

  function showQRCode(){
  if (document.querySelector('#qrcode')){
      let qrcode = new QRCode("qrcode", {
          text: "{{urlbase}}/file/{{id}}",
          width: 128,
          height: 128,
          colorDark: "#000000",
          colorLight: "#ffffff",
          correctLevel: QRCode.CorrectLevel.H
        });
  }
}

function updateExpires(){
  let expires = document.querySelectorAll('.expires');
  if (expires.length){
    expires.forEach(e => e.innerText = timeago.format(e.getAttribute('timestamp')));
    setTimeout(updateExpires, 1000);
  }
}

function updateDialog(){
  showQRCode();
  updateExpires();
}

  function showFilePage(res) {
    dialog.innerHTML = res;
    dialog.append(dom.html('button', {onClick: 'this.parentElement.close()'}, 'OK'));
    updateDialog();
    dialog.showModal();
  }

  function saveAs(data, filename) {
    saveToCallback(data, filename, saveBlob);
  }

  function saveBlob(blob, filename) {
    var reader = new FileReader();
    reader.onloadend = function() {
      var a = dom.html("a", {
        href: reader.result,
        download: filename,
        target: "_blank"
      });
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
    };
    reader.readAsDataURL(blob);
  }

  function readFile(file) {
    var fileName = file.name;
    if (fileName.indexOf(".svg", fileName.length - 5) === -1) {
      return alert("Not an SVG file");
    }
    var reader = new FileReader();
    reader.readAsText(file);
    reader.onload = function(evt) {
      restoreFormat(evt.target.result);
    };
  }

  function loadFile() {
    var input = dom.html("input", { type: "file", accept: "image/svg+xml" });
    if (!input) {
      return;
    }
    input.addEventListener("change", function(evt) {
      readFile(input.files[0]);
    });
    input.click();
  }

  // Save script to gist;
  function saveCurrentScriptsToGist(event) {
    event.preventDefault();
    // console.log("Saving to Gist");
    ajax.post(
      "https://api.github.com/gists",
      function(data) {
        //var raw_url = JSON.parse(data).files["script.json"].raw_url;
        gistID = JSON.parse(data)
          .url.split("/")
          .pop();
        var path = location.href.split("?")[0];
        path += "?gist=" + gistID;
        window.location = path;
      },
      JSON.stringify({
        description: "saved drawingboard file",
        public: true,
        files: {
          "animation.svg": {
            content: saveFormat()
          }
        }
      }),
      function(statusCode, x) {
        alert(
          "Can't save to Gist:\n" + statusCode + " (" + x.statusText + ") "
        );
      }
    );
  }

  var gistID = null;

  function loadScriptsFromGistId(id) {
    //we may get an event passed to this function so make sure we have a valid id or ask for one
    gistID = isNaN(parseInt(id))
      ? prompt(
          "What Gist would you like to load? Please enter the ID of the Gist: "
        )
      : id;
    if (!gistID) return;
    ajax.get(
      "https://api.github.com/gists/" + gistID,
      function(gist) {
        restoreFormat(JSON.parse(gist).files["animation.svg"].content);
      },
      function(statusCode, x) {
        alert(
          "Can't load from Gist:\n" + statusCode + " (" + x.statusText + ") "
        );
      }
    );
  }

  function newFile() {
    clear();
    onChange();
  }

  function onChange() {
    if (gistID) {
      gistID = null;
      var path = location.href.split("?")[0];
      history.replaceState(null, null, path);
    }
  }

  function queryMoat(cb) {
    fetch(MOAT_URL + "programs/?integration=shimmy").then(response =>
      response.json().then(cb)
    );
  }
  if (USE_MOAT) {
    window.addEventListener("load", e => queryMoat(setMoatUI), true);
  }else{
    document.getElementById('moat-container').remove();
  }

  window.file = {
    onChange: onChange,
    new: newFile,
    clear: clear,
    loadFile,
    saveFile,
    saveBlob,
    saveLocal,
    saveAs,
    sendToMoat
  };

  window.addEventListener("unload", saveLocal, false);
  window.addEventListener("load", restore, false);
})(window);
<commit_msg>🕷🕍 Checkpoint ./js/file.js:739936/39<commit_after>/* globals ajax updateFrameCount dom listenCanvas canvas getState setState setMoatUI dialogPolyfill QRCode timeago*/

(function(global) {
  "use strict";

  // CONFIGURATION
  let params = new URLSearchParams(new URL(window.location).search);

  const USE_MOAT = params.has('moat');

  const MOAT_URL = window.location.host.includes('glitch') ? "https://sd-moat.glitch.me/": "https://launchpad.yourlibrary.com/moat";
  console.log(MOAT_URL);

  var defaultCanvas = `<svg id="canvas" width="2560px" height="1116px" data-tool="pen" data-stroke-width="2" data-do-onionskin="true" data-fps="10" data-palette="0" data-color="#000000" data-bgcolor="#FFFFFF" data-color1="#FF0000" data-color2="#FFFF00" data-color3="#00FF00" data-color4="#00FFFF" data-color5="#0000FF" data-color6="#666666" data-color7="#000000" data-color8="#FFFFFF" data-tab_file="false" data-tab_draw="true" data-tab_frames="true" data-tab_animate="false"><g class="frame selected"></g></svg>`;

  // polyfill for dialog
  const dialog = document.querySelector('dialog');
  dialogPolyfill.registerDialog(dialog);

  function saveLocal() {
    localStorage._currentWork = saveFormat();
  }

  function updateSavedState() {
    let state = getState();
    for (let key in state) {
      canvas.dataset[key] = state[key];
    }
  }

  function restoreSavedState() {
    let state = {};
    for (let key in canvas.dataset) {
      state[key] = canvas.dataset[key];
    }
    setState(state);
  }

  function saveFormat() {
    if (canvas) {
      updateSavedState();
      return canvas.outerHTML;
    } else {
      return "";
    }
  }

  window.canvas = null;

  function restoreFormat(savetext) {
    window.canvas = document.querySelector("#canvas");
    if (!canvas) {
      canvas = dom.svg("svg");
      document.body.prepend(canvas);
    }
    if (!savetext) {
      savetext = defaultCanvas;
    }
    canvas.outerHTML = savetext;
    canvas = document.querySelector("#canvas");
    updateFrameCount();
    canvas.setAttribute("width", document.body.clientWidth + "px");
    canvas.setAttribute("height", document.body.clientHeight + "px");
    listenCanvas();
    restoreSavedState();
  }

  function restore() {
    var path = location.href.split("?");
    var query = location.search;
    if (query) {
      var queryparts = query.slice(1).split("=");
      if (queryparts[0] === "gist") {
        loadScriptsFromGistId(queryparts[1]);
        return;
      }
    }
    restoreLocal();
  }

  function restoreLocal() {
    restoreFormat(localStorage._currentWork || defaultCanvas);
  }

  function clear() {
    restoreFormat(defaultCanvas);
  }

  function saveFile(evt) {
    if (evt) {
      evt.preventDefault();
    }
    var title = prompt("Save file as: ");
    if (!title) {
      return;
    }
    saveAs(saveFormat(), `${title}.svg`);
  }

  const filetypes = {
    svg: "image/svg+xml",
    png: "image/png",
    gif: "image/gif"
  };

  function saveToCallback(data, filename, cb) {
    // Callback is shaped cb(blob, filename);
    console.log('saveToCallback(%s)', filename);
    let ext = filename.split(".").pop();
    let filetype = filetypes[ext];
    if (data.toBlob) {
      // ex: canvas.toBlob()
      data.toBlob(blob => cb(blob, filename), filetype);
    } else {
      cb(new Blob([data], { type: filetype }), filename);
    }
  }

  function sendToMoat(progid) {
    console.log('sendToMoat(%s)', progid);
    saveToCallback(saveFormat(), "shimmy.svg", (blob, filename) =>
      sendToMoatCB(blob, filename, progid)
    );
  }

  function sendToMoatCB(blob, filename, progid) {
    console.log('sendToMoatCB(%s)', filename);
    let formData = new FormData();
    formData.append("program", progid);
    formData.append("file", blob, filename);
    let request = new XMLHttpRequest();
    request.open("POST", MOAT_URL + 'file/create');
    request.setRequestHeader('X-Requested-With', 'XMLHTTPRequest');
    request.send(formData);
    request.onload = () => showFilePage(request.response);
    request.onerror = () => handleError('send file');
    request.ontimeout = () => handleTimeout('send file');
  }

  function handleError(step) {
    alert("Error uploading to Moat during " + step + " step, please try again.");
  }

  function handleTimeout(step) {
    alert("Timeout uploading to Moat during " + step + ", please try again.");
  }

  function showQRCode(){
  if (document.querySelector('#qrcode')){
      let qrcode = new QRCode("qrcode", {
          text: "{{urlbase}}/file/{{id}}",
          width: 128,
          height: 128,
          colorDark: "#000000",
          colorLight: "#ffffff",
          correctLevel: QRCode.CorrectLevel.H
        });
  }
}

function updateExpires(){
  let expires = document.querySelectorAll('.expires');
  if (expires.length){
    expires.forEach(e => e.innerText = timeago.format(e.getAttribute('timestamp')));
    setTimeout(updateExpires, 1000);
  }
}

function updateDialog(){
  showQRCode();
  updateExpires();
}

  function showFilePage(res) {
    dialog.innerHTML = res;
    dialog.append(dom.html('button', {onClick: 'this.parentElement.close()'}, 'OK'));
    updateDialog();
    dialog.showModal();
  }

  function saveAs(data, filename) {
    saveToCallback(data, filename, saveBlob);
  }

  function saveBlob(blob, filename) {
    var reader = new FileReader();
    reader.onloadend = function() {
      var a = dom.html("a", {
        href: reader.result,
        download: filename,
        target: "_blank"
      });
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
    };
    reader.readAsDataURL(blob);
  }

  function readFile(file) {
    var fileName = file.name;
    if (fileName.indexOf(".svg", fileName.length - 5) === -1) {
      return alert("Not an SVG file");
    }
    var reader = new FileReader();
    reader.readAsText(file);
    reader.onload = function(evt) {
      restoreFormat(evt.target.result);
    };
  }

  function loadFile() {
    var input = dom.html("input", { type: "file", accept: "image/svg+xml" });
    if (!input) {
      return;
    }
    input.addEventListener("change", function(evt) {
      readFile(input.files[0]);
    });
    input.click();
  }

  // Save script to gist;
  function saveCurrentScriptsToGist(event) {
    event.preventDefault();
    // console.log("Saving to Gist");
    ajax.post(
      "https://api.github.com/gists",
      function(data) {
        //var raw_url = JSON.parse(data).files["script.json"].raw_url;
        gistID = JSON.parse(data)
          .url.split("/")
          .pop();
        var path = location.href.split("?")[0];
        path += "?gist=" + gistID;
        window.location = path;
      },
      JSON.stringify({
        description: "saved drawingboard file",
        public: true,
        files: {
          "animation.svg": {
            content: saveFormat()
          }
        }
      }),
      function(statusCode, x) {
        alert(
          "Can't save to Gist:\n" + statusCode + " (" + x.statusText + ") "
        );
      }
    );
  }

  var gistID = null;

  function loadScriptsFromGistId(id) {
    //we may get an event passed to this function so make sure we have a valid id or ask for one
    gistID = isNaN(parseInt(id))
      ? prompt(
          "What Gist would you like to load? Please enter the ID of the Gist: "
        )
      : id;
    if (!gistID) return;
    ajax.get(
      "https://api.github.com/gists/" + gistID,
      function(gist) {
        restoreFormat(JSON.parse(gist).files["animation.svg"].content);
      },
      function(statusCode, x) {
        alert(
          "Can't load from Gist:\n" + statusCode + " (" + x.statusText + ") "
        );
      }
    );
  }

  function newFile() {
    clear();
    onChange();
  }

  function onChange() {
    if (gistID) {
      gistID = null;
      var path = location.href.split("?")[0];
      history.replaceState(null, null, path);
    }
  }

  function queryMoat(cb) {
    fetch(MOAT_URL + "programs/?integration=shimmy").then(response =>
      response.json().then(cb)
    );
  }
  if (USE_MOAT) {
    window.addEventListener("load", e => queryMoat(setMoatUI), true);
  }else{
    document.getElementById('moat-container').remove();
  }

  window.file = {
    onChange: onChange,
    new: newFile,
    clear: clear,
    loadFile,
    saveFile,
    saveBlob,
    saveLocal,
    saveAs,
    sendToMoat
  };

  window.addEventListener("unload", saveLocal, false);
  window.addEventListener("load", restore, false);
})(window);
<|endoftext|>


<commit_before>var DEBUG = 1;

// AJAX setup
var AJAX_SETUP = {
	timeout: 9000,
	cache: false, // this little sentence killed a lot of little bugs that was actually one big big
}

// Loops & intervals
var BACKGROUND_LOOP = 30000; // 30s
var BACKGROUND_LOOP_OFFLINE = 3000; // 3s, respond quickly when we get back online
var PAGE_LOOP = 10000; // 10s

// Update stuff at every X intervals
var UPDATE_OFFICE_INTERVAL = 1; // recommended: 1
var UPDATE_SERVANT_INTERVAL = 20; // recommended: 20
var UPDATE_MEETINGS_INTERVAL = 20; // recommended: 20
var UPDATE_COFFEE_INTERVAL = 1; // recommended: 1
var UPDATE_HOURS_INTERVAL = 60; // recommended: 60
var UPDATE_CANTINAS_INTERVAL = 60; // recommended: 60
var UPDATE_BUS_INTERVAL = 2; // recommended: 1
var UPDATE_NEWS_INTERVAL = 20; // recommended: 20

// Meme detection
var urlExists = function(url) {
	try {
	    var http = new XMLHttpRequest();
	    http.open('HEAD', url, false);
	    http.send();
	    return http.status!=404;
	}
	catch (e) {
		return false;
	}
}
var MEME_AMOUNT = 0;
var __counter__ = 1;
while (urlExists('meme/'+__counter__+'.jpg')) {
	MEME_AMOUNT++;
	__counter__++;
}

// OS detection
var OPERATING_SYSTEM = "Unknown";
if (navigator.appVersion.indexOf("Win")!==-1) OPERATING_SYSTEM="Windows";
else if (navigator.appVersion.indexOf("Linux")!==-1) OPERATING_SYSTEM="Linux";
else if (navigator.appVersion.indexOf("X11")!==-1) OPERATING_SYSTEM="UNIX";
else if (navigator.appVersion.indexOf("Mac")!==-1) {
	OPERATING_SYSTEM = "Old Mac";
	if (navigator.appVersion.indexOf("10_7")!==-1||navigator.appVersion.indexOf("10_8")!==-1) {
		OPERATING_SYSTEM = "Mac";
	}
}
else {
	console.log('WARNING: Potentially unsupported operating system');
}

// Browser detection
var BROWSER = "Unknown";
if (typeof chrome != "undefined" && typeof opr == "undefined")
	BROWSER = "Chrome";
else if (typeof chrome != "undefined" && typeof opr != "undefined")
	BROWSER = "Opera";
else
	console.log('WARNING: Potentially unsupported browser');

// Production detection
if (BROWSER == 'Chrome')
	if (typeof chrome.i18n != 'undefined')
		if (chrome.i18n.getMessage('@@extension_id') === 'hfgffimlnajpbenfpaofmmffcdmgkllf')
			DEBUG = 0;
else if (BROWSER == 'Opera')
	if (typeof chrome.i18n != 'undefined')
		if (chrome.i18n.getMessage('@@extension_id') === 'npnpbddfcaibgnegafofkmffmbmflelj')
			DEBUG = 0;
<commit_msg>constants: turned off debug<commit_after>var DEBUG = 0;

// AJAX setup
var AJAX_SETUP = {
	timeout: 9000,
	cache: false, // this little sentence killed a lot of little bugs that was actually one big big
}

// Loops & intervals
var BACKGROUND_LOOP = 30000; // 30s
var BACKGROUND_LOOP_OFFLINE = 3000; // 3s, respond quickly when we get back online
var PAGE_LOOP = 10000; // 10s

// Update stuff at every X intervals
var UPDATE_OFFICE_INTERVAL = 1; // recommended: 1
var UPDATE_SERVANT_INTERVAL = 20; // recommended: 20
var UPDATE_MEETINGS_INTERVAL = 20; // recommended: 20
var UPDATE_COFFEE_INTERVAL = 1; // recommended: 1
var UPDATE_HOURS_INTERVAL = 60; // recommended: 60
var UPDATE_CANTINAS_INTERVAL = 60; // recommended: 60
var UPDATE_BUS_INTERVAL = 2; // recommended: 1
var UPDATE_NEWS_INTERVAL = 20; // recommended: 20

// Meme detection
var urlExists = function(url) {
	try {
	    var http = new XMLHttpRequest();
	    http.open('HEAD', url, false);
	    http.send();
	    return http.status!=404;
	}
	catch (e) {
		return false;
	}
}
var MEME_AMOUNT = 0;
var __counter__ = 1;
while (urlExists('meme/'+__counter__+'.jpg')) {
	MEME_AMOUNT++;
	__counter__++;
}

// OS detection
var OPERATING_SYSTEM = "Unknown";
if (navigator.appVersion.indexOf("Win")!==-1) OPERATING_SYSTEM="Windows";
else if (navigator.appVersion.indexOf("Linux")!==-1) OPERATING_SYSTEM="Linux";
else if (navigator.appVersion.indexOf("X11")!==-1) OPERATING_SYSTEM="UNIX";
else if (navigator.appVersion.indexOf("Mac")!==-1) {
	OPERATING_SYSTEM = "Old Mac";
	if (navigator.appVersion.indexOf("10_7")!==-1||navigator.appVersion.indexOf("10_8")!==-1) {
		OPERATING_SYSTEM = "Mac";
	}
}
else {
	console.log('WARNING: Potentially unsupported operating system');
}

// Browser detection
var BROWSER = "Unknown";
if (typeof chrome != "undefined" && typeof opr == "undefined")
	BROWSER = "Chrome";
else if (typeof chrome != "undefined" && typeof opr != "undefined")
	BROWSER = "Opera";
else
	console.log('WARNING: Potentially unsupported browser');

// Production detection
if (BROWSER == 'Chrome')
	if (typeof chrome.i18n != 'undefined')
		if (chrome.i18n.getMessage('@@extension_id') === 'hfgffimlnajpbenfpaofmmffcdmgkllf')
			DEBUG = 0;
else if (BROWSER == 'Opera')
	if (typeof chrome.i18n != 'undefined')
		if (chrome.i18n.getMessage('@@extension_id') === 'npnpbddfcaibgnegafofkmffmbmflelj')
			DEBUG = 0;
<|endoftext|>


<commit_before>"use strict";

var currentDate = new Date('Jun, 25, 2016, 12:00:00 GMT-400').getTime();
var countdown = document.getElementById('countdown');

function postEventInProgress(event) {
    countdown.innerHTML = "We are currently competing in " + event.link + "!";
    countdown.parentElement.style.background="#3D763C";
}

function addCountdown(futureDate) {
    var seconds_left = (futureDate - new Date().getTime()) / 1000;
    var days, hours, minutes, seconds;

    // do some time calculations
    days = parseInt(seconds_left / 86400);
    seconds_left = seconds_left % 86400;

    hours = parseInt(seconds_left / 3600);
    seconds_left = seconds_left % 3600;

    minutes = parseInt(seconds_left / 60);
    seconds = parseInt(seconds_left % 60);

    countdown.innerHTML = '' + days +  ' Days ' + hours + ' Hours '
    + minutes + ' Minutes ' + seconds + ' Seconds';
}

class event {
    constructor(name, start, end, link) {
        this.name = name;
        this.start = start;
        this.end = end;
        this.link = link;
    }

    post() {
        addCountdown(this.start);
    }
}

var events = [];
var eventPosted = false;

events.push(new event(
                'Midknight Mayhem',
                new Date('Jun, 25, 2016, 12:00:00 GMT-400').getTime(),
                new Date('Jun, 26, 2016, 12:00:00 GMT-400').getTime(),
                'MidKnight Mayhem'
                ));

events.push(new event(
                'Indiana Robotics Invitational',
                new Date('Jul, 15, 2016, 12:00:00 GMT-400').getTime(),
                new Date('Jul, 17, 2016, 12:00:00 GMT-400').getTime(),
                'Indiana Robotics Invitational'
                ));

//Sort the events array based on start date
events.sort(function(a,b) {return a.start - b.start; });

for(var currentEvent in events) {

    //If the curretEvent in the array hasn't occured yet,
    if(events[currentEvent].start > currentDate) {
        document.getElementById("nextevent").innerHTML = 'Next Event: ' + events[currentEvent].link;
        setInterval(function() { events[currentEvent].post(); }, 1000);
        eventPosted = true;
        break;
    } //If this statement is true, the start of the event has passed

    //If the event is in progress, post it as such
    else if(events[currentEvent].end > currentDate) {
        postEventInProgress(events[currentEvent]);
        eventPosted = true;
        break;
    }
}

if(!eventPosted) {
    document.getElementById("nextevent").innerHTML = 'We have no upcoming events!';
}
<commit_msg>Removed the condtion that I used to test a time-dependent feature of the code<commit_after>"use strict";

var currentDate = new Date().getTime();
var countdown = document.getElementById('countdown');

function postEventInProgress(event) {
    countdown.innerHTML = "We are currently competing in " + event.link + "!";
    countdown.parentElement.style.background="#3D763C";
}

function addCountdown(futureDate) {
    var seconds_left = (futureDate - new Date().getTime()) / 1000;
    var days, hours, minutes, seconds;

    // do some time calculations
    days = parseInt(seconds_left / 86400);
    seconds_left = seconds_left % 86400;

    hours = parseInt(seconds_left / 3600);
    seconds_left = seconds_left % 3600;

    minutes = parseInt(seconds_left / 60);
    seconds = parseInt(seconds_left % 60);

    countdown.innerHTML = '' + days +  ' Days ' + hours + ' Hours '
    + minutes + ' Minutes ' + seconds + ' Seconds';
}

class event {
    constructor(name, start, end, link) {
        this.name = name;
        this.start = start;
        this.end = end;
        this.link = link;
    }

    post() {
        addCountdown(this.start);
    }
}

var events = [];
var eventPosted = false;

events.push(new event(
                'Midknight Mayhem',
                new Date('Jun, 25, 2016, 12:00:00 GMT-400').getTime(),
                new Date('Jun, 26, 2016, 12:00:00 GMT-400').getTime(),
                'MidKnight Mayhem'
                ));

events.push(new event(
                'Indiana Robotics Invitational',
                new Date('Jul, 15, 2016, 12:00:00 GMT-400').getTime(),
                new Date('Jul, 17, 2016, 12:00:00 GMT-400').getTime(),
                'Indiana Robotics Invitational'
                ));

//Sort the events array based on start date
events.sort(function(a,b) {return a.start - b.start; });

for(var currentEvent in events) {

    //If the curretEvent in the array hasn't occured yet,
    if(events[currentEvent].start > currentDate) {
        document.getElementById("nextevent").innerHTML = 'Next Event: ' + events[currentEvent].link;
        setInterval(function() { events[currentEvent].post(); }, 1000);
        eventPosted = true;
        break;
    } //If this statement is true, the start of the event has passed

    //If the event is in progress, post it as such
    else if(events[currentEvent].end > currentDate) {
        postEventInProgress(events[currentEvent]);
        eventPosted = true;
        break;
    }
}

if(!eventPosted) {
    document.getElementById("nextevent").innerHTML = 'We have no upcoming events!';
}
<|endoftext|>


<commit_before>/**
 * Jadu CMP Dashboard
 *
 * Attaches the behaviour to a Dashboard in Jadu CMP
 */
define([
    'store-js',
    'jquery',
    'jquery-ui',
    'jquery-ui-touch',
    'modal',
    'tray'
], function(store) {

    'use strict';

    (function ($, window, document, undefined) {

        // Defaults
        var pluginName = 'dashboard',
            defaults = {
                fetchRetryTimeout: 50,
                title: 'My Dashboard',
                titleContainer: '.heading',
                sortableForcePlaceholderSize: true,
                sortableOpacity: 0.5,
                sortableRevert: 100,
                sortableTolerance: 'pointer',
                stateContainer: '#dashboard-state',
                trayContainer: '.tray',
                widgetClass: '.widget',
                widgetDataContainer: '#widget__data',
                widgetRemoveAttribute: '[data-widget-action=remove]'
            };

        // Constructor
        function Plugin (element, options) {
            this.element = element;
            this.currentItem = '';
            this.settings = $.extend( {}, defaults, options );
            this._defaults = defaults;
            this._name = pluginName;
            this.tray = '';
            this.widgetState = [];
            this.widgetData = '';
            this.init();
        }

        // Methods
        Plugin.prototype = {
            init: function () {

                // Set up the tray
                this.tray = $(this.settings.trayContainer).tray({
                    connectToSortable: this.element
                });

                // Set up the sortable dashboard
                this.initDashboard();

                console.log(store.enabled);
            },

            initDashboard: function () {
                console.log('init dashboard');

                var parent = this;

                // Set up the sortable
                $(this.element).sortable({
                    forcePlaceholderSize: this.settings.sortableForcePlaceholderSize,
                    opacity: this.settings.sortableOpacity,
                    receive: function(e, ui) {
                        console.log('received');

                        var $this = $(this);

                        function isFetched() {
                            parent.widgetData = $(parent.settings.widgetDataContainer).val();

                            if (parent.widgetData !== '') {
                                var widget = $this.data().uiSortable.currentItem;
                                var sender = ui.sender;

                                widget.html(parent.widgetData) // Populate widget content
                                    .uniqueId(); // Attach unique identifier

                                // Reset last-appended flag
                                $(parent.settings.widgetClass, parent.element).not(widget)
                                    .removeAttr('data-last-appended');

                                // Populate data attributes in new widget instance
                                widget.data('widget', sender.data('widget'))
                                      .data('widget-title', sender.data('widget-title'))
                                      .data('widget-description', sender.data('widget-description'))
                                      .attr('data-last-appended', 'true');

                                // Tidy up after ourselves
                                $(parent.settings.widgetDataContainer).val('');
                                parent.widgetData = '';
                            } else {

                                // Wait a bit more...
                                setTimeout(isFetched, parent.settings.fetchRetryTimeout);
                            }
                        }

                        // If the fetch started by the dragging event hasn't finished, keep checking for the response...
                        isFetched();

                    },
                    revert: this.settings.sortableRevert,
                    stop: function() {
                        parent.captureState();
                    },
                    tolerance: this.settings.sortableTolerance
                });

                // Remove widget event
                $(this.element).on('click', this.settings.widgetClass + ' ' + this.settings.widgetRemoveAttribute, function() {
                    $(this).closest(parent.settings.widgetClass).remove();
                    this.captureState;
                });

                // Rename dashboard
                $('form#rename').submit(function(e) {
                    e.preventDefault();

                    var values = {};
                    $.each($(this).serializeArray(), function(i, field) {
                        values[field.name] = field.value;
                    });

                    parent.settings.title = values.name;

                    $(parent.settings.titleContainer).text(parent.settings.title);
                    parent.captureState();

                    $(this).closest('.modal').modal().modal('hide');
                    $('.modal__backdrop').remove();
                });
            },

            captureState: function () {
                var state = [];

                // Grab the widget states
                $.map($(this.element).find(this.settings.widgetClass), function(el) {
                    state.push({
                        guid: 'widget_guid',
                        id: $(el).attr('id'),
                        settings: {
                            name: $(el).data('widget')
                        }
                    });
                });

                // Create the json object that stores dashboard state
                var Dashboard = {
                    title: this.settings.title,
                    widgets: state
                };

                // Store our JSON object
                this.state = Dashboard;

                // Save state to localstorage if available
                if (store.enabled) {
                    store.set(this.pluginName, this.state);
                    console.log('State saved to localstorage');
                }

                // Copy state to hidden stateContainer field in the DOM
                $(this.settings.stateContainer).val(JSON.stringify(Dashboard));

                console.log(JSON.stringify(this.state));
            }

        };

        $.fn[pluginName] = function (options) {
            return this.each(function() {
                if (!$.data(this, 'plugin_' + pluginName)) {
                    $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
                }
            });
        };

    })( jQuery, window, document );

});<commit_msg>Properly capture state when widgets are removed<commit_after>/**
 * Jadu CMP Dashboard
 *
 * Attaches the behaviour to a Dashboard in Jadu CMP
 */
define([
    'store-js',
    'jquery',
    'jquery-ui',
    'jquery-ui-touch',
    'modal',
    'tray'
], function(store) {

    'use strict';

    (function ($, window, document, undefined) {

        // Defaults
        var pluginName = 'dashboard',
            defaults = {
                fetchRetryTimeout: 50,
                title: 'My Dashboard',
                titleContainer: '.heading',
                sortableForcePlaceholderSize: true,
                sortableOpacity: 0.5,
                sortableRevert: 100,
                sortableTolerance: 'pointer',
                stateContainer: '#dashboard-state',
                trayContainer: '.tray',
                widgetClass: '.widget',
                widgetDataContainer: '#widget__data',
                widgetRemoveAttribute: '[data-widget-action=remove]'
            };

        // Constructor
        function Plugin (element, options) {
            this.element = element;
            this.currentItem = '';
            this.settings = $.extend( {}, defaults, options );
            this._defaults = defaults;
            this._name = pluginName;
            this.tray = '';
            this.widgetState = [];
            this.widgetData = '';
            this.init();
        }

        // Methods
        Plugin.prototype = {
            init: function () {

                // Set up the tray
                this.tray = $(this.settings.trayContainer).tray({
                    connectToSortable: this.element
                });

                // Set up the sortable dashboard
                this.initDashboard();
            },

            initDashboard: function () {
                console.log('init dashboard');

                var parent = this;

                // Set up the sortable
                $(this.element).sortable({
                    forcePlaceholderSize: this.settings.sortableForcePlaceholderSize,
                    opacity: this.settings.sortableOpacity,
                    receive: function(e, ui) {
                        console.log('received');

                        var $this = $(this);

                        function isFetched() {
                            parent.widgetData = $(parent.settings.widgetDataContainer).val();

                            if (parent.widgetData !== '') {
                                var widget = $this.data().uiSortable.currentItem;
                                var sender = ui.sender;

                                widget.html(parent.widgetData) // Populate widget content
                                    .uniqueId(); // Attach unique identifier

                                // Reset last-appended flag
                                $(parent.settings.widgetClass, parent.element).not(widget)
                                    .removeAttr('data-last-appended');

                                // Populate data attributes in new widget instance
                                widget.data('widget', sender.data('widget'))
                                      .data('widget-title', sender.data('widget-title'))
                                      .data('widget-description', sender.data('widget-description'))
                                      .attr('data-last-appended', 'true');

                                // Tidy up after ourselves
                                $(parent.settings.widgetDataContainer).val('');
                                parent.widgetData = '';
                            } else {

                                // Wait a bit more...
                                setTimeout(isFetched, parent.settings.fetchRetryTimeout);
                            }
                        }

                        // If the fetch started by the dragging event hasn't finished, keep checking for the response...
                        isFetched();

                    },
                    revert: this.settings.sortableRevert,
                    stop: function() {
                        parent.captureState();
                    },
                    tolerance: this.settings.sortableTolerance
                });

                // Remove widget event
                $(this.element).on('click', this.settings.widgetClass + ' ' + this.settings.widgetRemoveAttribute, function() {
                    $(this).closest(parent.settings.widgetClass).remove();
                    parent.captureState();
                });

                // Rename dashboard
                $('form#rename').submit(function(e) {
                    e.preventDefault();

                    var values = {};
                    $.each($(this).serializeArray(), function(i, field) {
                        values[field.name] = field.value;
                    });

                    parent.settings.title = values.name;

                    $(parent.settings.titleContainer).text(parent.settings.title);
                    parent.captureState();

                    $(this).closest('.modal').modal().modal('hide');
                    $('.modal__backdrop').remove();
                });
            },

            captureState: function () {
                var state = [];

                // Grab the widget states
                $.map($(this.element).find(this.settings.widgetClass), function(el) {
                    state.push({
                        guid: 'widget_guid',
                        id: $(el).attr('id'),
                        settings: {
                            name: $(el).data('widget')
                        }
                    });
                });

                // Create the json object that stores dashboard state
                var Dashboard = {
                    title: this.settings.title,
                    widgets: state
                };

                // Store our JSON object
                this.state = Dashboard;

                // Save state to localstorage if available
                if (store.enabled) {
                    store.set(this._name, this.state);
                }

                // Copy state to hidden stateContainer field in the DOM
                $(this.settings.stateContainer).val(JSON.stringify(Dashboard));

                console.log(JSON.stringify(this.state));
            }

        };

        $.fn[pluginName] = function (options) {
            return this.each(function() {
                if (!$.data(this, 'plugin_' + pluginName)) {
                    $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
                }
            });
        };

    })( jQuery, window, document );

});<|endoftext|>


<commit_before>/*
 * JavaScript Load Image Demo JS
 * https://github.com/blueimp/JavaScript-Load-Image
 *
 * Copyright 2013, Sebastian Tschan
 * https://blueimp.net
 *
 * Licensed under the MIT license:
 * https://opensource.org/licenses/MIT
 */

/* global loadImage, $ */

$(function () {
  'use strict'

  var result = $('#result')
  var exifNode = $('#exif')
  var iptcNode = $('#iptc')
  var thumbNode = $('#thumbnail')
  var actionsNode = $('#actions')
  var currentFile
  var coordinates
  var jcropAPI

  /**
   * Displays tag data
   *
   * @param {*} node jQuery node
   * @param {object} tags Tags object
   */
  function displayTagData(node, tags) {
    var table = node.find('table').empty()
    var row = $('

')
    var cell = $('	')
    var prop
    for (prop in tags) {
      if (Object.prototype.hasOwnProperty.call(tags, prop)) {
        table.append(
          row
            .clone()
            .append(cell.clone().text(prop))
            .append(cell.clone().text(tags[prop]))
        )
      }
    }
    node.show()
  }

  /**
   * Displays the thumbnal image
   *
   * @param {*} node jQuery node
   * @param {string} thumbnail Thumbnail URL
   * @param {object} [options] Options object
   */
  function displayThumbnailImage(node, thumbnail, options) {
    if (thumbnail) {
      thumbNode.empty()
      loadImage(
        thumbnail,
        function (img) {
          node.append(img).show()
        },
        options
      )
    }
  }

  /**
   * Displays meta data
   *
   * @param {object} [data] Meta data object
   */
  function displayMetaData(data) {
    if (!data) return
    var exif = data.exif
    var iptc = data.iptc
    if (exif) {
      displayThumbnailImage(thumbNode, exif.get('Thumbnail'), {
        orientation: exif.get('Orientation')
      })
      displayTagData(exifNode, exif.getAll())
    }
    if (iptc) {
      displayTagData(iptcNode, iptc.getAll())
    }
  }

  /**
   * Updates the results view
   *
   * @param {*} img Image or canvas element
   * @param {object} [data] Meta data object
   */
  function updateResults(img, data) {
    var fileName = currentFile.name
    var href = currentFile.url || img.src
    var dataURLStart
    var content
    if (!(img.src || img instanceof HTMLCanvasElement)) {
      content = $('Loading image file failed')
    } else {
      if (!href) {
        href = img.toDataURL(currentFile.type)
        // Check if file type is supported for the dataURL export:
        dataURLStart = 'data:' + currentFile.type
        if (href.slice(0, dataURLStart.length) !== dataURLStart) {
          fileName = fileName.replace(/\.\w+$/, '.png')
        }
      }
      content = $('')
        .append(img)
        .attr('download', fileName)
        .attr('href', href)
    }
    result.children().replaceWith(content)
    if (img.getContext) {
      actionsNode.show()
    }
    displayMetaData(data)
  }

  /**
   * Displays the image
   *
   * @param {File|Blob|string} file File or Blob object or image URL
   */
  function displayImage(file) {
    var options = {
      maxWidth: result.width(),
      canvas: true,
      pixelRatio: window.devicePixelRatio,
      downsamplingRatio: 0.5,
      orientation: true
    }
    exifNode.hide()
    iptcNode.hide()
    thumbNode.hide()
    if (!loadImage(file, updateResults, options)) {
      result
        .children()
        .replaceWith(
          $(
            '' +
              'Your browser does not support the URL or FileReader API.' +
              ''
          )
        )
    }
  }

  /**
   * Handles drop and file selection change events
   *
   * @param {event} event Drop or file selection change event
   */
  function fileChangeHandler(event) {
    event.preventDefault()
    var originalEvent = event.originalEvent
    var target = originalEvent.dataTransfer || originalEvent.target
    var file = target && target.files && target.files[0]
    if (!file) {
      return
    }
    currentFile = file
    displayImage(file)
  }

  /**
   * Handles URL change events
   */
  function urlChangeHandler() {
    var url = $(this).val()
    if (!url || (currentFile && currentFile.url === url)) return
    currentFile = {
      name: url.replace(/^.*\//g, ''),
      url: url
    }
    displayImage(url)
  }

  // Hide URL/FileReader API requirement message in capable browsers:
  if (
    window.createObjectURL ||
    window.URL ||
    window.webkitURL ||
    window.FileReader
  ) {
    result.children().hide()
  }

  $(document)
    .on('dragover', function (e) {
      e.preventDefault()
      var originalEvent = event.originalEvent
      if (originalEvent) originalEvent.dataTransfer.dropEffect = 'copy'
    })
    .on('drop', fileChangeHandler)

  $('#file-input').on('change', fileChangeHandler)

  $('#url').on('change paste input', urlChangeHandler)

  $('#edit').on('click', function (event) {
    event.preventDefault()
    var imgNode = result.find('img, canvas')
    var img = imgNode[0]
    var pixelRatio = window.devicePixelRatio || 1
    imgNode
      // eslint-disable-next-line new-cap
      .Jcrop(
        {
          setSelect: [
            40,
            40,
            img.width / pixelRatio - 40,
            img.height / pixelRatio - 40
          ],
          onSelect: function (coords) {
            coordinates = coords
          },
          onRelease: function () {
            coordinates = null
          }
        },
        function () {
          jcropAPI = this
        }
      )
      .parent()
      .on('click', function (event) {
        event.preventDefault()
      })
  })

  $('#crop').on('click', function (event) {
    event.preventDefault()
    var img = result.find('img, canvas')[0]
    var pixelRatio = window.devicePixelRatio || 1
    if (img && coordinates) {
      updateResults(
        loadImage.scale(img, {
          left: coordinates.x * pixelRatio,
          top: coordinates.y * pixelRatio,
          sourceWidth: coordinates.w * pixelRatio,
          sourceHeight: coordinates.h * pixelRatio,
          minWidth: result.width(),
          maxWidth: result.width(),
          pixelRatio: pixelRatio,
          downsamplingRatio: 0.5
        })
      )
      coordinates = null
    }
  })

  $('#cancel').on('click', function (event) {
    event.preventDefault()
    if (jcropAPI) jcropAPI.release()
  })
})
<commit_msg>Use the full frame for small images.<commit_after>/*
 * JavaScript Load Image Demo JS
 * https://github.com/blueimp/JavaScript-Load-Image
 *
 * Copyright 2013, Sebastian Tschan
 * https://blueimp.net
 *
 * Licensed under the MIT license:
 * https://opensource.org/licenses/MIT
 */

/* global loadImage, $ */

$(function () {
  'use strict'

  var result = $('#result')
  var exifNode = $('#exif')
  var iptcNode = $('#iptc')
  var thumbNode = $('#thumbnail')
  var actionsNode = $('#actions')
  var currentFile
  var coordinates
  var jcropAPI

  /**
   * Displays tag data
   *
   * @param {*} node jQuery node
   * @param {object} tags Tags object
   */
  function displayTagData(node, tags) {
    var table = node.find('table').empty()
    var row = $('

')
    var cell = $('	')
    var prop
    for (prop in tags) {
      if (Object.prototype.hasOwnProperty.call(tags, prop)) {
        table.append(
          row
            .clone()
            .append(cell.clone().text(prop))
            .append(cell.clone().text(tags[prop]))
        )
      }
    }
    node.show()
  }

  /**
   * Displays the thumbnal image
   *
   * @param {*} node jQuery node
   * @param {string} thumbnail Thumbnail URL
   * @param {object} [options] Options object
   */
  function displayThumbnailImage(node, thumbnail, options) {
    if (thumbnail) {
      thumbNode.empty()
      loadImage(
        thumbnail,
        function (img) {
          node.append(img).show()
        },
        options
      )
    }
  }

  /**
   * Displays meta data
   *
   * @param {object} [data] Meta data object
   */
  function displayMetaData(data) {
    if (!data) return
    var exif = data.exif
    var iptc = data.iptc
    if (exif) {
      displayThumbnailImage(thumbNode, exif.get('Thumbnail'), {
        orientation: exif.get('Orientation')
      })
      displayTagData(exifNode, exif.getAll())
    }
    if (iptc) {
      displayTagData(iptcNode, iptc.getAll())
    }
  }

  /**
   * Updates the results view
   *
   * @param {*} img Image or canvas element
   * @param {object} [data] Meta data object
   */
  function updateResults(img, data) {
    var fileName = currentFile.name
    var href = currentFile.url || img.src
    var dataURLStart
    var content
    if (!(img.src || img instanceof HTMLCanvasElement)) {
      content = $('Loading image file failed')
    } else {
      if (!href) {
        href = img.toDataURL(currentFile.type)
        // Check if file type is supported for the dataURL export:
        dataURLStart = 'data:' + currentFile.type
        if (href.slice(0, dataURLStart.length) !== dataURLStart) {
          fileName = fileName.replace(/\.\w+$/, '.png')
        }
      }
      content = $('')
        .append(img)
        .attr('download', fileName)
        .attr('href', href)
    }
    result.children().replaceWith(content)
    if (img.getContext) {
      actionsNode.show()
    }
    displayMetaData(data)
  }

  /**
   * Displays the image
   *
   * @param {File|Blob|string} file File or Blob object or image URL
   */
  function displayImage(file) {
    var options = {
      maxWidth: result.width(),
      canvas: true,
      pixelRatio: window.devicePixelRatio,
      downsamplingRatio: 0.5,
      orientation: true
    }
    exifNode.hide()
    iptcNode.hide()
    thumbNode.hide()
    if (!loadImage(file, updateResults, options)) {
      result
        .children()
        .replaceWith(
          $(
            '' +
              'Your browser does not support the URL or FileReader API.' +
              ''
          )
        )
    }
  }

  /**
   * Handles drop and file selection change events
   *
   * @param {event} event Drop or file selection change event
   */
  function fileChangeHandler(event) {
    event.preventDefault()
    var originalEvent = event.originalEvent
    var target = originalEvent.dataTransfer || originalEvent.target
    var file = target && target.files && target.files[0]
    if (!file) {
      return
    }
    currentFile = file
    displayImage(file)
  }

  /**
   * Handles URL change events
   */
  function urlChangeHandler() {
    var url = $(this).val()
    if (!url || (currentFile && currentFile.url === url)) return
    currentFile = {
      name: url.replace(/^.*\//g, ''),
      url: url
    }
    displayImage(url)
  }

  // Hide URL/FileReader API requirement message in capable browsers:
  if (
    window.createObjectURL ||
    window.URL ||
    window.webkitURL ||
    window.FileReader
  ) {
    result.children().hide()
  }

  $(document)
    .on('dragover', function (e) {
      e.preventDefault()
      var originalEvent = event.originalEvent
      if (originalEvent) originalEvent.dataTransfer.dropEffect = 'copy'
    })
    .on('drop', fileChangeHandler)

  $('#file-input').on('change', fileChangeHandler)

  $('#url').on('change paste input', urlChangeHandler)

  $('#edit').on('click', function (event) {
    event.preventDefault()
    var imgNode = result.find('img, canvas')
    var img = imgNode[0]
    var pixelRatio = window.devicePixelRatio || 1
    var margin = img.width / pixelRatio >= 140 ? 40 : 0
    imgNode
      // eslint-disable-next-line new-cap
      .Jcrop(
        {
          setSelect: [
            margin,
            margin,
            img.width / pixelRatio - margin,
            img.height / pixelRatio - margin
          ],
          onSelect: function (coords) {
            coordinates = coords
          },
          onRelease: function () {
            coordinates = null
          }
        },
        function () {
          jcropAPI = this
        }
      )
      .parent()
      .on('click', function (event) {
        event.preventDefault()
      })
  })

  $('#crop').on('click', function (event) {
    event.preventDefault()
    var img = result.find('img, canvas')[0]
    var pixelRatio = window.devicePixelRatio || 1
    if (img && coordinates) {
      updateResults(
        loadImage.scale(img, {
          left: coordinates.x * pixelRatio,
          top: coordinates.y * pixelRatio,
          sourceWidth: coordinates.w * pixelRatio,
          sourceHeight: coordinates.h * pixelRatio,
          minWidth: result.width(),
          maxWidth: result.width(),
          pixelRatio: pixelRatio,
          downsamplingRatio: 0.5
        })
      )
      coordinates = null
    }
  })

  $('#cancel').on('click', function (event) {
    event.preventDefault()
    if (jcropAPI) jcropAPI.release()
  })
})
<|endoftext|>


<commit_before>(function() {
    var app = angular.module('pdtDeveloper', []);
    app.controller('DeveloperController', function($scope, $rootScope, $uibModal, apiService){
        $scope.self = $scope;
        $scope.navColumnItems = [];//list of projects, also for providing items to navColumn
        $scope.activity = undefined;//activity object
        $scope.project = {};
        $scope.activityTypes = [
	        {title:'Development', id:0, code:'D'},
	        {title:'Defect Removal', id:1, code:'R'},
	        {title:'Management', id:2, code:'M'}
        ];
	    $scope.activityTypeIndex = undefined;

        $scope.createProject = function(){
            $location.path('projectmanager/createproject');
        };

        $scope.getProjects = function() {
            apiService.developer($rootScope.userId).success(function(data) {
                console.log(data);
	            $scope.navColumnItems = data.projects;
	            for (var i = 0; i < $scope.navColumnItems.length; i++)
		            $scope.navColumnItems[i].dropdownItems = $scope.activityTypes;
	            console.log($scope.navColumnItems);
            });
        };

        //nav column delegate
        $scope.selectNavColumnDropdownItem = function(item, dropdownItem) {
            $scope.promptSwitch(item, dropdownItem);
        };
        $scope.isActiveNavColumnItem = function(item) {
            return item.id == $scope.project.id;
        };

        $scope.switchTo = function(project, activityType) {
            console.log(project.id + ' ' +  activityType.id);

            if ($scope.activity) {
                apiService.endActivity($scope.activity.id).success(function(data) {
                    console.log(data);
                });
            }

            apiService.startActivity($rootScope.userId, project.id, activityType.code).success(function(data) {
                console.log(data);
                $scope.activity = data;
            });

            $scope.project = project;
            $scope.activityTypeIndex = activityType.id;
        };

        //modal delegate
        $scope.promptSwitch = function (project, activityType) {
            var modalInstance = $uibModal.open({
                animation: true,
                templateUrl: '/pdt/templates/modal.html',
                controller: 'ModalInstanceController',
                resolve: {
                    title: function () {return "Confirm";},
                    details: function () {
                        return "Do you want to switch to " + project.title + " " + activityType.title + "?";
                    }
                }
            });
            modalInstance.result.then(function (selectedItem) {
                $scope.switchTo(project, activityType);
            }, undefined);
        };

        //run time
        $scope.getProjects();
    });
})();<commit_msg>activity<commit_after>(function() {
    var app = angular.module('pdtDeveloper', []);
    app.controller('DeveloperController', function($scope, $rootScope, $uibModal, apiService){
        $scope.self = $scope;
        $scope.navColumnItems = [];//list of projects, also for providing items to navColumn
        $scope.activity = undefined;//activity object
        $scope.project = {};//project copied from navColumnItems
        $scope.activityTypes = [
	        {title:'Development', id:0, code:'D'},
	        {title:'Defect Removal', id:1, code:'R'},
	        {title:'Management', id:2, code:'M'}
        ];
	    $scope.activityTypeIndex = undefined;

        $scope.createProject = function(){
            $location.path('projectmanager/createproject');
        };

        $scope.getProjects = function() {
            apiService.developer($rootScope.userId).success(function(data) {
                console.log(data);
	            $scope.navColumnItems = data.projects;
	            for (var i = 0; i < $scope.navColumnItems.length; i++)
		            $scope.navColumnItems[i].dropdownItems = $scope.activityTypes;
	            console.log($scope.navColumnItems);
            });
        };

        //nav column delegate
        $scope.selectNavColumnDropdownItem = function(item, dropdownItem) {
            $scope.promptSwitch(item, dropdownItem);
        };
        $scope.isActiveNavColumnItem = function(item) {
            return item.id == $scope.project.id;
        };

        $scope.switchTo = function(project, activityType) {
            console.log(project.id + ' ' +  activityType.id);

            if ($scope.activity) {
                apiService.endActivity($scope.activity.id).success(function(data) {
                    console.log(data);
                });
            }

            apiService.startActivity($rootScope.userId, project.id, activityType.code).success(function(data) {
                console.log(data);
                $scope.activity = data;
            });

            $scope.project = project;
            $scope.activityTypeIndex = activityType.id;
        };

        //modal delegate
        $scope.promptSwitch = function (project, activityType) {
            var modalInstance = $uibModal.open({
                animation: true,
                templateUrl: '/pdt/templates/modal.html',
                controller: 'ModalInstanceController',
                resolve: {
                    title: function () {return "Confirm";},
                    details: function () {
                        return "Do you want to switch to " + project.title + " " + activityType.title + "?";
                    }
                }
            });
            modalInstance.result.then(function (selectedItem) {
                $scope.switchTo(project, activityType);
            }, undefined);
        };

        //run time
        $scope.getProjects();
    });
})();<|endoftext|>


<commit_before>angular.module('ohhell.directive', []).

directive('ohhellTrend', function() {
  return {
    restrict: 'A',
    scope: {
      // total score at each round for a player
      playerScores: '=', // by reference
      // lowest score for any player, at any point in the game
      minScore: '@', // by value
      // highest score for any player, at any point in the game
      maxScore: '@' // by value
    },
    link: function(scope, element, attributes) {
      // Not sure if this is needed
      function everythingAvailable() {
        return scope.minScore !== undefined
          && scope.maxScore !== undefined
          && scope.playerScores !== undefined;
      }

      scope.$watch(function() {
        return everythingAvailable();
      }, function(showPlot) {
        if (showPlot) {
          // plot scores
          $(element).sparkline(scope.playerScores, {
            fillColor: false,     // disable fill
            maxSpotColor: false,  // disable spot on max y value
            minSpotColor: false   // disable spot on min y value
          });
        }
      });
    }
  };
});<commit_msg>actually use min/max scores<commit_after>angular.module('ohhell.directive', []).

directive('ohhellTrend', function() {
  return {
    restrict: 'A',
    scope: {
      // total score at each round for a player
      playerScores: '=', // by reference
      // lowest score for any player, at any point in the game
      minScore: '@', // by value
      // highest score for any player, at any point in the game
      maxScore: '@' // by value
    },
    link: function(scope, element, attributes) {
      // Not sure if this is needed
      function everythingAvailable() {
        return scope.minScore !== undefined
          && scope.maxScore !== undefined
          && scope.playerScores !== undefined;
      }

      scope.$watch(function() {
        return everythingAvailable();
      }, function(showPlot) {
        if (showPlot) {
          // plot scores
          $(element).sparkline(scope.playerScores, {
            fillColor: false,               // disable fill
            maxSpotColor: false,            // disable spot on max y value
            minSpotColor: false,            // disable spot on min y value
            chartRangeMin: scope.minScore,
            chartRangeMax: scope.maxScore
          });
        }
      });
    }
  };
});<|endoftext|>


<commit_before>function describe(){}
function it(){}

describe('Test Suite - Let\'s use jquery', () => {

    it('should hide all the images from the view', () =>{

    });

    it('should show all the images again', () =>{

    });

    it('should change the heading to "The Best Collection"', () =>{

    });

    it('should make the hr (.line) element bolder', () =>{

    });

    it('should change the background of each product title with a different color', () =>{

    });

    it('should remove the "BUY ITEM" buttons', () =>{

    });

    it('should remove the last three item from the view', () =>{

    });

    it('should make 10% reduction on all products', () =>{

    });

    it('should remove the pahts from the katalog', () =>{

    });

    it('should rename the product shirt to "Fish-Shirt"', () =>{

    });

    it('should rename the first rock item to "Bird-Rock"', () =>{

    });

    it('should add 5 stars to the product shirt', () =>{

    });

    it('should change the title name with a random name (use alg. for randomly generating chars)', () =>{

    });

    it('should color the stars of the third product with green', () =>{

    });

    it('should reset the last two images to the url "http://bit.ly/2xq8ev0"', () =>{

    });

    it('should constantly change the price (#changingPrice), increment it by one in each 3 secs.', () =>{

    });

    it('should show the "BUY ITEM" again with a green background, gray border and a thin shadow', () =>{

    });

    it('should add an event handler to the "BUY ITEM" buttons and after a click it should show an alert', () =>{

    });

    it('should bring back the initial image again, instead of "http://bit.ly/2xq8ev0"', () =>{

    });

    it('should change every product desctiption to any text with at least 50 charakters', () =>{

    });

    it('should randomly change all of the prices', () =>{

    });

    it('should mark the background with the color yellow of the two cheapest products', () =>{

    });

    it('should sort all the products ascendantly based on the the new prices', () =>{

    });

    it('should add an mouse over event only the highest two products which logs in console the price', () =>{

    });
});
<commit_msg>correction<commit_after>function describe(){}
function it(fn){
    return fn();
}

    it('should hide all the images from the view', () =>{

    });

    it('should show all the images again', () =>{

    });

    it('should change the heading to "The Best Collection"', () =>{

    });

    it('should make the hr (.line) element bolder', () =>{

    });

    it('should change the background of each product title with a different color', () =>{

    });

    it('should remove the "BUY ITEM" buttons', () =>{

    });

    it('should remove the last three item from the view', () =>{

    });

    it('should make 10% reduction on all products', () =>{

    });

    it('should remove the pahts from the katalog', () =>{

    });

    it('should rename the product shirt to "Fish-Shirt"', () =>{

    });

    it('should rename the first rock item to "Bird-Rock"', () =>{

    });

    it('should add 5 stars to the product shirt', () =>{

    });

    it('should change the title name with a random name (use alg. for randomly generating chars)', () =>{

    });

    it('should color the stars of the third product with green', () =>{

    });

    it('should reset the last two images to the url "http://bit.ly/2xq8ev0"', () =>{

    });

    it('should constantly change the price (#changingPrice), increment it by one in each 3 secs.', () =>{

    });

    it('should show the "BUY ITEM" again with a green background, gray border and a thin shadow', () =>{

    });

    it('should add an event handler to the "BUY ITEM" buttons and after a click it should show an alert', () =>{

    });

    it('should bring back the initial image again, instead of "http://bit.ly/2xq8ev0"', () =>{

    });

    it('should change every product desctiption to any text with at least 50 charakters', () =>{

    });

    it('should randomly change all of the prices', () =>{

    });

    it('should mark the background with the color yellow of the two cheapest products', () =>{

    });

    it('should sort all the products ascendantly based on the the new prices', () =>{

    });

    it('should add an mouse over event only the highest two products which logs in console the price', () =>{

    });

<|endoftext|>


<commit_before>/**
 * jQuery Plugin Fast Facts
 * Version 1.1.0
 * Sal Ferrarello (http://salferrarello.com)
 *
 * http://fastfacts.salcode.com/
 */
(function( $ ) {
	$.fn.fastFacts = function( options ) {

		var options = $.extend({
			'min': 0,
			'max': 9,
			'colClass': 'col-xs-1',
			'rowClass': 'row',
			'operator': '+',
			'numProblems': 100,
			'allowNegativeResult': false,
			'allowZeroResult': false
		}, options );

		return this.each( function() {
			var elem = $( this );
			var markup = getMarkup( options );
			elem.append( markup );
		});
	};

	var getMarkup = function( options ) {
		var markup = '';
		var problemCount = 0;
		var colIndex = 0;
		var numColumns = 10;

		while ( problemCount < options.numProblems ) {
			markup += startRow( options );
				colIndex = 0;
				while ( colIndex < numColumns && problemCount < options.numProblems ) {
					markup += startColumn( options );
					markup += getProblem( options );
					markup += endColumn( options );

					colIndex++;
					problemCount++;

				}

			markup += endRow( options );
		}

		return markup;
	}

	var startRow = function( options ) {
		return '
';
	}
	var endRow = function( options ) {
		return '
';
	}

	var startColumn = function( options ) {
		return '
';
	}
	var endColumn = function( options ) {
		return '
';
	}
	var getProblem = function( options ) {
		var markup = '';
		var firstNumber  = getNumber( options );
		var secondNumber = getNumber( options, firstNumber );

		markup += '
';

			markup += '
';
			markup += firstNumber;
			markup += '
';

			markup += '
';
				markup += '';
				markup += options.operator;
				markup += '';

				markup += secondNumber;
			markup += '
';
		markup += '
';

		return markup;
	}

	var getNumber = function( options, otherNumber = false ) {
		var min, max;
		if ( '-' === options.operator && false !== otherNumber ) {
			min = options.min;
			max = options.allowNegativeResult ? options.max : otherNumber - 1;

			if ( false === options.allowZeroResult && otherNumber === max ) {
				max--;
			}
		} else {
			min = options.min;
			max = options.max;
		}

		return randomNumberFromMinToMaxInclusive( min, max );
	}

	var randomNumberFromMinToMaxInclusive = function( min, max ) {
		return Math.floor( Math.random() * ( max - min + 1 ) ) + min;
	}

}) ( jQuery );
<commit_msg>Address edge case where min > max<commit_after>/**
 * jQuery Plugin Fast Facts
 * Version 1.1.0
 * Sal Ferrarello (http://salferrarello.com)
 *
 * http://fastfacts.salcode.com/
 */
(function( $ ) {
	$.fn.fastFacts = function( options ) {

		var options = $.extend({
			'min': 0,
			'max': 9,
			'colClass': 'col-xs-1',
			'rowClass': 'row',
			'operator': '+',
			'numProblems': 100,
			'allowNegativeResult': false,
			'allowZeroResult': false
		}, options );

		return this.each( function() {
			var elem = $( this );
			var markup = getMarkup( options );
			elem.append( markup );
		});
	};

	var getMarkup = function( options ) {
		var markup = '';
		var problemCount = 0;
		var colIndex = 0;
		var numColumns = 10;

		while ( problemCount < options.numProblems ) {
			markup += startRow( options );
				colIndex = 0;
				while ( colIndex < numColumns && problemCount < options.numProblems ) {
					markup += startColumn( options );
					markup += getProblem( options );
					markup += endColumn( options );

					colIndex++;
					problemCount++;

				}

			markup += endRow( options );
		}

		return markup;
	}

	var startRow = function( options ) {
		return '
';
	}
	var endRow = function( options ) {
		return '
';
	}

	var startColumn = function( options ) {
		return '
';
	}
	var endColumn = function( options ) {
		return '
';
	}
	var getProblem = function( options ) {
		var markup = '';
		var firstNumber  = getNumber( options );
		var secondNumber = getNumber( options, firstNumber );

		markup += '
';

			markup += '
';
			markup += firstNumber;
			markup += '
';

			markup += '
';
				markup += '';
				markup += options.operator;
				markup += '';

				markup += secondNumber;
			markup += '
';
		markup += '
';

		return markup;
	}

	var getNumber = function( options, otherNumber = false ) {
		var min, max;
		if ( '-' === options.operator && false !== otherNumber ) {
			min = options.min;
			max = options.allowNegativeResult ? options.max : otherNumber - 1;

			if ( false === options.allowZeroResult && otherNumber === max ) {
				max--;
			}

			if ( min > max ) {
				min = max;
			}
		} else {
			min = options.min;
			max = options.max;
		}

		return randomNumberFromMinToMaxInclusive( min, max );
	}

	var randomNumberFromMinToMaxInclusive = function( min, max ) {
		return Math.floor( Math.random() * ( max - min + 1 ) ) + min;
	}

}) ( jQuery );
<|endoftext|>