<commit_before>//Utility functions
//From http://www.jquerybyexample.net/2012/06/get-url-parameters-using-jquery.html
function getURLParameter(sParam) {
    var sPageURL = window.location.search.substring(1);
    var sURLVariables = sPageURL.split('&');
    for (var i = 0; i < sURLVariables.length; i++) {
        var sParameterName = sURLVariables[i].split('=');
        if (sParameterName[0] === sParam) {
            return sParameterName[1];
        }
    }
}
;

function ampDecode(encoded) {
    var elem = document.createElement('textarea');
    elem.innerHTML = encoded;
    return elem.value;
}

$(function () {
    var gh = null;
    var profile;

    var exerciseParam = getURLParameter("exercise");
    if (exerciseParam) {
        $("#exercise").attr("resource", exerciseParam);
    }

    LD2h.expand().then(function () {

        var sourceUriValue = $("#sourceURI").val();
        if (sourceUriValue && (sourceUriValue.trim().length > 0)) {
            setRdfSourceType("uri");
        }

        var codeEditorValue = ampDecode($("#codeEditor").html());
        $("#codeEditor").html("");
        var codeEditorCM = CodeMirror($("#codeEditor")[0], {
            mode: "javascript"
        });
        if (codeEditorValue) {
            codeEditorCM.setValue(codeEditorValue);
        }
        var matchersEditorValue = ampDecode($("#matchersEditor").html());
        $("#matchersEditor").html("")
        var matchersEditorCM = CodeMirror($("#matchersEditor")[0], {
            mode: "turtle"
        });
        if (matchersEditorValue) {
            matchersEditorCM.setValue(matchersEditorValue);
        }
        var run = function () {
            if ($("#sourceURI").val() !== "") {
                var sourceURI = $("#sourceURI").val();
            } else {
                var sourceURI = $("#endpointURL").val() + "?query=" + encodeURIComponent($("#queryForEndpoint").val()) + "&format=auto";
            }
            var turtleParser = LdpStore.parsers.findParsers("text/turtle")[0];
            var store = new LdpStore({
                parsers: new LdpStore.ParserUtil({
                    'text/turtle': turtleParser,
                    //'application/ld+json': LdpStore.parsers.findParsers("application/ld+json")[0],
                    'application/rdf+xml': LdpStore.parsers.findParsers("application/rdf+xml")[0]
                })
            });
            var getData = function () {
                if ($('#rdfSource-uri').is(":visible") || $('#rdfSource-endpoint').is(":visible")) {
                    return store.match(
                            null,
                            null,
                            null,
                            sourceURI).catch(
                            function (error) {
                                console.warn("Couldn't get any triple from " + sourceURI + ". reason: " + error);
                            });

                } else {
                    var turtle = rdfDataEditorCM.getValue();
                    return turtleParser.parse(turtle, undefined, "http://example.org/").catch(function (e) {
                        console.log(e);
                        alert("Could not parse Turtle: " + e.constructor.name);
                        throw "Parsing failed";
                    });
                }
            };
            getData().then(function (g) {
                var code = codeEditorCM.getValue();
                var runCode = new Promise(function (resolve, reject) {
                    try {
                        var result = eval(code);
                    } catch (e) {
                        if ((e instanceof ReferenceError) ||
                                (e instanceof SyntaxError) ||
                                (e instanceof TypeError)) {
                            alert(e.constructor.name +
                                    (e.lineNumber ? " on line " + e.lineNumber : "") +
                                    ": " + e.message);
                        } else {
                            throw(e);
                        }
                    }
                    //if code result in undefined it will immediately be resolves
                    //if it returns a promise it will follow that promise
                    resolve(result);
                });
                runCode.then(function () {
                    var resource = rdf.createNamedNode($("#rendering-resource").val());
                    var matchersTurtle = matchersEditorCM.getValue();
                    if (matchersTurtle.length > 0) {
                        turtleParser.parse(matchersTurtle).then(function (matchers) {
                            var renderingResult = new RDF2h(matchers).render(
                                    g, resource);
                            $("#result").html(renderingResult);
                        });
                    }
                });
            });
        };
        $("#run").on("click", run);

        $(".source-solution-button").on("click", function () {
            if ($("#sourceURI-solution").length > 0) {
                if (confirm("Confirm that you are you too lazy to copy and paste that URI.")) {
                    $("#sourceURI").val($("#sourceURI-solution").text().trim());
                    setRdfSourceType("uri")
                }
            } else {
                setRdfSourceType("directInput");
                rdfDataEditorCM.setValue($("#sourceEditor-solution").text().trim());
            }
        });
        $("#codeEditor-solution-button").on("click", function () {
            var message = "Confirm that you would like to see the solution.";
            if (codeEditorCM.getValue().trim().length > 0) {
                message += "\nWARNING: The code that you've already entered will be gone forever.";
            }
            if (confirm(message)) {
                codeEditorCM.setValue($("#codeEditor-solution").text().trim());
            }
        });
        $("#rendering-solution-button").on("click", function () {
            var message = "Confirm that you would like to see the solution.";
            if (matchersEditorCM.getValue().trim().length > 0) {
                message += "\nWARNING: That code that you've already entered will be forever lost.";
            }
            if (confirm(message)) {
                $("#rendering-resource").val($("#rendering-resource-solution").text().trim());
                matchersEditorCM.setValue($("#matchersEditor-solution").text().trim());
            }
        });

        updateLogginStatus();

        function updateLogginStatus() {
            if (profile) {
                $('.authenticatedOnly').show();
                $('#login-div').html('Logged in as ' + profile.login + ' (Logout)');
                $('#logout-link').click(function () {
                    profile = null;
                    updateLogginStatus();
                    return false;
                });
                var repo = gh.getRepo(profile.login, 'lodide-saved-contents');
                repo.getTree("master").then(function (r) {
                    var tree = r.data.tree
                    //for (var i = 0; i < tree.length;i++) {
                    //    var e = tree[i];
                    tree.forEach(function (e) {
                        console.log(e);
                        repo.getContents('master', e.path, 'raw').then(function (response) {
                            console.log("Contents of: " + e.path);
                            console.log(response.data);
                        });
                    });
                }).catch(function (e) {
                    alert("e: " + e);
                });
            } else {
                $('.authenticatedOnly').hide();
                $('#login-div').html('Login with GitHub');
                $('#login-link').click(function () {
                    $('#login-dialog').modal("show");
                    return false;
                });
            }
        }

        var loginButtonAction = function (auth) {
            gh = new GitHub(auth);
            var user = gh.getUser();
            console.log(user);
            user.getProfile().then(function (response) {
                profile = response.data;
                console.log(profile);
                updateLogginStatus();
                $('#login-dialog').modal('hide');
            });

        }

        $('#personalAccessTokenLoginButton').click(function () {
            if ($('#saveCredentialForLater').prop("checked")) {
                localStorage.setItem("personalAccessToken", $('#personalAccessToken').val());
            } else {
                localStorage.removeItem("personalAccessToken");
            }
            loginButtonAction({
                token: $('#personalAccessToken').val(),
            });
        });

        $('#passwordLoginButton').click(function () {
            loginButtonAction({
                'username': $('#userName').val(),
                'password': $('#password').val()
            });
        });

        $("#saveButton").click(function () {
            $("#fileNameDialog").modal("show");
        });

        $("#saveButton2").click(function () {
            var fileName = $("#fileName").val();
            if (!fileName.endsWith(".ttl")) {
                fileName = fileName + ".ttl";
            }
            var repo = gh.getRepo(profile.login, 'lodide-saved-contents');
            repo.listBranches().then(writeFile).catch(function (e) {
                console.log("failed to write file, will attempt to create repo");
                console.log(e);
                //create new repository
                gh.getUser().createRepo({
                    "name": "lodide-saved-contents",
                    "description": "A repository for saving http://lodide.io/ projects.",
                    "homepage": "http://lodide.io/",
                    "private": false,
                    "has_issues": false,
                    "has_wiki": false,
                    "has_downloads": false
                }).then(writeFile)
                        .catch(function (a) {
                            alert("error: " + a)
                        });
            });
            function writeFile() {
                serializeCurrentState().then(function (fileContent) {
                    repo.writeFile('master', fileName, fileContent,
                            "Run it on http://lodide.io/?exercise=https://raw.githubusercontent.com/" + profile.login + "/lodide-saved-contents/master/" + fileName, {}).then(function (r) {
                        alert("saved file: " + fileName);
                        console.log(r);
                    });
                }).catch(function (e) {
                    console.log("Error serializing:");
                    console.log(e);
                    alert("Serialization failed, see log");
                });
            }
            function serializeCurrentState() {
                var g = new rdf.Graph();
                var exercise = rdf.createNamedNode(""); //rdf-ext supports relative IRIs
                g.add(rdf.createTriple(exercise, rdfNs("type"), lodIdeNs("Exercise")));
                g.add(rdf.createTriple(exercise, lodIdeNs("intro"), rdf.createLiteral($("#intro").html())));
                g.add(rdf.createTriple(exercise, lodIdeNs("finalWords"),
                        rdf.createLiteral($("#finalWords").html())));
                var dataSource = rdf.createBlankNode();
                g.add(rdf.createTriple(exercise, lodIdeNs("dataSource"), dataSource));
                if ($("#dataSource-taskDescription").length > 0) {
                    g.add(rdf.createTriple(dataSource, lodIdeNs("taskDescription"),
                            rdf.createLiteral($("#dataSource-taskDescription").html())));
                }

                g.add(rdf.createTriple(dataSource, lodIdeNs("taskSolutionResource"),
                        rdf.createNamedNode($("#sourceURI-solution").html())));
                if ($('#rdfSource-uri').is(":visible")) {
                    g.add(rdf.createTriple(dataSource, lodIdeNs("taskSolutionResourceCurrent"),
                            rdf.createLiteral($("#sourceURI").val())));
                }
                if ($('#rdfSource-directInput').is(":visible")) {
                    g.add(rdf.createTriple(dataSource, lodIdeNs("taskSolutionCodeCurrent"),
                            rdf.createLiteral(rdfDataEditorCM.getValue())));
                }
                var dataProcessing = rdf.createBlankNode();
                g.add(rdf.createTriple(exercise, lodIdeNs("dataProcessing"), dataProcessing));
                if ($("#dataProcessing-taskDescription").length > 0) {
                    g.add(rdf.createTriple(dataProcessing, lodIdeNs("taskDescription"),
                            rdf.createLiteral($("#dataProcessing-taskDescription").html())));
                }
                g.add(rdf.createTriple(dataProcessing, lodIdeNs("taskSolutionCode"),
                        rdf.createLiteral($("#codeEditor-solution").html())));
                g.add(rdf.createTriple(dataProcessing, lodIdeNs("taskSolutionCodeCurrent"),
                        rdf.createLiteral(codeEditorCM.getValue())));
                if ($("#dataRenderingTitle").length > 0) {
                    var dataRendering = rdf.createBlankNode();
                    g.add(rdf.createTriple(exercise, lodIdeNs("dataRendering"), dataRendering));
                    if ($("#dataRendering-taskDescription").length > 0) {
                        g.add(rdf.createTriple(dataRendering, lodIdeNs("taskDescription"),
                                rdf.createLiteral($("#dataRendering-taskDescription").html())));
                    }
                    g.add(rdf.createTriple(dataRendering, lodIdeNs("taskSolutionCode"),
                            rdf.createLiteral($("#matchersEditor-solution").html())));
                    g.add(rdf.createTriple(dataRendering, lodIdeNs("taskSolutionCodeCurrent"),
                            rdf.createLiteral(matchersEditorCM.getValue())));
                    g.add(rdf.createTriple(dataRendering, lodIdeNs("taskSolutionResource"),
                            rdf.createNamedNode($("#rendering-resource-solution").html())));
                    g.add(rdf.createTriple(dataRendering, lodIdeNs("taskSolutionResourceCurrent"),
                            rdf.createLiteral($("#rendering-resource").val())));
                }
                return rdf.serializers["text/turtle"].serialize(g).then(function (turtle) {
                    return turtle;
                });
            }
            function lodIdeNs(localName) {
                return rdf.createNamedNode("http://ontology.lodide.io/" + localName);
            }
            function rdfNs(localName) {
                return rdf.createNamedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#" + localName);
            }
        });

        $(".exerciseIndexLink").click(function (e) {
            var exerciseArea = $("#exercise");
            exerciseArea.hide();
            var exerciseIndexArea = $("#exerciseIndex");

            if (exerciseIndexArea.is(":visible")) {
                exerciseIndexArea.addClass("fetch");
                exerciseIndexArea.attr("resource", "index.ttl");
                LD2h.expand();
            } else {
                exerciseIndexArea.show();
            }
            window.previousLocation = window.location.toString();
            window.history.pushState({}, "", "exercise-index.html");
            $("#lodIDEMenu").removeClass("active");
            $("#exerciseIndexMenu").addClass("active");
            e.preventDefault();
        });

        $(".lodIDELink").click(function () {
            var exerciseArea = $("#exercise");
            exerciseArea.show();
            var exerciseIndexArea = $("#exerciseIndex");
            exerciseIndexArea.hide();
            window.history.pushState({}, "", window.previousLocation);
            $("#lodIDEMenu").addClass("active");
            $("#exerciseIndexMenu").removeClass("active");
        });

    });

});
<commit_msg>No more undefined taskSolutionResource when not present<commit_after>//Utility functions
//From http://www.jquerybyexample.net/2012/06/get-url-parameters-using-jquery.html
function getURLParameter(sParam) {
    var sPageURL = window.location.search.substring(1);
    var sURLVariables = sPageURL.split('&');
    for (var i = 0; i < sURLVariables.length; i++) {
        var sParameterName = sURLVariables[i].split('=');
        if (sParameterName[0] === sParam) {
            return sParameterName[1];
        }
    }
}
;

function ampDecode(encoded) {
    var elem = document.createElement('textarea');
    elem.innerHTML = encoded;
    return elem.value;
}

$(function () {
    var gh = null;
    var profile;

    var exerciseParam = getURLParameter("exercise");
    if (exerciseParam) {
        $("#exercise").attr("resource", exerciseParam);
    }

    LD2h.expand().then(function () {

        var sourceUriValue = $("#sourceURI").val();
        if (sourceUriValue && (sourceUriValue.trim().length > 0)) {
            setRdfSourceType("uri");
        }

        var codeEditorValue = ampDecode($("#codeEditor").html());
        $("#codeEditor").html("");
        var codeEditorCM = CodeMirror($("#codeEditor")[0], {
            mode: "javascript"
        });
        if (codeEditorValue) {
            codeEditorCM.setValue(codeEditorValue);
        }
        var matchersEditorValue = ampDecode($("#matchersEditor").html());
        $("#matchersEditor").html("")
        var matchersEditorCM = CodeMirror($("#matchersEditor")[0], {
            mode: "turtle"
        });
        if (matchersEditorValue) {
            matchersEditorCM.setValue(matchersEditorValue);
        }
        var run = function () {
            if ($("#sourceURI").val() !== "") {
                var sourceURI = $("#sourceURI").val();
            } else {
                var sourceURI = $("#endpointURL").val() + "?query=" + encodeURIComponent($("#queryForEndpoint").val()) + "&format=auto";
            }
            var turtleParser = LdpStore.parsers.findParsers("text/turtle")[0];
            var store = new LdpStore({
                parsers: new LdpStore.ParserUtil({
                    'text/turtle': turtleParser,
                    //'application/ld+json': LdpStore.parsers.findParsers("application/ld+json")[0],
                    'application/rdf+xml': LdpStore.parsers.findParsers("application/rdf+xml")[0]
                })
            });
            var getData = function () {
                if ($('#rdfSource-uri').is(":visible") || $('#rdfSource-endpoint').is(":visible")) {
                    return store.match(
                            null,
                            null,
                            null,
                            sourceURI).catch(
                            function (error) {
                                console.warn("Couldn't get any triple from " + sourceURI + ". reason: " + error);
                            });

                } else {
                    var turtle = rdfDataEditorCM.getValue();
                    return turtleParser.parse(turtle, undefined, "http://example.org/").catch(function (e) {
                        console.log(e);
                        alert("Could not parse Turtle: " + e.constructor.name);
                        throw "Parsing failed";
                    });
                }
            };
            getData().then(function (g) {
                var code = codeEditorCM.getValue();
                var runCode = new Promise(function (resolve, reject) {
                    try {
                        var result = eval(code);
                    } catch (e) {
                        if ((e instanceof ReferenceError) ||
                                (e instanceof SyntaxError) ||
                                (e instanceof TypeError)) {
                            alert(e.constructor.name +
                                    (e.lineNumber ? " on line " + e.lineNumber : "") +
                                    ": " + e.message);
                        } else {
                            throw(e);
                        }
                    }
                    //if code result in undefined it will immediately be resolves
                    //if it returns a promise it will follow that promise
                    resolve(result);
                });
                runCode.then(function () {
                    var resource = rdf.createNamedNode($("#rendering-resource").val());
                    var matchersTurtle = matchersEditorCM.getValue();
                    if (matchersTurtle.length > 0) {
                        turtleParser.parse(matchersTurtle).then(function (matchers) {
                            var renderingResult = new RDF2h(matchers).render(
                                    g, resource);
                            $("#result").html(renderingResult);
                        });
                    }
                });
            });
        };
        $("#run").on("click", run);

        $(".source-solution-button").on("click", function () {
            if ($("#sourceURI-solution").length > 0) {
                if (confirm("Confirm that you are you too lazy to copy and paste that URI.")) {
                    $("#sourceURI").val($("#sourceURI-solution").text().trim());
                    setRdfSourceType("uri")
                }
            } else {
                setRdfSourceType("directInput");
                rdfDataEditorCM.setValue($("#sourceEditor-solution").text().trim());
            }
        });
        $("#codeEditor-solution-button").on("click", function () {
            var message = "Confirm that you would like to see the solution.";
            if (codeEditorCM.getValue().trim().length > 0) {
                message += "\nWARNING: The code that you've already entered will be gone forever.";
            }
            if (confirm(message)) {
                codeEditorCM.setValue($("#codeEditor-solution").text().trim());
            }
        });
        $("#rendering-solution-button").on("click", function () {
            var message = "Confirm that you would like to see the solution.";
            if (matchersEditorCM.getValue().trim().length > 0) {
                message += "\nWARNING: That code that you've already entered will be forever lost.";
            }
            if (confirm(message)) {
                $("#rendering-resource").val($("#rendering-resource-solution").text().trim());
                matchersEditorCM.setValue($("#matchersEditor-solution").text().trim());
            }
        });

        updateLogginStatus();

        function updateLogginStatus() {
            if (profile) {
                $('.authenticatedOnly').show();
                $('#login-div').html('Logged in as ' + profile.login + ' (Logout)');
                $('#logout-link').click(function () {
                    profile = null;
                    updateLogginStatus();
                    return false;
                });
                var repo = gh.getRepo(profile.login, 'lodide-saved-contents');
                repo.getTree("master").then(function (r) {
                    var tree = r.data.tree
                    //for (var i = 0; i < tree.length;i++) {
                    //    var e = tree[i];
                    tree.forEach(function (e) {
                        console.log(e);
                        repo.getContents('master', e.path, 'raw').then(function (response) {
                            console.log("Contents of: " + e.path);
                            console.log(response.data);
                        });
                    });
                }).catch(function (e) {
                    alert("e: " + e);
                });
            } else {
                $('.authenticatedOnly').hide();
                $('#login-div').html('Login with GitHub');
                $('#login-link').click(function () {
                    $('#login-dialog').modal("show");
                    return false;
                });
            }
        }

        var loginButtonAction = function (auth) {
            gh = new GitHub(auth);
            var user = gh.getUser();
            console.log(user);
            user.getProfile().then(function (response) {
                profile = response.data;
                console.log(profile);
                updateLogginStatus();
                $('#login-dialog').modal('hide');
            });

        }

        $('#personalAccessTokenLoginButton').click(function () {
            if ($('#saveCredentialForLater').prop("checked")) {
                localStorage.setItem("personalAccessToken", $('#personalAccessToken').val());
            } else {
                localStorage.removeItem("personalAccessToken");
            }
            loginButtonAction({
                token: $('#personalAccessToken').val(),
            });
        });

        $('#passwordLoginButton').click(function () {
            loginButtonAction({
                'username': $('#userName').val(),
                'password': $('#password').val()
            });
        });

        $("#saveButton").click(function () {
            $("#fileNameDialog").modal("show");
        });

        $("#saveButton2").click(function () {
            var fileName = $("#fileName").val();
            if (!fileName.endsWith(".ttl")) {
                fileName = fileName + ".ttl";
            }
            var repo = gh.getRepo(profile.login, 'lodide-saved-contents');
            repo.listBranches().then(writeFile).catch(function (e) {
                console.log("failed to write file, will attempt to create repo");
                console.log(e);
                //create new repository
                gh.getUser().createRepo({
                    "name": "lodide-saved-contents",
                    "description": "A repository for saving http://lodide.io/ projects.",
                    "homepage": "http://lodide.io/",
                    "private": false,
                    "has_issues": false,
                    "has_wiki": false,
                    "has_downloads": false
                }).then(writeFile)
                        .catch(function (a) {
                            alert("error: " + a)
                        });
            });
            function writeFile() {
                serializeCurrentState().then(function (fileContent) {
                    repo.writeFile('master', fileName, fileContent,
                            "Run it on http://lodide.io/?exercise=https://raw.githubusercontent.com/" + profile.login + "/lodide-saved-contents/master/" + fileName, {}).then(function (r) {
                        alert("saved file: " + fileName);
                        console.log(r);
                    });
                }).catch(function (e) {
                    console.log("Error serializing:");
                    console.log(e);
                    alert("Serialization failed, see log");
                });
            }
            function serializeCurrentState() {
                var g = new rdf.Graph();
                var exercise = rdf.createNamedNode(""); //rdf-ext supports relative IRIs
                g.add(rdf.createTriple(exercise, rdfNs("type"), lodIdeNs("Exercise")));
                g.add(rdf.createTriple(exercise, lodIdeNs("intro"), rdf.createLiteral($("#intro").html())));
                g.add(rdf.createTriple(exercise, lodIdeNs("finalWords"),
                        rdf.createLiteral($("#finalWords").html())));
                var dataSource = rdf.createBlankNode();
                g.add(rdf.createTriple(exercise, lodIdeNs("dataSource"), dataSource));
                if ($("#dataSource-taskDescription").length > 0) {
                    g.add(rdf.createTriple(dataSource, lodIdeNs("taskDescription"),
                            rdf.createLiteral($("#dataSource-taskDescription").html())));
                }
                if ($("#sourceURI-solution").html()) {
                    g.add(rdf.createTriple(dataSource, lodIdeNs("taskSolutionResource"),
                            rdf.createNamedNode($("#sourceURI-solution").html())));
                }
                if ($('#rdfSource-uri').is(":visible")) {
                    g.add(rdf.createTriple(dataSource, lodIdeNs("taskSolutionResourceCurrent"),
                            rdf.createLiteral($("#sourceURI").val())));
                }
                if ($('#rdfSource-directInput').is(":visible")) {
                    g.add(rdf.createTriple(dataSource, lodIdeNs("taskSolutionCodeCurrent"),
                            rdf.createLiteral(rdfDataEditorCM.getValue())));
                }
                var dataProcessing = rdf.createBlankNode();
                g.add(rdf.createTriple(exercise, lodIdeNs("dataProcessing"), dataProcessing));
                if ($("#dataProcessing-taskDescription").length > 0) {
                    g.add(rdf.createTriple(dataProcessing, lodIdeNs("taskDescription"),
                            rdf.createLiteral($("#dataProcessing-taskDescription").html())));
                }
                g.add(rdf.createTriple(dataProcessing, lodIdeNs("taskSolutionCode"),
                        rdf.createLiteral($("#codeEditor-solution").html())));
                g.add(rdf.createTriple(dataProcessing, lodIdeNs("taskSolutionCodeCurrent"),
                        rdf.createLiteral(codeEditorCM.getValue())));
                if ($("#dataRenderingTitle").length > 0) {
                    var dataRendering = rdf.createBlankNode();
                    g.add(rdf.createTriple(exercise, lodIdeNs("dataRendering"), dataRendering));
                    if ($("#dataRendering-taskDescription").length > 0) {
                        g.add(rdf.createTriple(dataRendering, lodIdeNs("taskDescription"),
                                rdf.createLiteral($("#dataRendering-taskDescription").html())));
                    }
                    g.add(rdf.createTriple(dataRendering, lodIdeNs("taskSolutionCode"),
                            rdf.createLiteral($("#matchersEditor-solution").html())));
                    g.add(rdf.createTriple(dataRendering, lodIdeNs("taskSolutionCodeCurrent"),
                            rdf.createLiteral(matchersEditorCM.getValue())));
                    g.add(rdf.createTriple(dataRendering, lodIdeNs("taskSolutionResource"),
                            rdf.createNamedNode($("#rendering-resource-solution").html())));
                    g.add(rdf.createTriple(dataRendering, lodIdeNs("taskSolutionResourceCurrent"),
                            rdf.createLiteral($("#rendering-resource").val())));
                }
                return rdf.serializers["text/turtle"].serialize(g).then(function (turtle) {
                    return turtle;
                });
            }
            function lodIdeNs(localName) {
                return rdf.createNamedNode("http://ontology.lodide.io/" + localName);
            }
            function rdfNs(localName) {
                return rdf.createNamedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#" + localName);
            }
        });

        $(".exerciseIndexLink").click(function (e) {
            var exerciseArea = $("#exercise");
            exerciseArea.hide();
            var exerciseIndexArea = $("#exerciseIndex");

            if (exerciseIndexArea.is(":visible")) {
                exerciseIndexArea.addClass("fetch");
                exerciseIndexArea.attr("resource", "index.ttl");
                LD2h.expand();
            } else {
                exerciseIndexArea.show();
            }
            window.previousLocation = window.location.toString();
            window.history.pushState({}, "", "exercise-index.html");
            $("#lodIDEMenu").removeClass("active");
            $("#exerciseIndexMenu").addClass("active");
            e.preventDefault();
        });

        $(".lodIDELink").click(function () {
            var exerciseArea = $("#exercise");
            exerciseArea.show();
            var exerciseIndexArea = $("#exerciseIndex");
            exerciseIndexArea.hide();
            window.history.pushState({}, "", window.previousLocation);
            $("#lodIDEMenu").addClass("active");
            $("#exerciseIndexMenu").removeClass("active");
        });

    });

});
<|endoftext|>


<commit_before>/**
 * HUD
 */
Garnish.HUD = Garnish.Base.extend({

	/**
	 * Constructor
	 */
	init: function(trigger, contentsHtml, settings) {

		this.$trigger = $(trigger);
		this.setSettings(settings, Garnish.HUD.defaults);

		this.showing = false;

		this.$hud = $('
').appendTo(Garnish.$bod);
		this.$tip = $('
').appendTo(this.$hud);
		this.$contents = $('
').appendTo(this.$hud).html(contentsHtml);

		this.show();

		// Prevent clicks on the HUD from hiding itself
		this.addListener(this.$hud, 'click', function(ev)
		{
			ev.stopPropagation();
		});
	},

	/**
	 * Show
	 */
	show: function(ev) {

		if (this.showing)
		{
			return;
		}

		if (Garnish.HUD.active)
		{
			Garnish.HUD.active.hide();
		}

		this.$hud.show();

		// -------------------------------------------
		//  Get all relevant dimensions, lengths, etc
		// -------------------------------------------

		this.windowWidth = Garnish.$win.width();
		this.windowHeight = Garnish.$win.height();

		this.windowScrollLeft = Garnish.$win.scrollLeft();
		this.windowScrollTop = Garnish.$win.scrollTop();

		// get the trigger element's dimensions
		this.triggerWidth = this.$trigger.outerWidth();
		this.triggerHeight = this.$trigger.outerHeight();

		// get the offsets for each side of the trigger element
		this.triggerOffset = this.$trigger.offset();
		this.triggerOffsetRight = this.triggerOffset.left + this.triggerWidth;
		this.triggerOffsetBottom = this.triggerOffset.top + this.triggerHeight;
		this.triggerOffsetLeft = this.triggerOffset.left;
		this.triggerOffsetTop = this.triggerOffset.top;

		// get the HUD dimensions
		this.width = this.$hud.width();
		this.height = this.$hud.height();

		// get the minimum horizontal/vertical clearance needed to fit the HUD
		this.minHorizontalClearance = this.width + this.settings.triggerSpacing + this.settings.windowSpacing;
		this.minVerticalClearance = this.height + this.settings.triggerSpacing + this.settings.windowSpacing;

		// find the actual available right/bottom/left/top clearances
		this.rightClearance = this.windowWidth + this.windowScrollLeft - this.triggerOffsetRight;
		this.bottomClearance = this.windowHeight + this.windowScrollTop - this.triggerOffsetBottom;
		this.leftClearance = this.triggerOffsetLeft - this.windowScrollLeft;
		this.topClearance = this.triggerOffsetTop - this.windowScrollTop;

		// -------------------------------------------
		//  Where are we putting it?
		//   - Ideally, we'll be able to find a place to put this where it's not overlapping the trigger at all.
		//     If we can't find that, either put it to the right or below the trigger, depending on which has the most room.
		// -------------------------------------------

		// below?
		if (this.bottomClearance >= this.minVerticalClearance)
		{
			var top = this.triggerOffsetBottom + this.settings.triggerSpacing;
			this.$hud.css('top', top);
			this._setLeftPos();
			this._setTipClass('top');
		}
		// to the right?
		else if (this.rightClearance >= this.minHorizontalClearance)
		{
			var left = this.triggerOffsetRight + this.settings.triggerSpacing;
			this.$hud.css('left', left);
			this._setTopPos();
			this._setTipClass('left');
		}
		// to the left?
		else if (this.leftClearance >= this.minHorizontalClearance)
		{
			var left = this.triggerOffsetLeft - (this.width + this.settings.triggerSpacing);
			this.$hud.css('left', left);
			this._setTopPos();
			this._setTipClass('right');
		}
		// above?
		else if (this.topClearance >= this.minVerticalClearance)
		{
			var top = this.triggerOffsetTop - (this.height + this.settings.triggerSpacing);
			this.$hud.css('top', top);
			this._setLeftPos();
			this._setTipClass('bottom');
		}
		// ok, which one comes the closest -- right or bottom?
		else
		{
			var rightClearanceDiff = this.minHorizontalClearance - this.rightClearance,
				bottomClearanceDiff = this.minVerticalClearance - this.bottomClearance;

			if (rightClearanceDiff >= bottomClearanceDiff)
			{
				var left = this.windowWidth - (this.width + this.settings.windowSpacing),
					minLeft = this.triggerOffsetLeft + this.settings.triggerSpacing;
				if (left < minLeft) left = minLeft;
				this.$hud.css('left', left);
				this._setTopPos();
				this._setTipClass('left');
			}
			else
			{
				var top = this.windowHeight - (this.height + this.settings.windowSpacing),
					minTop = this.triggerOffsetTop + this.settings.triggerSpacing;
				if (top < minTop) top = minTop;
				this.$hud.css('top', top);
				this._setLeftPos();
				this._setTipClass('top');
			}
		}

		if (ev && ev.stopPropagation)
		{
			ev.stopPropagation();
		}

		this.addListener(Garnish.$bod, 'click', 'hide');

		if (this.settings.closeBtn)
		{
			this.addListener(this.settings.closeBtn, 'activate', 'hide');
		}

		this.showing = true;
		Garnish.HUD.active = this;

		// onShow callback
		this.settings.onShow();
	},

	/**
	 * Set Top
	 */
	_setTopPos: function()
	{
		var maxTop = (this.windowHeight + this.windowScrollTop) - (this.height + this.settings.windowSpacing),
			minTop = (this.windowScrollTop + this.settings.windowSpacing),

			triggerCenter = this.triggerOffsetTop + Math.round(this.triggerHeight / 2),
			top = triggerCenter - Math.round(this.height / 2);

		// adjust top position as needed
		if (top > maxTop) top = maxTop;
		if (top < minTop) top = minTop;

		this.$hud.css('top', top);

		// set the tip's top position
		var tipTop = (triggerCenter - top) - (this.settings.tipWidth / 2);
		this.$tip.css({ top: tipTop, left: '' });
	},

	/**
	 * Set Left
	 */
	_setLeftPos: function()
	{
		var maxLeft = (this.windowWidth + this.windowScrollLeft) - (this.width + this.settings.windowSpacing),
			minLeft = (this.windowScrollLeft + this.settings.windowSpacing),

			triggerCenter = this.triggerOffsetLeft + Math.round(this.triggerWidth / 2),
			left = triggerCenter - Math.round(this.width / 2);

		// adjust left position as needed
		if (left > maxLeft) left = maxLeft;
		if (left < minLeft) left = minLeft;

		this.$hud.css('left', left);

		// set the tip's left position
		var tipLeft = (triggerCenter - left) - (this.settings.tipWidth / 2);
		this.$tip.css({ left: tipLeft, top: '' });
	},

	/**
	 * Set Tip Class
	 */
	_setTipClass: function(c)
	{
		if (this.tipClass)
		{
			this.$tip.removeClass(this.tipClass);
		}

		this.tipClass = this.settings.tipClass+'-'+c;
		this.$tip.addClass(this.tipClass);
	},

	/**
	 * Hide
	 */
	hide: function()
	{
		this.$hud.hide();
		this.showing = false;

		Garnish.HUD.active = null;

		// onHide callback
		this.settings.onHide();
	}
},
{
	defaults: {
		hudClass: 'hud',
		tipClass: 'tip',
		contentsClass: 'contents',
		triggerSpacing: 7,
		windowSpacing: 20,
		tipWidth: 8,
		onShow: $.noop,
		onHide: $.noop,
		closeBtn: null
	}
});
<commit_msg>HUD tweaks<commit_after>/**
 * HUD
 */
Garnish.HUD = Garnish.Base.extend({

	/**
	 * Constructor
	 */
	init: function(trigger, bodyContents, settings) {

		this.$trigger = $(trigger);
		this.setSettings(settings, Garnish.HUD.defaults);

		this.showing = false;

		this.$hud = $('
').appendTo(Garnish.$bod);
		this.$tip = $('
').appendTo(this.$hud);
		this.$body = $('
').appendTo(this.$hud).append(bodyContents)

		this.show();

		// Prevent clicks on the HUD from hiding itself
		this.addListener(this.$hud, 'click', function(ev)
		{
			ev.stopPropagation();
		});
	},

	/**
	 * Show
	 */
	show: function(ev) {

		if (this.showing)
		{
			return;
		}

		if (Garnish.HUD.active)
		{
			Garnish.HUD.active.hide();
		}

		this.$hud.show();

		// -------------------------------------------
		//  Get all relevant dimensions, lengths, etc
		// -------------------------------------------

		this.windowWidth = Garnish.$win.width();
		this.windowHeight = Garnish.$win.height();

		this.windowScrollLeft = Garnish.$win.scrollLeft();
		this.windowScrollTop = Garnish.$win.scrollTop();

		// get the trigger element's dimensions
		this.triggerWidth = this.$trigger.outerWidth();
		this.triggerHeight = this.$trigger.outerHeight();

		// get the offsets for each side of the trigger element
		this.triggerOffset = this.$trigger.offset();
		this.triggerOffsetRight = this.triggerOffset.left + this.triggerWidth;
		this.triggerOffsetBottom = this.triggerOffset.top + this.triggerHeight;
		this.triggerOffsetLeft = this.triggerOffset.left;
		this.triggerOffsetTop = this.triggerOffset.top;

		// get the HUD dimensions
		this.width = this.$hud.outerWidth();
		this.height = this.$hud.outerHeight();

		// get the minimum horizontal/vertical clearance needed to fit the HUD
		this.minHorizontalClearance = this.width + this.settings.triggerSpacing + this.settings.windowSpacing;
		this.minVerticalClearance = this.height + this.settings.triggerSpacing + this.settings.windowSpacing;

		// find the actual available right/bottom/left/top clearances
		this.rightClearance = this.windowWidth + this.windowScrollLeft - this.triggerOffsetRight;
		this.bottomClearance = this.windowHeight + this.windowScrollTop - this.triggerOffsetBottom;
		this.leftClearance = this.triggerOffsetLeft - this.windowScrollLeft;
		this.topClearance = this.triggerOffsetTop - this.windowScrollTop;

		// -------------------------------------------
		//  Where are we putting it?
		//   - Ideally, we'll be able to find a place to put this where it's not overlapping the trigger at all.
		//     If we can't find that, either put it to the right or below the trigger, depending on which has the most room.
		// -------------------------------------------

		// below?
		if (this.bottomClearance >= this.minVerticalClearance)
		{
			var top = this.triggerOffsetBottom + this.settings.triggerSpacing;
			this.$hud.css('top', top);
			this._setLeftPos();
			this._setTipClass('top');
		}
		// above?
		else if (this.topClearance >= this.minVerticalClearance)
		{
			var top = this.triggerOffsetTop - (this.height + this.settings.triggerSpacing);
			this.$hud.css('top', top);
			this._setLeftPos();
			this._setTipClass('bottom');
		}
		// to the right?
		else if (this.rightClearance >= this.minHorizontalClearance)
		{
			var left = this.triggerOffsetRight + this.settings.triggerSpacing;
			this.$hud.css('left', left);
			this._setTopPos();
			this._setTipClass('left');
		}
		// to the left?
		else if (this.leftClearance >= this.minHorizontalClearance)
		{
			var left = this.triggerOffsetLeft - (this.width + this.settings.triggerSpacing);
			this.$hud.css('left', left);
			this._setTopPos();
			this._setTipClass('right');
		}
		// ok, which one comes the closest -- right or bottom?
		else
		{
			var rightClearanceDiff = this.minHorizontalClearance - this.rightClearance,
				bottomClearanceDiff = this.minVerticalClearance - this.bottomClearance;

			if (rightClearanceDiff >= bottomClearanceDiff)
			{
				var left = this.windowWidth - (this.width + this.settings.windowSpacing),
					minLeft = this.triggerOffsetLeft + this.settings.triggerSpacing;
				if (left < minLeft) left = minLeft;
				this.$hud.css('left', left);
				this._setTopPos();
				this._setTipClass('left');
			}
			else
			{
				var top = this.windowHeight - (this.height + this.settings.windowSpacing),
					minTop = this.triggerOffsetTop + this.settings.triggerSpacing;
				if (top < minTop) top = minTop;
				this.$hud.css('top', top);
				this._setLeftPos();
				this._setTipClass('top');
			}
		}

		if (ev && ev.stopPropagation)
		{
			ev.stopPropagation();
		}

		this.addListener(Garnish.$bod, 'click', 'hide');

		if (this.settings.closeBtn)
		{
			this.addListener(this.settings.closeBtn, 'activate', 'hide');
		}

		this.showing = true;
		Garnish.HUD.active = this;

		// onShow callback
		this.settings.onShow();
	},

	/**
	 * Set Top
	 */
	_setTopPos: function()
	{
		var maxTop = (this.windowHeight + this.windowScrollTop) - (this.height + this.settings.windowSpacing),
			minTop = (this.windowScrollTop + this.settings.windowSpacing),

			triggerCenter = this.triggerOffsetTop + Math.round(this.triggerHeight / 2),
			top = triggerCenter - Math.round(this.height / 2);

		// adjust top position as needed
		if (top > maxTop) top = maxTop;
		if (top < minTop) top = minTop;

		this.$hud.css('top', top);

		// set the tip's top position
		var tipTop = (triggerCenter - top) - (this.settings.tipWidth / 2);
		this.$tip.css({ top: tipTop, left: '' });
	},

	/**
	 * Set Left
	 */
	_setLeftPos: function()
	{
		var maxLeft = (this.windowWidth + this.windowScrollLeft) - (this.width + this.settings.windowSpacing),
			minLeft = (this.windowScrollLeft + this.settings.windowSpacing),

			triggerCenter = this.triggerOffsetLeft + Math.round(this.triggerWidth / 2),
			left = triggerCenter - Math.round(this.width / 2);

		// adjust left position as needed
		if (left > maxLeft) left = maxLeft;
		if (left < minLeft) left = minLeft;

		this.$hud.css('left', left);

		// set the tip's left position
		var tipLeft = (triggerCenter - left) - (this.settings.tipWidth / 2);
		this.$tip.css({ left: tipLeft, top: '' });
	},

	/**
	 * Set Tip Class
	 */
	_setTipClass: function(c)
	{
		if (this.tipClass)
		{
			this.$tip.removeClass(this.tipClass);
		}

		this.tipClass = this.settings.tipClass+'-'+c;
		this.$tip.addClass(this.tipClass);
	},

	/**
	 * Hide
	 */
	hide: function()
	{
		this.$hud.hide();
		this.showing = false;

		Garnish.HUD.active = null;

		// onHide callback
		this.settings.onHide();
	}
},
{
	defaults: {
		hudClass: 'hud',
		tipClass: 'tip',
		bodyClass: 'body',
		triggerSpacing: 7,
		windowSpacing: 20,
		tipWidth: 8,
		onShow: $.noop,
		onHide: $.noop,
		closeBtn: null
	}
});
<|endoftext|>


<commit_before>var Bell 	= require("bell");
var Path 	= require("path");
var Joi 	= require("joi");
var config 	= require('../config');
var users 	= require('../models/users');
var designs = require('../models/designs');

module.exports = {

	serveFile: {
		auth: false,
		handler: {
			directory: {
				path: '../public'
			}
		}
	},

	login: {
		 auth: {
			strategy: "google"
		 },
		 handler: function (request, reply) {
			if (request.auth.isAuthenticated) {

				var gPlus = request.auth.credentials;
				console.dir(gPlus,{depth:null});
				var profile = {
					username 	: gPlus.profile.displayName,
					email 		: gPlus.profile.email,
					picture 	: gPlus.profile.raw.picture,
					hasAccount	: false,
					isAdmin		: false
				};

				// NB. We are assuming user.username will be set to profile.username
				 users.getUser(profile.username, function(err, user){
					if (err) console.log(err);

					if (user) profile.hasAccount = true;
					if (user) {
						if (user.isAdmin) profile.isAdmin = true;
					}

					request.auth.session.clear();
					request.auth.session.set(profile);

					return profile.hasAccount ? reply.redirect('/') : reply.redirect('/signup');
				 });
			}
			else {
				return reply.redirect('/');
			}

		}
	},

	logout: {
		handler: function (request, reply ){
			request.auth.session.clear();
			return reply.redirect('/');
		}
	},

	homeView: {
		auth: false, //to prevent redirect loop from session cookie
		handler: function (request, reply ){
			return reply.view('index');
		}
	},

	signupView: {
		auth: {mode: 'required'},
		handler: function (request, reply ){
			// return request.auth.credentials.hasAccount ? reply.redirect('/profile/'+request.auth.credentials.username) : reply.view('signup');
			return reply.view('signup');
		}
	},

	signupSubmit: {
		auth: {mode: 'required'},
		// validate:{
		// 	payload: <joiObjectName>,
		// },
		payload : {
			maxBytes: 5242880, //5MB User feedback on hitting the limit required. Prevent attachment of too large an image, submit attempt should never fail.
			output: 'file',
			parse: true
		},
		handler: function (request, reply ){
			console.dir(request.auth.credentials);
			console.log('Payload:');
			console.dir(request.payload);
			var user = request.payload;
			var newUserObj = {
				username: request.auth.credentials.username,
				email: user.email,
				firstName: user.firstname,
				lastName: user.lastname,
				dateJoined: new Date()
			};
			// Construct address as string
			newUserObj.address = '';
			newUserObj.address += user.addressFirstLine + '\n';
			if(user.addressSecondLine) newUserObj.address += user.addressSecondLine + '\n';
			newUserObj.address += user.addressTown + '\n';
			if(user.addressCounty) newUserObj.address += user.addressCounty + '\n';
			newUserObj.address += user.addressPostcode;

			if (user.phonenumber) newUserObj.phoneNumber = user.phoneNumber;
			if (user.bio) newUserObj.bio = user.bio;
			// TODO links. ??? -> array
			var profileImgPath = null;
			if (user.profileImage) profileImgPath = user.profileImage.path;
			if (user.admin === 'Yes') newUserObj.isAdmin = true; //!!!! REMOVE IN PRODUCTION

			// ADD NEW USER TO DB
			users.createUser(newUserObj, profileImgPath, function(err, user){
				if (err) {
					console.error(err);
					reply.view('signup', {error: err}); //TODO use error in template. User needs to know signup failed
				}
				else {
					// !!! CANT EDIT request.auth.creds - doesnt save
					// request.auth.credentials.hasAccount = true;
					// if (user.isAdmin) request.auth.credentials.isAdmin = true; //!!!! REMOVE IN PRODUCTION
					request.auth.session.set('hasAccount', true);
					if (user.isAdmin) request.auth.session.set('isAdmin', true); //!!!! REMOVE IN PRODUCTION
					console.dir(request.auth.credentials);
					reply.redirect('/profile/'+user.username);
				}
			});
		}
	},

	profileView: {
		handler: function (request, reply ){
			var userName = request.params.username;
			users.getUser(userName, function(err, user){
				if (err) {
					console.error(err);
					return reply.redirect('/'); //TODO pass failure info to user e.g.'server error'. How? if can't pass context data to redirect, try adding query string to url, and parse
				}
				else if (user) {
					return reply.view('profile', {user: user});
				}
				else {
					return reply.redirect('/'); //TODO pass failure info to user e.g.'user not found'. How? if can't pass context data to redirect, try adding query string to url, and parse !!OR!! put in cookie
					// Could simply reply with home view, butshould be redirect as not requested resource.
				}
			});
		}
	},

	editUser: {
		auth: {mode: 'required'},
		handler: function (request, reply ){

			var editor = request.params.username;
			var updatedField = request.payload;

			users.updateUser(editor, updatedField, function(err, result){
				if (err) {
					return reply(err);
				}
				if (updatedField.bio) {
					//think this is almost there but not quite sure how to make the result bit work
					return reply.redirect("profile");
				}
			});
			// UPDATE USER DB ENTRY
			// RETURN VIEW OF UPDATED PROFILE
			//return reply.view('profile');
		}
	},

	deleteUser: {
		auth: {mode: 'required'},
		handler: function (request, reply ){
			// DELETE USER DB ENTRY
			// REDIRECT TO LOGOUT? better/more common to be taken back to the homeview(gallery)
			return reply.redirect('/');
		}
	},

	uploadView: {
		handler: function (request, reply ){
			console.log(request.auth.credentials);
			return request.auth.credentials.hasAccount ? reply.view('upload') : reply.redirect('signup');
		}
	},

	// function createDesign(designData, mainImgPath, imageArray, fileArray, callback)
	uploadNewDesign: {
		auth: {mode: 'required'},
		// validate:{
		// 	payload: <joiObjectName>,
		// },
		payload : {
			maxBytes: 209715200, //20MB? May need to be greater, and user feedback on hitting the limit required. Prevent attachment of too large a collection of images, submit attempt should never fail.
			output: 'data',
			parse: true
		},
		handler: function (request, reply ){
			console.dir(request.payload);
			// ADD NEW SUBMISSION TO DB
			// 1. get user doc from db
			var userName = request.auth.credentials.username;
			users.getUser(userName, function(err, user){
				if (err) {
					console.error(err);
					return reply.redirect('/'); //TODO: error handling. redirect? or same view with error?
				}
				// 2. save payload data to new design doc
				else if (user) {
					var design = request.payload;
					var newDesignObj = {
						designerUserName: userName,
						designerId: user._id,
						name: design.name,
						description: design.description,
						dateAdded: new Date()
					};
					if (design.additionalInfo) newDesignObj.additionalInfo = design.additionalInfo;
					var mainImgPath = request.payload.files.mainImage.path;
					var imageArray = [];
					var fileArray = [];
					// TODO collect addImages and files from payload and put paths in array
					designs.createDesign(newDesignObj, mainImgPath, imageArray, fileArray, function(err1, design){
						if (err1) {
							console.error(err1);
							return reply.redirect('/'); //TODO <--
						}
						// 3. save design doc ObjId to user designs[]
						else {
							console.log('design saved');
							console.dir(design);
							var designId = design._id;
							user.designIds.push(designId);
							user.save(function(err2, savedUser){
								if (err2) {
									console.error(err2);
									// TODO delete design if saving designId fails??? Maybe add a scheduled task that searches designs by username, checks if indexed in user
									return reply.redirect('/'); // <--- TODO
								}
								else {
									console.dir(savedUser);
									return reply.view('profile', {user: savedUser.username});
								}
							});
						}
					});
				}
				else {
					return reply.redirect('/'); //TODO <- user not found response. should never happen...
				}
			});

			return reply.redirect('profile/'+request.auth.credentials.username);
		}
	},

	designView: {
		handler: function (request, reply ){
			return reply.view('design');
		}
	},

	preorderDesign: {
		handler: function (request, reply ){
			// REQUIRE AUTH!
			// ADD UPVOTE/PREORDER TO DB
			// redirect to design view with upvote/preorder registered
			return reply.redirect('designs/{username}/{design}');
		}
	},

	adminView: {
				// check auth for isAdmin - add it on login
		handler: function (request, reply ){
			// REQUIRE AUTH!
			return reply.view('admin');
		}
	},

	adminDesignView:  {
		// check auth for isAdmin - add it on login
		handler: function (request, reply ){
			// REQUIRE AUTH!
			return reply.view('admin');
		}
	},

	adminApproveDesign:  {
		handler: function (request, reply ){
			// REQUIRE AUTH!
			// approve new design for gallery display -toggle a bool in the db?
			return reply.redirect('admin');
		}
	},

	adminBinDesign:  {
		handler: function (request, reply ){
			// REQUIRE AUTH!
			// reject a design. purge all db refs to it.
			return reply.redirect('admin');
		}
	}
};
<commit_msg>comment<commit_after>var Bell 	= require("bell");
var Path 	= require("path");
var Joi 	= require("joi");
var config 	= require('../config');
var users 	= require('../models/users');
var designs = require('../models/designs');

module.exports = {

	serveFile: {
		auth: false,
		handler: {
			directory: {
				path: '../public'
			}
		}
	},

	login: {
		 auth: {
			strategy: "google"
		 },
		 handler: function (request, reply) {
			if (request.auth.isAuthenticated) {

				var gPlus = request.auth.credentials;
				console.dir(gPlus,{depth:null});
				var profile = {
					username 	: gPlus.profile.displayName,
					email 		: gPlus.profile.email,
					picture 	: gPlus.profile.raw.picture,
					hasAccount	: false,
					isAdmin		: false
				};

				// NB. We are assuming user.username will be set to profile.username
				 users.getUser(profile.username, function(err, user){
					if (err) console.log(err);

					if (user) profile.hasAccount = true;
					if (user) {
						if (user.isAdmin) profile.isAdmin = true;
					}

					request.auth.session.clear();
					request.auth.session.set(profile);

					return profile.hasAccount ? reply.redirect('/') : reply.redirect('/signup');
				 });
			}
			else {
				return reply.redirect('/');
			}

		}
	},

	logout: {
		handler: function (request, reply ){
			request.auth.session.clear();
			return reply.redirect('/');
		}
	},

	homeView: {
		auth: false, //to prevent redirect loop from session cookie
		handler: function (request, reply ){
			return reply.view('index');
		}
	},

	signupView: {
		auth: {mode: 'required'},
		handler: function (request, reply ){
			// return request.auth.credentials.hasAccount ? reply.redirect('/profile/'+request.auth.credentials.username) : reply.view('signup');
			return reply.view('signup');
		}
	},

	signupSubmit: {
		auth: {mode: 'required'},
		// validate:{
		// 	payload: <joiObjectName>,
		// },
		payload : {
			maxBytes: 5242880, //5MB User feedback on hitting the limit required. Prevent attachment of too large an image, submit attempt should never fail.
			output: 'file',
			parse: true
		},
		handler: function (request, reply ){
			console.dir(request.auth.credentials);
			console.log('Payload:');
			console.dir(request.payload);
			var user = request.payload;
			var newUserObj = {
				username: request.auth.credentials.username,
				email: user.email,
				firstName: user.firstname,
				lastName: user.lastname,
				dateJoined: new Date()
			};
			// Construct address as string
			newUserObj.address = '';
			newUserObj.address += user.addressFirstLine + '\n';
			if(user.addressSecondLine) newUserObj.address += user.addressSecondLine + '\n';
			newUserObj.address += user.addressTown + '\n';
			if(user.addressCounty) newUserObj.address += user.addressCounty + '\n';
			newUserObj.address += user.addressPostcode;

			if (user.phonenumber) newUserObj.phoneNumber = user.phoneNumber;
			if (user.bio) newUserObj.bio = user.bio;
			// TODO links. ??? -> array
			var profileImgPath = null;
			if (user.profileImage) profileImgPath = user.profileImage.path;
			if (user.admin === 'Yes') newUserObj.isAdmin = true; //!!!! REMOVE IN PRODUCTION

			// ADD NEW USER TO DB
			users.createUser(newUserObj, profileImgPath, function(err, user){
				if (err) {
					console.error(err);
					reply.view('signup', {error: err}); //TODO use error in template. User needs to know signup failed
				}
				else {
					// !!! CANT EDIT request.auth.creds - doesnt save
					// request.auth.credentials.hasAccount = true;
					// if (user.isAdmin) request.auth.credentials.isAdmin = true; //!!!! REMOVE IN PRODUCTION
					request.auth.session.set('hasAccount', true);
					if (user.isAdmin) request.auth.session.set('isAdmin', true); //!!!! REMOVE IN PRODUCTION
					console.dir(request.auth.credentials);
					reply.redirect('/profile/'+user.username);
				}
			});
		}
	},

	profileView: {
		handler: function (request, reply ){
			var userName = request.params.username;
			users.getUser(userName, function(err, user){
				if (err) {
					console.error(err);
					return reply.redirect('/'); //TODO pass failure info to user e.g.'server error'. How? if can't pass context data to redirect, try adding query string to url, and parse
				}
				else if (user) {
					return reply.view('profile', {user: user});
				}
				else {
					return reply.redirect('/'); //TODO pass failure info to user e.g.'user not found'. How? if can't pass context data to redirect, try adding query string to url, and parse !!OR!! put in cookie
					// Could simply reply with home view, butshould be redirect as not requested resource.
				}
			});
		}
	},

	// I suggest we take the username for this from request.auth.credentials, rather than url param as a security measure.
	// i.e. You can only edit/delete the profile you are logged in as.
	// Further, we could change the route to simply 'profile', or 'profile/edit' <- GET is the edit profile view, PUT and DEL are the edit/del operations
	editUser: {
		auth: {mode: 'required'},
		handler: function (request, reply ){

			var editor = request.params.username;
			var updatedField = request.payload;

			users.updateUser(editor, updatedField, function(err, result){
				if (err) {
					return reply(err);
				}
				if (updatedField.bio) {
					//think this is almost there but not quite sure how to make the result bit work
					return reply.redirect("profile");
				}
			});
			// UPDATE USER DB ENTRY
			// RETURN VIEW OF UPDATED PROFILE
			//return reply.view('profile');
		}
	},

	deleteUser: {
		auth: {mode: 'required'},
		handler: function (request, reply ){
			// DELETE USER DB ENTRY
			// REDIRECT TO LOGOUT? better/more common to be taken back to the homeview(gallery)
			return reply.redirect('/');
		}
	},

	uploadView: {
		handler: function (request, reply ){
			console.log(request.auth.credentials);
			return request.auth.credentials.hasAccount ? reply.view('upload') : reply.redirect('signup');
		}
	},

	// function createDesign(designData, mainImgPath, imageArray, fileArray, callback)
	uploadNewDesign: {
		auth: {mode: 'required'},
		// validate:{
		// 	payload: <joiObjectName>,
		// },
		payload : {
			maxBytes: 209715200, //20MB? May need to be greater, and user feedback on hitting the limit required. Prevent attachment of too large a collection of images, submit attempt should never fail.
			output: 'data',
			parse: true
		},
		handler: function (request, reply ){
			console.dir(request.payload);
			// ADD NEW SUBMISSION TO DB
			// 1. get user doc from db
			var userName = request.auth.credentials.username;
			users.getUser(userName, function(err, user){
				if (err) {
					console.error(err);
					return reply.redirect('/'); //TODO: error handling. redirect? or same view with error?
				}
				// 2. save payload data to new design doc
				else if (user) {
					var design = request.payload;
					var newDesignObj = {
						designerUserName: userName,
						designerId: user._id,
						name: design.name,
						description: design.description,
						dateAdded: new Date()
					};
					if (design.additionalInfo) newDesignObj.additionalInfo = design.additionalInfo;
					var mainImgPath = request.payload.files.mainImage.path;
					var imageArray = [];
					var fileArray = [];
					// TODO collect addImages and files from payload and put paths in array
					designs.createDesign(newDesignObj, mainImgPath, imageArray, fileArray, function(err1, design){
						if (err1) {
							console.error(err1);
							return reply.redirect('/'); //TODO <--
						}
						// 3. save design doc ObjId to user designs[]
						else {
							console.log('design saved');
							console.dir(design);
							var designId = design._id;
							user.designIds.push(designId);
							user.save(function(err2, savedUser){
								if (err2) {
									console.error(err2);
									// TODO delete design if saving designId fails??? Maybe add a scheduled task that searches designs by username, checks if indexed in user
									return reply.redirect('/'); // <--- TODO
								}
								else {
									console.dir(savedUser);
									return reply.view('profile', {user: savedUser.username});
								}
							});
						}
					});
				}
				else {
					return reply.redirect('/'); //TODO <- user not found response. should never happen...
				}
			});

			return reply.redirect('profile/'+request.auth.credentials.username);
		}
	},

	designView: {
		handler: function (request, reply ){
			return reply.view('design');
		}
	},

	preorderDesign: {
		handler: function (request, reply ){
			// REQUIRE AUTH!
			// ADD UPVOTE/PREORDER TO DB
			// redirect to design view with upvote/preorder registered
			return reply.redirect('designs/{username}/{design}');
		}
	},

	adminView: {
				// check auth for isAdmin - add it on login
		handler: function (request, reply ){
			// REQUIRE AUTH!
			return reply.view('admin');
		}
	},

	adminDesignView:  {
		// check auth for isAdmin - add it on login
		handler: function (request, reply ){
			// REQUIRE AUTH!
			return reply.view('admin');
		}
	},

	adminApproveDesign:  {
		handler: function (request, reply ){
			// REQUIRE AUTH!
			// approve new design for gallery display -toggle a bool in the db?
			return reply.redirect('admin');
		}
	},

	adminBinDesign:  {
		handler: function (request, reply ){
			// REQUIRE AUTH!
			// reject a design. purge all db refs to it.
			return reply.redirect('admin');
		}
	}
};
<|endoftext|>


<commit_before><commit_msg>Removed componentDidUpdate from Tabs component.<commit_after><|endoftext|>


<commit_before>var BigInteger = require('./jsbn/jsbn');
var sec = require('./jsbn/sec');
var base58 = require('./base58');
var Crypto = require('./crypto-js/crypto');
var util = require('./util');
var conv = require('./convert');
var Address = require('./address');
var ecdsa = require('./ecdsa');
var ECPointFp = require('./jsbn/ec').ECPointFp;

var ecparams = sec("secp256k1");

// input can be nothing, array of bytes, hex string, or base58 string
var ECKey = function (input,compressed) {
    if (!(this instanceof ECKey)) { return new ECKey(input); }
    if (!input) {
        // Generate new key
        var n = ecparams.getN();
        this.priv = ecdsa.getBigRandom(n);
        this.compressed = compressed || false;
    }
    else this.import(input,compressed)
};

ECKey.prototype.import = function (input,compressed) {
    function has(li,v) { return li.indexOf(v) >= 0 }
    function fromBin(x) { return BigInteger.fromByteArrayUnsigned(x) }
    this.priv =
          input instanceof ECKey                   ? input.priv
        : input instanceof BigInteger              ? input.mod(ecparams.getN())
        : util.isArray(input)                      ? fromBin(input.slice(0,32))
        : typeof input != "string"                 ? null
        : input.length == 51 && input[0] == '5'    ? fromBin(base58.checkDecode(input))
        : input.length == 52 && has('LK',input[0]) ? fromBin(base58.checkDecode(input))
        : has([64,65],input.length)                ? fromBin(conv.hexToBytes(input.slice(0,64)))
                                                   : null

    this.compressed =
          compressed !== undefined                 ? compressed
        : input instanceof ECKey                   ? input.compressed
        : input instanceof BigInteger              ? false
        : util.isArray(input)                      ? false
        : typeof input != "string"                 ? null
        : input.length == 51 && input[0] == '5'    ? false
        : input.length == 52 && has('LK',input[0]) ? true
        : input.length == 64                       ? false
        : input.length == 65                       ? true
                                                   : null
};

ECKey.prototype.getPub = function() {
    return ECPubKey(ecparams.getG().multiply(this.priv),this.compressed)
}

ECKey.prototype.export = function (format) {
    var bytes = this.priv.toByteArrayUnsigned();
    if (this.compressed)
         bytes.push(1)
    return format === "base58"    ? base58.checkEncode(bytes,128)
         : format === "wif"       ? base58.checkEncode(bytes,128)
         : format === "bin"       ? conv.bytesToString(bytes)
         : format === "bytes"     ? bytes
         : format === "hex"       ? conv.bytesToHex(bytes)
         :                          bytes
};

ECKey.prototype.toString = function (format) {
    return ''+this.export(format)
}

ECKey.prototype.getBitcoinAddress = function(v) {
    return this.getPub().getBitcoinAddress(v)
}

ECKey.prototype.add = function(key) {
    return ECKey(this.priv.add(ECKey(key).priv),this.compressed)
}

ECKey.prototype.multiply = function(key) {
    return ECKey(this.priv.multiply(ECKey(key).priv),this.compressed)
}

var ECPubKey = function(input,compressed) {
    if (!(this instanceof ECPubKey)) { return new ECPubKey(input,compressed); }
    if (!input) {
        // Generate new key
        var n = ecparams.getN();
        this.pub = ecparams.getG().multiply(ecdsa.getBigRandom(n))
        this.compressed = compressed || false;
    }
    else this.import(input,compressed)
}

ECPubKey.prototype.import = function(input,compressed) {
    var decode = function(x) { return ECPointFp.decodeFrom(ecparams.getCurve(), x) }
    this.pub =
          input instanceof ECPointFp ? input
        : input instanceof ECKey     ? ecparams.getG().multiply(input.priv)
        : input instanceof ECPubKey  ? input.pub
        : typeof input == "string"   ? decode(conv.hexToBytes(input))
        : util.isArray(input)        ? decode(input)
                                     : ecparams.getG().multiply(ecdsa.getBigRandom(ecparams.getN()))

    this.compressed =
          arguments.length > 1       ? compressed
        : input instanceof ECPointFp ? input.compressed
        : input instanceof ECPubKey  ? input.compressed
                                     : (this.pub[0] < 4)
}

ECPubKey.prototype.add = function(key) {
    return ECPubKey(this.pub.add(ECPubKey(key).pub),this.compressed)
}

ECPubKey.prototype.multiply = function(key) {
    return ECPubKey(this.pub.multiply(ECKey(key).priv),this.compressed)
}

ECPubKey.prototype.export = function(formt) {
    var o = this.pub.getEncoded(this.compressed)
    return formt == 'hex'   ? conv.bytesToHex(o)
         : formt == 'bin'   ? conv.bytesToString(o)
                           : o;
}

ECPubKey.prototype.toString = function (format) {
    return ''+this.export(format)
}

ECPubKey.prototype.getBitcoinAddress = function(v) {
    return new Address(util.sha256ripe160(this.export()),v);
}

ECKey.prototype.sign = function (hash) {
  return ecdsa.sign(hash, this.priv);
};

ECKey.prototype.verify = function (hash, sig) {
  return ecdsa.verify(hash, sig, this.getPub()['export']('bytes'));
};

/**
 * Parse an exported private key contained in a string.
 */

module.exports = { ECKey: ECKey, ECPubKey: ECPubKey };
<commit_msg>Improve naming of ECKey/ECPubKey formatters. close vbuterin/bitcoinjs-lib#13<commit_after>var BigInteger = require('./jsbn/jsbn');
var sec = require('./jsbn/sec');
var base58 = require('./base58');
var Crypto = require('./crypto-js/crypto');
var util = require('./util');
var conv = require('./convert');
var Address = require('./address');
var ecdsa = require('./ecdsa');
var ECPointFp = require('./jsbn/ec').ECPointFp;

var ecparams = sec("secp256k1");

// input can be nothing, array of bytes, hex string, or base58 string
var ECKey = function (input,compressed) {
    if (!(this instanceof ECKey)) { return new ECKey(input); }
    if (!input) {
        // Generate new key
        var n = ecparams.getN();
        this.priv = ecdsa.getBigRandom(n);
        this.compressed = compressed || false;
    }
    else this.import(input,compressed)
};

ECKey.prototype.import = function (input,compressed) {
    function has(li,v) { return li.indexOf(v) >= 0 }
    function fromBin(x) { return BigInteger.fromByteArrayUnsigned(x) }
    this.priv =
          input instanceof ECKey                   ? input.priv
        : input instanceof BigInteger              ? input.mod(ecparams.getN())
        : util.isArray(input)                      ? fromBin(input.slice(0,32))
        : typeof input != "string"                 ? null
        : input.length == 51 && input[0] == '5'    ? fromBin(base58.checkDecode(input))
        : input.length == 52 && has('LK',input[0]) ? fromBin(base58.checkDecode(input))
        : has([64,65],input.length)                ? fromBin(conv.hexToBytes(input.slice(0,64)))
                                                   : null

    this.compressed =
          compressed !== undefined                 ? compressed
        : input instanceof ECKey                   ? input.compressed
        : input instanceof BigInteger              ? false
        : util.isArray(input)                      ? false
        : typeof input != "string"                 ? null
        : input.length == 51 && input[0] == '5'    ? false
        : input.length == 52 && has('LK',input[0]) ? true
        : input.length == 64                       ? false
        : input.length == 65                       ? true
                                                   : null
};

ECKey.prototype.getPub = function() {
    return ECPubKey(ecparams.getG().multiply(this.priv),this.compressed)
}

/**
 * @deprecated Reserved keyword, factory pattern. Use toHex, toBytes, etc.
 */
ECKey.prototype['export'] = function(format) {
    format || (format = 'hex')
    return this['to' + format.substr(0, 1).toUpperCase() + format.substr(1)]()
};

ECKey.prototype.toBin = function() {
    return conv.bytesToString(this.toBytes())
}

ECKey.prototype.toBase58 = function() {
    return base58.checkEncode(this.toBytes(), 128)
}

ECKey.prototype.toWif = ECKey.prototype.toBase58

ECKey.prototype.toHex = function() {
    return conv.bytesToHex(this.toBytes())
}

ECKey.prototype.toBytes = function() {
    var bytes = this.priv.toByteArrayUnsigned();
    if (this.compressed) bytes.push(1)
    return bytes
}

ECKey.prototype.toString = ECKey.prototype.toBase58

ECKey.prototype.getBitcoinAddress = function(v) {
    return this.getPub().getBitcoinAddress(v)
}

ECKey.prototype.add = function(key) {
    return ECKey(this.priv.add(ECKey(key).priv),this.compressed)
}

ECKey.prototype.multiply = function(key) {
    return ECKey(this.priv.multiply(ECKey(key).priv),this.compressed)
}

var ECPubKey = function(input,compressed) {
    if (!(this instanceof ECPubKey)) { return new ECPubKey(input,compressed); }
    if (!input) {
        // Generate new key
        var n = ecparams.getN();
        this.pub = ecparams.getG().multiply(ecdsa.getBigRandom(n))
        this.compressed = compressed || false;
    }
    else this.import(input,compressed)
}

ECPubKey.prototype.import = function(input,compressed) {
    var decode = function(x) { return ECPointFp.decodeFrom(ecparams.getCurve(), x) }
    this.pub =
          input instanceof ECPointFp ? input
        : input instanceof ECKey     ? ecparams.getG().multiply(input.priv)
        : input instanceof ECPubKey  ? input.pub
        : typeof input == "string"   ? decode(conv.hexToBytes(input))
        : util.isArray(input)        ? decode(input)
                                     : ecparams.getG().multiply(ecdsa.getBigRandom(ecparams.getN()))

    this.compressed =
          arguments.length > 1       ? compressed
        : input instanceof ECPointFp ? input.compressed
        : input instanceof ECPubKey  ? input.compressed
                                     : (this.pub[0] < 4)
}

ECPubKey.prototype.add = function(key) {
    return ECPubKey(this.pub.add(ECPubKey(key).pub),this.compressed)
}

ECPubKey.prototype.multiply = function(key) {
    return ECPubKey(this.pub.multiply(ECKey(key).priv),this.compressed)
}

ECPubKey.prototype['export'] = function(format) {
    format || (format = 'hex')
    return this['to' + format.substr(0, 1).toUpperCase() + format.substr(1)]()
}

ECPubKey.prototype.toBytes = function() {
    return this.pub.getEncoded(this.compressed)
}

ECPubKey.prototype.toHex = function() {
    return conv.bytesToHex(this.toBytes())
}

ECPubKey.prototype.toBin = function() {
    return conv.bytesToString(this.toBytes())
}

ECPubKey.prototype.toString = function() {
    return this.getBitcoinAddress().toString()
}

ECPubKey.prototype.getBitcoinAddress = function(v) {
    return new Address(util.sha256ripe160(this.export()),v);
}

ECKey.prototype.sign = function (hash) {
  return ecdsa.sign(hash, this.priv);
};

ECKey.prototype.verify = function (hash, sig) {
  return ecdsa.verify(hash, sig, this.getPub()['export']('bytes'));
};

/**
 * Parse an exported private key contained in a string.
 */

module.exports = { ECKey: ECKey, ECPubKey: ECPubKey };
<|endoftext|>


<commit_before>/*!
 * jQuery UI Core @VERSION
 * http://jqueryui.com
 *
 * Copyright 2012 jQuery Foundation and other contributors
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI
 */
(function( $, undefined ) {

var uuid = 0,
	runiqueId = /^ui-id-\d+$/;

// prevent duplicate loading
// this is only a problem because we proxy existing functions
// and we don't want to double proxy them
$.ui = $.ui || {};
if ( $.ui.version ) {
	return;
}

$.extend( $.ui, {
	version: "@VERSION",

	keyCode: {
		BACKSPACE: 8,
		COMMA: 188,
		DELETE: 46,
		DOWN: 40,
		END: 35,
		ENTER: 13,
		ESCAPE: 27,
		HOME: 36,
		LEFT: 37,
		NUMPAD_ADD: 107,
		NUMPAD_DECIMAL: 110,
		NUMPAD_DIVIDE: 111,
		NUMPAD_ENTER: 108,
		NUMPAD_MULTIPLY: 106,
		NUMPAD_SUBTRACT: 109,
		PAGE_DOWN: 34,
		PAGE_UP: 33,
		PERIOD: 190,
		RIGHT: 39,
		SPACE: 32,
		TAB: 9,
		UP: 38
	}
});

// plugins
$.fn.extend({
	_focus: $.fn.focus,
	focus: function( delay, fn ) {
		return typeof delay === "number" ?
			this.each(function() {
				var elem = this;
				setTimeout(function() {
					$( elem ).focus();
					if ( fn ) {
						fn.call( elem );
					}
				}, delay );
			}) :
			this._focus.apply( this, arguments );
	},

	scrollParent: function() {
		var scrollParent;
		if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
			scrollParent = this.parents().filter(function() {
				return (/(relative|absolute|fixed)/).test($.css(this,'position')) && (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x'));
			}).eq(0);
		} else {
			scrollParent = this.parents().filter(function() {
				return (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x'));
			}).eq(0);
		}

		return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
	},

	zIndex: function( zIndex ) {
		if ( zIndex !== undefined ) {
			return this.css( "zIndex", zIndex );
		}

		if ( this.length ) {
			var elem = $( this[ 0 ] ), position, value;
			while ( elem.length && elem[ 0 ] !== document ) {
				// Ignore z-index if position is set to a value where z-index is ignored by the browser
				// This makes behavior of this function consistent across browsers
				// WebKit always returns auto if the element is positioned
				position = elem.css( "position" );
				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
					// IE returns 0 when zIndex is not specified
					// other browsers return a string
					// we ignore the case of nested elements with an explicit value of 0
					//

					value = parseInt( elem.css( "zIndex" ), 10 );
					if ( !isNaN( value ) && value !== 0 ) {
						return value;
					}
				}
				elem = elem.parent();
			}
		}

		return 0;
	},

	uniqueId: function() {
		return this.each(function() {
			if ( !this.id ) {
				this.id = "ui-id-" + (++uuid);
			}
		});
	},

	removeUniqueId: function() {
		return this.each(function() {
			if ( runiqueId.test( this.id ) ) {
				$( this ).removeAttr( "id" );
			}
		});
	},

	disableSelection: function() {
		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
			".ui-disableSelection", function( event ) {
				event.preventDefault();
			});
	},

	enableSelection: function() {
		return this.unbind( ".ui-disableSelection" );
	}
});

// support: jQuery <1.8
if ( !$( "" ).outerWidth( 1 ).jquery ) {
	$.each( [ "Width", "Height" ], function( i, name ) {
		var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
			type = name.toLowerCase(),
			orig = {
				innerWidth: $.fn.innerWidth,
				innerHeight: $.fn.innerHeight,
				outerWidth: $.fn.outerWidth,
				outerHeight: $.fn.outerHeight
			};

		function reduce( elem, size, border, margin ) {
			$.each( side, function() {
				size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
				if ( border ) {
					size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
				}
				if ( margin ) {
					size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
				}
			});
			return size;
		}

		$.fn[ "inner" + name ] = function( size ) {
			if ( size === undefined ) {
				return orig[ "inner" + name ].call( this );
			}

			return this.each(function() {
				$( this ).css( type, reduce( this, size ) + "px" );
			});
		};

		$.fn[ "outer" + name] = function( size, margin ) {
			if ( typeof size !== "number" ) {
				return orig[ "outer" + name ].call( this, size );
			}

			return this.each(function() {
				$( this).css( type, reduce( this, size, true, margin ) + "px" );
			});
		};
	});
}

// selectors
function focusable( element, isTabIndexNotNaN ) {
	var map, mapName, img,
		nodeName = element.nodeName.toLowerCase();
	if ( "area" === nodeName ) {
		map = element.parentNode;
		mapName = map.name;
		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
			return false;
		}
		img = $( "img[usemap=#" + mapName + "]" )[0];
		return !!img && visible( img );
	}
	return ( /input|select|textarea|button|object/.test( nodeName ) ?
		!element.disabled :
		"a" === nodeName ?
			element.href || isTabIndexNotNaN :
			isTabIndexNotNaN) &&
		// the element and all of its ancestors must be visible
		visible( element );
}

function visible( element ) {
	return !$( element ).parents().andSelf().filter(function() {
		return $.css( this, "visibility" ) === "hidden" ||
			$.expr.filters.hidden( this );
	}).length;
}

$.extend( $.expr[ ":" ], {
	data: function( elem, i, match ) {
		return !!$.data( elem, match[ 3 ] );
	},

	focusable: function( element ) {
		return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
	},

	tabbable: function( element ) {
		var tabIndex = $.attr( element, "tabindex" ),
			isTabIndexNaN = isNaN( tabIndex );
		return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
	}
});

// support
$(function() {
	var body = document.body,
		div = body.appendChild( div = document.createElement( "div" ) );

	// access offsetHeight before setting the style to prevent a layout bug
	// in IE 9 which causes the element to continue to take up space even
	// after it is removed from the DOM (#8026)
	div.offsetHeight;

	$.extend( div.style, {
		minHeight: "100px",
		height: "auto",
		padding: 0,
		borderWidth: 0
	});

	$.support.minHeight = div.offsetHeight === 100;
	$.support.selectstart = "onselectstart" in div;

	// set display to none to avoid a layout bug in IE
	// http://dev.jquery.com/ticket/4014
	body.removeChild( div ).style.display = "none";
});

// deprecated
$.extend( $.ui, {
	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
	plugin: {
		add: function( module, option, set ) {
			var i,
				proto = $.ui[ module ].prototype;
			for ( i in set ) {
				proto.plugins[ i ] = proto.plugins[ i ] || [];
				proto.plugins[ i ].push( [ option, set[ i ] ] );
			}
		},
		call: function( instance, name, args ) {
			var i,
				set = instance.plugins[ name ];
			if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
				return;
			}

			for ( i = 0; i < set.length; i++ ) {
				if ( instance.options[ set[ i ][ 0 ] ] ) {
					set[ i ][ 1 ].apply( instance.element, args );
				}
			}
		}
	},

	contains: $.contains,

	// only used by resizable
	hasScroll: function( el, a ) {

		//If overflow is hidden, the element might have extra content, but the user wants to hide it
		if ( $( el ).css( "overflow" ) === "hidden") {
			return false;
		}

		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
			has = false;

		if ( el[ scroll ] > 0 ) {
			return true;
		}

		// TODO: determine which cases actually cause this to happen
		// if the element doesn't have the scroll set, see if it's possible to
		// set the scroll
		el[ scroll ] = 1;
		has = ( el[ scroll ] > 0 );
		el[ scroll ] = 0;
		return has;
	},

	// these are odd functions, fix the API or move into individual plugins
	isOverAxis: function( x, reference, size ) {
		//Determines when x coordinate is over "b" element axis
		return ( x > reference ) && ( x < ( reference + size ) );
	},
	isOver: function( y, x, top, left, height, width ) {
		//Determines when x, y coordinates is over "b" element
		return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
	}
});

})( jQuery );
<commit_msg>Core: Adjust data pseudo creation to use new Sizzle pseudo creation for pseudos with arguments.<commit_after>/*!
 * jQuery UI Core @VERSION
 * http://jqueryui.com
 *
 * Copyright 2012 jQuery Foundation and other contributors
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI
 */
(function( $, undefined ) {

var uuid = 0,
	runiqueId = /^ui-id-\d+$/;

// prevent duplicate loading
// this is only a problem because we proxy existing functions
// and we don't want to double proxy them
$.ui = $.ui || {};
if ( $.ui.version ) {
	return;
}

$.extend( $.ui, {
	version: "@VERSION",

	keyCode: {
		BACKSPACE: 8,
		COMMA: 188,
		DELETE: 46,
		DOWN: 40,
		END: 35,
		ENTER: 13,
		ESCAPE: 27,
		HOME: 36,
		LEFT: 37,
		NUMPAD_ADD: 107,
		NUMPAD_DECIMAL: 110,
		NUMPAD_DIVIDE: 111,
		NUMPAD_ENTER: 108,
		NUMPAD_MULTIPLY: 106,
		NUMPAD_SUBTRACT: 109,
		PAGE_DOWN: 34,
		PAGE_UP: 33,
		PERIOD: 190,
		RIGHT: 39,
		SPACE: 32,
		TAB: 9,
		UP: 38
	}
});

// plugins
$.fn.extend({
	_focus: $.fn.focus,
	focus: function( delay, fn ) {
		return typeof delay === "number" ?
			this.each(function() {
				var elem = this;
				setTimeout(function() {
					$( elem ).focus();
					if ( fn ) {
						fn.call( elem );
					}
				}, delay );
			}) :
			this._focus.apply( this, arguments );
	},

	scrollParent: function() {
		var scrollParent;
		if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
			scrollParent = this.parents().filter(function() {
				return (/(relative|absolute|fixed)/).test($.css(this,'position')) && (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x'));
			}).eq(0);
		} else {
			scrollParent = this.parents().filter(function() {
				return (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x'));
			}).eq(0);
		}

		return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
	},

	zIndex: function( zIndex ) {
		if ( zIndex !== undefined ) {
			return this.css( "zIndex", zIndex );
		}

		if ( this.length ) {
			var elem = $( this[ 0 ] ), position, value;
			while ( elem.length && elem[ 0 ] !== document ) {
				// Ignore z-index if position is set to a value where z-index is ignored by the browser
				// This makes behavior of this function consistent across browsers
				// WebKit always returns auto if the element is positioned
				position = elem.css( "position" );
				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
					// IE returns 0 when zIndex is not specified
					// other browsers return a string
					// we ignore the case of nested elements with an explicit value of 0
					//

					value = parseInt( elem.css( "zIndex" ), 10 );
					if ( !isNaN( value ) && value !== 0 ) {
						return value;
					}
				}
				elem = elem.parent();
			}
		}

		return 0;
	},

	uniqueId: function() {
		return this.each(function() {
			if ( !this.id ) {
				this.id = "ui-id-" + (++uuid);
			}
		});
	},

	removeUniqueId: function() {
		return this.each(function() {
			if ( runiqueId.test( this.id ) ) {
				$( this ).removeAttr( "id" );
			}
		});
	},

	disableSelection: function() {
		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
			".ui-disableSelection", function( event ) {
				event.preventDefault();
			});
	},

	enableSelection: function() {
		return this.unbind( ".ui-disableSelection" );
	}
});

// support: jQuery <1.8
if ( !$( "" ).outerWidth( 1 ).jquery ) {
	$.each( [ "Width", "Height" ], function( i, name ) {
		var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
			type = name.toLowerCase(),
			orig = {
				innerWidth: $.fn.innerWidth,
				innerHeight: $.fn.innerHeight,
				outerWidth: $.fn.outerWidth,
				outerHeight: $.fn.outerHeight
			};

		function reduce( elem, size, border, margin ) {
			$.each( side, function() {
				size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
				if ( border ) {
					size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
				}
				if ( margin ) {
					size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
				}
			});
			return size;
		}

		$.fn[ "inner" + name ] = function( size ) {
			if ( size === undefined ) {
				return orig[ "inner" + name ].call( this );
			}

			return this.each(function() {
				$( this ).css( type, reduce( this, size ) + "px" );
			});
		};

		$.fn[ "outer" + name] = function( size, margin ) {
			if ( typeof size !== "number" ) {
				return orig[ "outer" + name ].call( this, size );
			}

			return this.each(function() {
				$( this).css( type, reduce( this, size, true, margin ) + "px" );
			});
		};
	});
}

// selectors
function focusable( element, isTabIndexNotNaN ) {
	var map, mapName, img,
		nodeName = element.nodeName.toLowerCase();
	if ( "area" === nodeName ) {
		map = element.parentNode;
		mapName = map.name;
		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
			return false;
		}
		img = $( "img[usemap=#" + mapName + "]" )[0];
		return !!img && visible( img );
	}
	return ( /input|select|textarea|button|object/.test( nodeName ) ?
		!element.disabled :
		"a" === nodeName ?
			element.href || isTabIndexNotNaN :
			isTabIndexNotNaN) &&
		// the element and all of its ancestors must be visible
		visible( element );
}

function visible( element ) {
	return !$( element ).parents().andSelf().filter(function() {
		return $.css( this, "visibility" ) === "hidden" ||
			$.expr.filters.hidden( this );
	}).length;
}

$.extend( $.expr[ ":" ], {
	data: $.expr.createPseudo ?
		$.expr.createPseudo(function( dataName ) {
			return function( elem ) {
				return !!$.data( elem, dataName );
			};
		}) :
		// support: jQuery <1.8
		function( elem, i, match ) {
			return !!$.data( elem, match[ 3 ] );
		},

	focusable: function( element ) {
		return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
	},

	tabbable: function( element ) {
		var tabIndex = $.attr( element, "tabindex" ),
			isTabIndexNaN = isNaN( tabIndex );
		return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
	}
});

// support
$(function() {
	var body = document.body,
		div = body.appendChild( div = document.createElement( "div" ) );

	// access offsetHeight before setting the style to prevent a layout bug
	// in IE 9 which causes the element to continue to take up space even
	// after it is removed from the DOM (#8026)
	div.offsetHeight;

	$.extend( div.style, {
		minHeight: "100px",
		height: "auto",
		padding: 0,
		borderWidth: 0
	});

	$.support.minHeight = div.offsetHeight === 100;
	$.support.selectstart = "onselectstart" in div;

	// set display to none to avoid a layout bug in IE
	// http://dev.jquery.com/ticket/4014
	body.removeChild( div ).style.display = "none";
});

// deprecated
$.extend( $.ui, {
	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
	plugin: {
		add: function( module, option, set ) {
			var i,
				proto = $.ui[ module ].prototype;
			for ( i in set ) {
				proto.plugins[ i ] = proto.plugins[ i ] || [];
				proto.plugins[ i ].push( [ option, set[ i ] ] );
			}
		},
		call: function( instance, name, args ) {
			var i,
				set = instance.plugins[ name ];
			if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
				return;
			}

			for ( i = 0; i < set.length; i++ ) {
				if ( instance.options[ set[ i ][ 0 ] ] ) {
					set[ i ][ 1 ].apply( instance.element, args );
				}
			}
		}
	},

	contains: $.contains,

	// only used by resizable
	hasScroll: function( el, a ) {

		//If overflow is hidden, the element might have extra content, but the user wants to hide it
		if ( $( el ).css( "overflow" ) === "hidden") {
			return false;
		}

		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
			has = false;

		if ( el[ scroll ] > 0 ) {
			return true;
		}

		// TODO: determine which cases actually cause this to happen
		// if the element doesn't have the scroll set, see if it's possible to
		// set the scroll
		el[ scroll ] = 1;
		has = ( el[ scroll ] > 0 );
		el[ scroll ] = 0;
		return has;
	},

	// these are odd functions, fix the API or move into individual plugins
	isOverAxis: function( x, reference, size ) {
		//Determines when x coordinate is over "b" element axis
		return ( x > reference ) && ( x < ( reference + size ) );
	},
	isOver: function( y, x, top, left, height, width ) {
		//Determines when x, y coordinates is over "b" element
		return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
	}
});

})( jQuery );
<|endoftext|>