<commit_before>/**
 * impress.js
 *
 * impress.js is a presentation tool based on the power of CSS3 transforms and transitions
 * in modern browsers and inspired by the idea behind prezi.com.
 *
 * MIT Licensed.
 *
 * Copyright 2011-2012 Bartek Szopka (@bartaz)
 *
 * ------------------------------------------------
 *  author:  Bartek Szopka
 *  version: 0.3
 *  url:     http://bartaz.github.com/impress.js/
 *  source:  http://github.com/bartaz/impress.js/
 */

(function ( document, window ) {
    'use strict';

    // HELPER FUNCTIONS

    var pfx = (function () {

        var style = document.createElement('dummy').style,
            prefixes = 'Webkit Moz O ms Khtml'.split(' '),
            memory = {};

        return function ( prop ) {
            if ( typeof memory[ prop ] === "undefined" ) {

                var ucProp  = prop.charAt(0).toUpperCase() + prop.substr(1),
                    props   = (prop + ' ' + prefixes.join(ucProp + ' ') + ucProp).split(' ');

                memory[ prop ] = null;
                for ( var i in props ) {
                    if ( style[ props[i] ] !== undefined ) {
                        memory[ prop ] = props[i];
                        break;
                    }
                }

            }

            return memory[ prop ];
        }

    })();

    var arrayify = function ( a ) {
        return [].slice.call( a );
    };

    var css = function ( el, props ) {
        var key, pkey;
        for ( key in props ) {
            if ( props.hasOwnProperty(key) ) {
                pkey = pfx(key);
                if ( pkey != null ) {
                    el.style[pkey] = props[key];
                }
            }
        }
        return el;
    }

    var byId = function ( id ) {
        return document.getElementById(id);
    }

    var $ = function ( selector, context ) {
        context = context || document;
        return context.querySelector(selector);
    };

    var $$ = function ( selector, context ) {
        context = context || document;
        return arrayify( context.querySelectorAll(selector) );
    };

    var translate = function ( t ) {
        return " translate3d(" + t.x + "px," + t.y + "px," + t.z + "px) ";
    };

    var rotate = function ( r, revert ) {
        var rX = " rotateX(" + r.x + "deg) ",
            rY = " rotateY(" + r.y + "deg) ",
            rZ = " rotateZ(" + r.z + "deg) ";

        return revert ? rZ+rY+rX : rX+rY+rZ;
    };

    var scale = function ( s ) {
        return " scale(" + s + ") ";
    };

    var getElementFromUrl = function () {
        // get id from url # by removing `#` or `#/` from the beginning,
        // so both "fallback" `#slide-id` and "enhanced" `#/slide-id` will work
        return byId( window.location.hash.replace(/^#\/?/,"") );
    };

    // CHECK SUPPORT

    var ua = navigator.userAgent.toLowerCase();
    var impressSupported = ( pfx("perspective") != null ) &&
                           ( document.body.classList ) &&
                           ( document.body.dataset ) &&
                           ( ua.search(/(iphone)|(ipod)|(android)/) == -1 );

    var roots = {};

    var impress = window.impress = function ( rootId ) {

        rootId = rootId || "impress";

        // if already initialized just return the API
        if (roots["impress-root-" + rootId]) {
            return roots["impress-root-" + rootId];
        }

        // DOM ELEMENTS

        var root = byId( rootId );

        if (!impressSupported) {
            root.className = "impress-not-supported";
            return;
        } else {
            root.className = "";
        }

        // viewport updates for iPad
        var meta = $("meta[name='viewport']") || document.createElement("meta");
        // hardcoding these values looks pretty bad, as they kind of depend on the content
        // so they should be at least configurable
        meta.content = "width=1024, minimum-scale=0.75, maximum-scale=0.75, user-scalable=no";
        if (meta.parentNode != document.head) {
            meta.name = 'viewport';
            document.head.appendChild(meta);
        }

        var canvas = document.createElement("div");
        canvas.className = "canvas";

        arrayify( root.childNodes ).forEach(function ( el ) {
            canvas.appendChild( el );
        });
        root.appendChild(canvas);

        var steps = $$(".step", root);

        // SETUP
        // set initial values and defaults

        document.documentElement.style.height = "100%";

        css(document.body, {
            height: "100%",
            overflow: "hidden"
        });

        var props = {
            position: "absolute",
            transformOrigin: "top left",
            transition: "all 0s ease-in-out",
            transformStyle: "preserve-3d"
        }

        css(root, props);
        css(root, {
            top: "50%",
            left: "50%",
            perspective: "1000px"
        });
        css(canvas, props);

        var current = {
            translate: { x: 0, y: 0, z: 0 },
            rotate:    { x: 0, y: 0, z: 0 },
            scale:     1
        };

        var stepData = {};

        var isStep = function ( el ) {
            return !!(el && el.id && stepData["impress-" + el.id]);
        }

        steps.forEach(function ( el, idx ) {
            var data = el.dataset,
                step = {
                    translate: {
                        x: data.x || 0,
                        y: data.y || 0,
                        z: data.z || 0
                    },
                    rotate: {
                        x: data.rotateX || 0,
                        y: data.rotateY || 0,
                        z: data.rotateZ || data.rotate || 0
                    },
                    scale: data.scale || 1,
                    el: el
                };

            if ( !el.id ) {
                el.id = "step-" + (idx + 1);
            }

            stepData["impress-" + el.id] = step;

            css(el, {
                position: "absolute",
                transform: "translate(-50%,-50%)" +
                           translate(step.translate) +
                           rotate(step.rotate) +
                           scale(step.scale),
                transformStyle: "preserve-3d"
            });

        });

        // making given step active

        var active = null;
        var hashTimeout = null;

        var goto = function ( el ) {
            if ( !isStep(el) || el == active) {
                // selected element is not defined as step or is already active
                return false;
            }

            // Sometimes it's possible to trigger focus on first link with some keyboard action.
            // Browser in such a case tries to scroll the page to make this element visible
            // (even that body overflow is set to hidden) and it breaks our careful positioning.
            //
            // So, as a lousy (and lazy) workaround we will make the page scroll back to the top
            // whenever slide is selected
            //
            // If you are reading this and know any better way to handle it, I'll be glad to hear about it!
            window.scrollTo(0, 0);

            var step = stepData["impress-" + el.id];

            if ( active ) {
                active.classList.remove("active");
            }
            el.classList.add("active");

            root.className = "step-" + el.id;

            // `#/step-id` is used instead of `#step-id` to prevent default browser
            // scrolling to element in hash
            //
            // and it has to be set after animation finishes, because in chrome it
            // causes transtion being laggy
            // BUG: http://code.google.com/p/chromium/issues/detail?id=62820
            window.clearTimeout( hashTimeout );
            hashTimeout = window.setTimeout(function () {
                window.location.hash = "#/" + el.id;
            }, 1000);

            var target = {
                rotate: {
                    x: -parseInt(step.rotate.x, 10),
                    y: -parseInt(step.rotate.y, 10),
                    z: -parseInt(step.rotate.z, 10)
                },
                translate: {
                    x: -step.translate.x,
                    y: -step.translate.y,
                    z: -step.translate.z
                },
                scale: 1 / parseFloat(step.scale)
            };

            // check if the transition is zooming in or not
            var zoomin = target.scale >= current.scale;

            // if presentation starts (nothing is active yet)
            // don't animate (set duration to 0)
            var duration = (active) ? "1s" : "0";

            css(root, {
                // to keep the perspective look similar for different scales
                // we need to 'scale' the perspective, too
                perspective: step.scale * 1000 + "px",
                transform: scale(target.scale),
                transitionDuration: duration,
                transitionDelay: (zoomin ? "500ms" : "0ms")
            });

            css(canvas, {
                transform: rotate(target.rotate, true) + translate(target.translate),
                transitionDuration: duration,
                transitionDelay: (zoomin ? "0ms" : "500ms")
            });

            current = target;
            active = el;

            return el;
        };

        var prev = function () {
            var prev = steps.indexOf( active ) - 1;
            prev = prev >= 0 ? steps[ prev ] : steps[ steps.length-1 ];

            return goto(prev);
        };

        var next = function () {
            var next = steps.indexOf( active ) + 1;
            next = next < steps.length ? steps[ next ] : steps[ 0 ];

            return goto(next);
        };

        window.addEventListener("hashchange", function () {
            goto( getElementFromUrl() );
        }, false);

        window.addEventListener("orientationchange", function () {
            window.scrollTo(0, 0);
        }, false);

        // START
        // by selecting step defined in url or first step of the presentation
        goto(getElementFromUrl() || steps[0]);

        return (roots[ "impress-root-" + rootId ] = {
            goto: goto,
            next: next,
            prev: prev
        });

    }
})(document, window);

// EVENTS

(function ( document, window ) {
    'use strict';

    // keyboard navigation handler
    document.addEventListener("keydown", function ( event ) {
        if ( event.keyCode == 9 || ( event.keyCode >= 32 && event.keyCode <= 34 ) || (event.keyCode >= 37 && event.keyCode <= 40) ) {
            switch( event.keyCode ) {
                case 33: ; // pg up
                case 37: ; // left
                case 38:   // up
                         impress().prev();
                         break;
                case 9:  ; // tab
                case 32: ; // space
                case 34: ; // pg down
                case 39: ; // right
                case 40:   // down
                         impress().next();
                         break;
            }

            event.preventDefault();
        }
    }, false);

    // delegated handler for clicking on the links to presentation steps
    document.addEventListener("click", function ( event ) {
        // event delegation with "bubbling"
        // check if event target (or any of its parents is a link)
        var target = event.target;
        while ( (target.tagName != "A") &&
                (target != document.body) ) {
            target = target.parentNode;
        }

        if ( target.tagName == "A" ) {
            var href = target.getAttribute("href");

            // if it's a link to presentation step, target this step
            if ( href && href[0] == '#' ) {
                target = document.getElementById( href.slice(1) );
            }
        }

        if ( impress().goto(target) ) {
            event.stopImmediatePropagation();
            event.preventDefault();
        }
    }, false);

    // delegated handler for clicking on step elements
    document.addEventListener("click", function ( event ) {
        var target = event.target;
        // find closest step element
        while ( !target.classList.contains("step") &&
                (target != document.body) ) {
            target = target.parentNode;
        }

        if ( impress().goto(target) ) {
            event.preventDefault();
        }
    }, false);

    // touch handler to detect taps on the left and right side of the screen
    document.addEventListener("touchstart", function ( event ) {
        if (event.touches.length === 1) {
            var x = event.touches[0].clientX,
                width = window.innerWidth * 0.3,
                result = null;

            if ( x < width ) {
                result = impress().prev();
            } else if ( x > window.innerWidth - width ) {
                result = impress().next();
            }

            if (result) {
                event.preventDefault();
            }
        }
    }, false);
})(document, window);

<commit_msg>it's not 0.3 anymore<commit_after>/**
 * impress.js
 *
 * impress.js is a presentation tool based on the power of CSS3 transforms and transitions
 * in modern browsers and inspired by the idea behind prezi.com.
 *
 * MIT Licensed.
 *
 * Copyright 2011-2012 Bartek Szopka (@bartaz)
 *
 * ------------------------------------------------
 *  author:  Bartek Szopka
 *  version: 0.4pre (in development)
 *  url:     http://bartaz.github.com/impress.js/
 *  source:  http://github.com/bartaz/impress.js/
 */

(function ( document, window ) {
    'use strict';

    // HELPER FUNCTIONS

    var pfx = (function () {

        var style = document.createElement('dummy').style,
            prefixes = 'Webkit Moz O ms Khtml'.split(' '),
            memory = {};

        return function ( prop ) {
            if ( typeof memory[ prop ] === "undefined" ) {

                var ucProp  = prop.charAt(0).toUpperCase() + prop.substr(1),
                    props   = (prop + ' ' + prefixes.join(ucProp + ' ') + ucProp).split(' ');

                memory[ prop ] = null;
                for ( var i in props ) {
                    if ( style[ props[i] ] !== undefined ) {
                        memory[ prop ] = props[i];
                        break;
                    }
                }

            }

            return memory[ prop ];
        }

    })();

    var arrayify = function ( a ) {
        return [].slice.call( a );
    };

    var css = function ( el, props ) {
        var key, pkey;
        for ( key in props ) {
            if ( props.hasOwnProperty(key) ) {
                pkey = pfx(key);
                if ( pkey != null ) {
                    el.style[pkey] = props[key];
                }
            }
        }
        return el;
    }

    var byId = function ( id ) {
        return document.getElementById(id);
    }

    var $ = function ( selector, context ) {
        context = context || document;
        return context.querySelector(selector);
    };

    var $$ = function ( selector, context ) {
        context = context || document;
        return arrayify( context.querySelectorAll(selector) );
    };

    var translate = function ( t ) {
        return " translate3d(" + t.x + "px," + t.y + "px," + t.z + "px) ";
    };

    var rotate = function ( r, revert ) {
        var rX = " rotateX(" + r.x + "deg) ",
            rY = " rotateY(" + r.y + "deg) ",
            rZ = " rotateZ(" + r.z + "deg) ";

        return revert ? rZ+rY+rX : rX+rY+rZ;
    };

    var scale = function ( s ) {
        return " scale(" + s + ") ";
    };

    var getElementFromUrl = function () {
        // get id from url # by removing `#` or `#/` from the beginning,
        // so both "fallback" `#slide-id` and "enhanced" `#/slide-id` will work
        return byId( window.location.hash.replace(/^#\/?/,"") );
    };

    // CHECK SUPPORT

    var ua = navigator.userAgent.toLowerCase();
    var impressSupported = ( pfx("perspective") != null ) &&
                           ( document.body.classList ) &&
                           ( document.body.dataset ) &&
                           ( ua.search(/(iphone)|(ipod)|(android)/) == -1 );

    var roots = {};

    var impress = window.impress = function ( rootId ) {

        rootId = rootId || "impress";

        // if already initialized just return the API
        if (roots["impress-root-" + rootId]) {
            return roots["impress-root-" + rootId];
        }

        // DOM ELEMENTS

        var root = byId( rootId );

        if (!impressSupported) {
            root.className = "impress-not-supported";
            return;
        } else {
            root.className = "";
        }

        // viewport updates for iPad
        var meta = $("meta[name='viewport']") || document.createElement("meta");
        // hardcoding these values looks pretty bad, as they kind of depend on the content
        // so they should be at least configurable
        meta.content = "width=1024, minimum-scale=0.75, maximum-scale=0.75, user-scalable=no";
        if (meta.parentNode != document.head) {
            meta.name = 'viewport';
            document.head.appendChild(meta);
        }

        var canvas = document.createElement("div");
        canvas.className = "canvas";

        arrayify( root.childNodes ).forEach(function ( el ) {
            canvas.appendChild( el );
        });
        root.appendChild(canvas);

        var steps = $$(".step", root);

        // SETUP
        // set initial values and defaults

        document.documentElement.style.height = "100%";

        css(document.body, {
            height: "100%",
            overflow: "hidden"
        });

        var props = {
            position: "absolute",
            transformOrigin: "top left",
            transition: "all 0s ease-in-out",
            transformStyle: "preserve-3d"
        }

        css(root, props);
        css(root, {
            top: "50%",
            left: "50%",
            perspective: "1000px"
        });
        css(canvas, props);

        var current = {
            translate: { x: 0, y: 0, z: 0 },
            rotate:    { x: 0, y: 0, z: 0 },
            scale:     1
        };

        var stepData = {};

        var isStep = function ( el ) {
            return !!(el && el.id && stepData["impress-" + el.id]);
        }

        steps.forEach(function ( el, idx ) {
            var data = el.dataset,
                step = {
                    translate: {
                        x: data.x || 0,
                        y: data.y || 0,
                        z: data.z || 0
                    },
                    rotate: {
                        x: data.rotateX || 0,
                        y: data.rotateY || 0,
                        z: data.rotateZ || data.rotate || 0
                    },
                    scale: data.scale || 1,
                    el: el
                };

            if ( !el.id ) {
                el.id = "step-" + (idx + 1);
            }

            stepData["impress-" + el.id] = step;

            css(el, {
                position: "absolute",
                transform: "translate(-50%,-50%)" +
                           translate(step.translate) +
                           rotate(step.rotate) +
                           scale(step.scale),
                transformStyle: "preserve-3d"
            });

        });

        // making given step active

        var active = null;
        var hashTimeout = null;

        var goto = function ( el ) {
            if ( !isStep(el) || el == active) {
                // selected element is not defined as step or is already active
                return false;
            }

            // Sometimes it's possible to trigger focus on first link with some keyboard action.
            // Browser in such a case tries to scroll the page to make this element visible
            // (even that body overflow is set to hidden) and it breaks our careful positioning.
            //
            // So, as a lousy (and lazy) workaround we will make the page scroll back to the top
            // whenever slide is selected
            //
            // If you are reading this and know any better way to handle it, I'll be glad to hear about it!
            window.scrollTo(0, 0);

            var step = stepData["impress-" + el.id];

            if ( active ) {
                active.classList.remove("active");
            }
            el.classList.add("active");

            root.className = "step-" + el.id;

            // `#/step-id` is used instead of `#step-id` to prevent default browser
            // scrolling to element in hash
            //
            // and it has to be set after animation finishes, because in chrome it
            // causes transtion being laggy
            // BUG: http://code.google.com/p/chromium/issues/detail?id=62820
            window.clearTimeout( hashTimeout );
            hashTimeout = window.setTimeout(function () {
                window.location.hash = "#/" + el.id;
            }, 1000);

            var target = {
                rotate: {
                    x: -parseInt(step.rotate.x, 10),
                    y: -parseInt(step.rotate.y, 10),
                    z: -parseInt(step.rotate.z, 10)
                },
                translate: {
                    x: -step.translate.x,
                    y: -step.translate.y,
                    z: -step.translate.z
                },
                scale: 1 / parseFloat(step.scale)
            };

            // check if the transition is zooming in or not
            var zoomin = target.scale >= current.scale;

            // if presentation starts (nothing is active yet)
            // don't animate (set duration to 0)
            var duration = (active) ? "1s" : "0";

            css(root, {
                // to keep the perspective look similar for different scales
                // we need to 'scale' the perspective, too
                perspective: step.scale * 1000 + "px",
                transform: scale(target.scale),
                transitionDuration: duration,
                transitionDelay: (zoomin ? "500ms" : "0ms")
            });

            css(canvas, {
                transform: rotate(target.rotate, true) + translate(target.translate),
                transitionDuration: duration,
                transitionDelay: (zoomin ? "0ms" : "500ms")
            });

            current = target;
            active = el;

            return el;
        };

        var prev = function () {
            var prev = steps.indexOf( active ) - 1;
            prev = prev >= 0 ? steps[ prev ] : steps[ steps.length-1 ];

            return goto(prev);
        };

        var next = function () {
            var next = steps.indexOf( active ) + 1;
            next = next < steps.length ? steps[ next ] : steps[ 0 ];

            return goto(next);
        };

        window.addEventListener("hashchange", function () {
            goto( getElementFromUrl() );
        }, false);

        window.addEventListener("orientationchange", function () {
            window.scrollTo(0, 0);
        }, false);

        // START
        // by selecting step defined in url or first step of the presentation
        goto(getElementFromUrl() || steps[0]);

        return (roots[ "impress-root-" + rootId ] = {
            goto: goto,
            next: next,
            prev: prev
        });

    }
})(document, window);

// EVENTS

(function ( document, window ) {
    'use strict';

    // keyboard navigation handler
    document.addEventListener("keydown", function ( event ) {
        if ( event.keyCode == 9 || ( event.keyCode >= 32 && event.keyCode <= 34 ) || (event.keyCode >= 37 && event.keyCode <= 40) ) {
            switch( event.keyCode ) {
                case 33: ; // pg up
                case 37: ; // left
                case 38:   // up
                         impress().prev();
                         break;
                case 9:  ; // tab
                case 32: ; // space
                case 34: ; // pg down
                case 39: ; // right
                case 40:   // down
                         impress().next();
                         break;
            }

            event.preventDefault();
        }
    }, false);

    // delegated handler for clicking on the links to presentation steps
    document.addEventListener("click", function ( event ) {
        // event delegation with "bubbling"
        // check if event target (or any of its parents is a link)
        var target = event.target;
        while ( (target.tagName != "A") &&
                (target != document.body) ) {
            target = target.parentNode;
        }

        if ( target.tagName == "A" ) {
            var href = target.getAttribute("href");

            // if it's a link to presentation step, target this step
            if ( href && href[0] == '#' ) {
                target = document.getElementById( href.slice(1) );
            }
        }

        if ( impress().goto(target) ) {
            event.stopImmediatePropagation();
            event.preventDefault();
        }
    }, false);

    // delegated handler for clicking on step elements
    document.addEventListener("click", function ( event ) {
        var target = event.target;
        // find closest step element
        while ( !target.classList.contains("step") &&
                (target != document.body) ) {
            target = target.parentNode;
        }

        if ( impress().goto(target) ) {
            event.preventDefault();
        }
    }, false);

    // touch handler to detect taps on the left and right side of the screen
    document.addEventListener("touchstart", function ( event ) {
        if (event.touches.length === 1) {
            var x = event.touches[0].clientX,
                width = window.innerWidth * 0.3,
                result = null;

            if ( x < width ) {
                result = impress().prev();
            } else if ( x > window.innerWidth - width ) {
                result = impress().next();
            }

            if (result) {
                event.preventDefault();
            }
        }
    }, false);
})(document, window);

<|endoftext|>


<commit_before>var TCM = TCM || {};

(function($) {

    // Filtering, autocomplete, and fake placeholder text for manage and results pages

    var formOptionsFilter = function(context_sel, data_attr, trigger_sel, target_sel) {
        var context = $(context_sel),
        trigger = context.find(trigger_sel);
        if (context.length && trigger.is("select")) {
            var target = context.find(target_sel),
            allopts = target.find("option").clone();

            var doFilter = function() {
                var key = trigger.find("option:selected").data(data_attr);
                target.empty();
                allopts.each(function() {
                    if ($(this).data(data_attr) === key) {
                        var newopt = $(this).clone();
                        newopt.appendTo(target);
                    }
                });
            };

            doFilter();

            trigger.change(doFilter);
        }
    },

    filtering = function() {
        var keycodes = {
            SPACE: 32,
            ENTER: 13,
            TAB: 9,
            ESC: 27,
            BACKSPACE: 8,
            SHIFT: 16,
            CTRL: 17,
            ALT: 18,
            CAPS: 20,
            LEFT: 37,
            UP: 38,
            RIGHT: 39,
            DOWN: 40
        },
        formActions = $('#filter .form-actions').hide(),
        toggle = $('#filter .toggle a'),
        input = $('#filter .visual .filter-group input[type="checkbox"]').each(function() {
            $(this).data('originallyChecked', $(this).is(':checked'));
        }),
        textbox = $('#filter .textual #text-filter'),
        typedText,
        placeholder = textbox.attr('placeholder'),
        suggestionList = $('#filter .textual .suggest').hide(),
        keywordGroups = $('#filter .visual .filter-group.keyword'),
        notKeywordGroups = $('#filter .visual .filter-group:not(.keyword)'),
        selected,
        removeFakePlaceholder = function() {
            if (textbox.val().indexOf(placeholder) !== -1) {
                textbox.val(null);
            }
            textbox.removeClass('placeholder');
        },
        updateFormActions = function() {
            if (input.filter(function() { return $(this).data('state') === 'changed'; }).length) {
                formActions.fadeIn('fast');
                $('.managelist').addClass('expired');
            } else {
                formActions.fadeOut('fast');
                $('.managelist').removeClass('expired');
            }
        },
        updateSuggestions = function() {
            typedText = textbox.val();
            suggestionList.empty();
            if (textbox.val().length) {
                var relevantFilters = notKeywordGroups.find('input[type="checkbox"]:not(:checked)').parent('li').filter(function() {
                        return $(this).children('label').html().toLowerCase().indexOf(typedText.toLowerCase()) !== -1;
                    });
                relevantFilters.each(function() {
                    var typedIndex = $(this).children('label').html().toLowerCase().indexOf(typedText.toLowerCase()),
                        preText = $(this).children('label').html().substring(0, typedIndex),
                        postText = $(this).children('label').html().substring(typedIndex + typedText.length),
                        type = $(this).children('input').attr('name'),
                        id = $(this).children('input').attr('id'),
                        newHTML = '
' + preText + '' + typedText + '' + postText + ' [' + type + ']
';
                    suggestionList.append(newHTML);
                });
                keywordGroups.each(function() {
                    var type = $(this).children('h5').html(),
                        name = $(this).data('name'),
                        keywordHTML = '
' + typedText + ' [' + type + ']
';
                    if ($(this).find('input[type="checkbox"]:checked').length) {
                        if ($(this).find('input[type="checkbox"][value^="^"][value$="$"]:checked').length === $(this).find('input[type="checkbox"]:checked').length) {
                            if (!($(this).find('input[type="checkbox"][value="' + typedText + '"]:checked').length) && typedText.indexOf('^') === 0 && typedText.lastIndexOf('$') === typedText.length - 1) {
                                suggestionList.append(keywordHTML);
                            }
                        }
                    } else {
                        suggestionList.append(keywordHTML);
                    }
                });
                suggestionList.find('li:first-child a').addClass('selected');
            }
        };

        toggle.click(function() {
            $('#filter .visual').toggleClass('compact').toggleClass('expanded');
            return false;
        });

        formActions.find('.reset').click(function() {
            formActions.fadeOut('fast');
            $('.managelist').removeClass('expired');
            input.each(function() {
                $(this).data('state', null);
                $(this).prop('checked', $(this).data('originallyChecked'));
            });
            textbox.focus();
            suggestionList.hide();
            return false;
        });

        input.live('change', function() {
            if ($(this).data('originallyChecked') !== $(this).is(':checked')) {
                $(this).data('state', 'changed');
            } else {
                $(this).data('state', null);
            }
            textbox.focus();
            suggestionList.hide();
            updateFormActions();
        });

        textbox.keyup(function(event) {
            if ($(this).val() !== typedText && $(this).val() !== placeholder) {
                updateSuggestions();
            }
        }).keydown(function(event) {
            if (textbox.hasClass('placeholder')) {
                if (!event.metaKey && event.keyCode !== keycodes.SHIFT && event.keyCode !== keycodes.CTRL && event.keyCode !== keycodes.ALT && event.keyCode !== keycodes.CAPS && event.keyCode !== keycodes.ESC) {
                    removeFakePlaceholder();
                }
            }
            if (!suggestionList.is(':visible')) {
                if (!event.metaKey && event.keyCode !== keycodes.SHIFT && event.keyCode !== keycodes.CTRL && event.keyCode !== keycodes.ALT && event.keyCode !== keycodes.CAPS && event.keyCode !== keycodes.ESC) {
                    if (event.keyCode === keycodes.TAB && textbox.val() !== '') {
                        event.preventDefault();
                    }
                    if (event.keyCode === keycodes.ENTER && textbox.val() === '' && $('.managelist').hasClass('expired')) {
                        formActions.find('button[type="submit"]').click();
                        return false;
                    }
                    updateSuggestions();
                    suggestionList.show();
                }
            } else {
                if (event.keyCode === keycodes.UP) {
                    event.preventDefault();
                    if (!suggestionList.find('.selected').parent().is(':first-child')) {
                        suggestionList.find('.selected').removeClass('selected').parent().prev().children('a').addClass('selected');
                    }
                    return false;
                }
                if (event.keyCode === keycodes.DOWN) {
                    event.preventDefault();
                    if (!suggestionList.find('.selected').parent().is(':last-child')) {
                        suggestionList.find('.selected').removeClass('selected').parent().next().children('a').addClass('selected');
                    }
                    return false;
                }
                if (event.keyCode === keycodes.ENTER) {
                    event.preventDefault();
                    var thisFilterName = input.filter('#' + suggestionList.find('.selected').data('id')).siblings('label').html();
                    if (thisFilterName && textbox.val() !== thisFilterName) {
                        textbox.val(thisFilterName);
                    } else {
                        if (textbox.val() === '' && $('.managelist').hasClass('expired')) {
                            formActions.find('button[type="submit"]').click();
                        } else {
                            suggestionList.find('.selected').click();
                            suggestionList.show();
                        }
                    }
                    return false;
                }
                if (event.keyCode === keycodes.TAB) {
                    var thisFilterName = input.filter('#' + suggestionList.find('.selected').data('id')).siblings('label').html();
                    if (thisFilterName && textbox.val() !== thisFilterName) {
                        event.preventDefault();
                        textbox.val(thisFilterName);
                        return false;
                    } else {
                        if (suggestionList.find('.selected').length) {
                            event.preventDefault();
                            suggestionList.find('.selected').click();
                            return false;
                        }
                    }
                }
                if (event.keyCode === keycodes.ESC) {
                    event.preventDefault();
                    suggestionList.hide();
                    return false;
                }
                return true;
            }
        }).click(function() {
            if (textbox.hasClass('placeholder')) {
                removeFakePlaceholder();
            }
        }).focus(function() {
            textbox.data('clicked', false);
            if (textbox.val().length === 0 && textbox.hasClass('placeholder')) {
                textbox.val(placeholder);
                textbox.get(0).setSelectionRange(0, 0);
            }
        }).blur(function() {
            function hideList() {
                if (textbox.data('clicked') !== true) {
                    suggestionList.hide();
                    textbox.data('clicked', false);
                }
            }
            removeFakePlaceholder();
            window.setTimeout(hideList, 150);
        }).addClass('placeholder').focus();

        suggestionList.hover(function() {
            selected = $(this).find('.selected').removeClass('selected');
        }, function() {
            selected.addClass('selected');
        }).find('a').live({
            mousedown: function() {
                textbox.data('clicked', true);
            },
            click: function() {
                if ($(this).data('class') === 'keyword') {
                    var name = $(this).data('name'),
                        thisGroup = keywordGroups.filter(function() {
                            return $(this).data('name') === name;
                        }),
                        existingKeyword = thisGroup.find('input[type="checkbox"][value="' + typedText + '"][name="' + name + '"]'),
                        index = thisGroup.find('li').length + 1,
                        newHTML =
                            '
' +
                                '<input type="checkbox" name="' + name + '" value="' + typedText + '" id="id-' + name + '-' + index + '">' +
                                '' + typedText + '' +
                            '
';
                    if (existingKeyword.length) {
                        existingKeyword.prop('checked', true);
                        if (existingKeyword.data('originallyChecked') !== existingKeyword.is(':checked')) {
                            existingKeyword.data('state', 'changed');
                        }
                    } else {
                        thisGroup.removeClass('empty').children('ul').append(newHTML);
                        $('#id-' + name + '-' + index).data('state', 'changed').data('originallyChecked', false).prop('checked', true);
                        input = input.add('#id-' + name + '-' + index);
                    }
                } else {
                    var thisFilter = input.filter('#' + $(this).data('id')).prop('checked', true);
                    if (thisFilter.data('originallyChecked') !== thisFilter.is(':checked')) {
                        thisFilter.data('state', 'changed');
                    }
                }
                updateFormActions();
                textbox.val(null);
                typedText = null;
                suggestionList.empty().hide();
                return false;
            }
        });
    },

    listDetails = function() {
        $('#listcontent .items .item.details').live(
            'click',
            function(event) {
                if ($(event.target).is("button, a")) {
                    return;
                }
                var item = $(this),
                content = item.find('.content'),
                url = item.data('details-url');
                if (url && !content.hasClass('loaded')) {
                    content.css('min-height', '4.854em').addClass('loaded');
                    content.loadingOverlay();
                    $.get(url,
                          function(data) {
                              content.loadingOverlay('remove');
                              content.html(data.html);
                          });
                }
            });
    },

    manageActionsAjax = function() {
        $('.manage button[name^=action-]').live(
            'click',
            function() {
                var button = $(this),
                form = button.closest('form'),
                token = form.find('input[name=csrfmiddlewaretoken]'),
                url = form.attr('action'),
                method = form.attr('method'),
                replace = button.closest('.action-ajax-replace'),
                success = function(data) {
                    var replacement = $(data.html);
                    replace.replaceWith(replacement);
                    replacement.find('.details').html5accordion('.summary');
                    replace.loadingOverlay('remove');
                },
                data = {};
                data[button.attr('name')] = button.val();
                data['csrfmiddlewaretoken'] = token.val();
                replace.loadingOverlay();
                $.ajax(url, {
                           type: method,
                           data: data,
                           success: success
                       });
                return false;
            }
        );
    };

    $(function() {
        filtering();
        listDetails();
        manageActionsAjax();
        $('.details:not(html)').html5accordion('.summary');
        $('#messages').messages({
            handleAjax: true,
            closeLink: '.message'
        });
        $('input[placeholder], textarea[placeholder]').placeholder();
        $('input:not([type=radio], [type=checkbox]), textarea').blur(
            function() {
                $(this).addClass('hadfocus');
            }
        );
        $('#filter .toggle a').click(
            function() {
                $('#filter .visual').toggleClass('compact').toggleClass('expanded');
                return false;
            }
        );
        $('.subnav .findertoggle').click(function() {
            $(this).add('.subnav .finder').toggleClass('expanded').toggleClass('compact');
            return false;
        });
        formOptionsFilter("#addsuite", "product-id", "#id_product", "#id_cases");
        formOptionsFilter("#addrun", "product-id", "#id_test_cycle", "#id_suites");
        $('.subnav').html5finder( {
            loading: true,
            ellipsis: true,
            horizontalScroll: true,
            scrollContainer: '.finder.expanded',
            headerSelector: '.listordering',
            sectionSelector: '.col',
            sectionContentSelector: '.colcontent',
            sectionClasses: [
                'products',
                'cycles',
                'runs',
                'cases',
                'results'
            ],
            sectionItemSelectors: [
                'input[name="product"]',
                'input[name="testcycle"]',
                'input[name="testrun"]',
                'input[name="testcase"]',
                'input[name="testresult"]'
            ]
        });
        $('.selectruns').html5finder( {
            loading: true,
            ellipsis: true,
            headerSelector: '.listordering',
            sectionSelector: '.col',
            sectionContentSelector: '.colcontent',
            sectionClasses: [
                'products',
                'cycles',
                'runs'
            ],
            sectionItemSelectors: [
                'input[name="product"]',
                'input[name="testcycle"]',
                'input[name="testrun"]'
            ],
            callback: function() {
                $('.selectruns + .environment').slideUp('fast');
            },
            lastChildCallback: function(choice) {
                var environments = $('.selectruns + .environment').css('min-height', '169px').slideDown('fast'),
                    ajaxUrl = $(choice).data("sub-url");
                environments.loadingOverlay();
                $.get(ajaxUrl, function(data) {
                    environments.loadingOverlay('remove');
                    environments.html(data.html);
                });
            }
        });
        $('.selectruns + .environment.empty').hide();
    });

    $(window).load(function() {
        $('#listcontent .items').find('.title, .product, .cycle, .run').ellipsis(true, 300);
        if ($('.manage').length && window.location.hash) {
            var hash = window.location.hash;
            $(hash).children('.summary').click();
        }
    });

})(jQuery);
<commit_msg>more js filtering bugfixes<commit_after>var TCM = TCM || {};

(function($) {

    // Filtering, autocomplete, and fake placeholder text for manage and results pages

    var formOptionsFilter = function(context_sel, data_attr, trigger_sel, target_sel) {
        var context = $(context_sel),
        trigger = context.find(trigger_sel);
        if (context.length && trigger.is("select")) {
            var target = context.find(target_sel),
            allopts = target.find("option").clone();

            var doFilter = function() {
                var key = trigger.find("option:selected").data(data_attr);
                target.empty();
                allopts.each(function() {
                    if ($(this).data(data_attr) === key) {
                        var newopt = $(this).clone();
                        newopt.appendTo(target);
                    }
                });
            };

            doFilter();

            trigger.change(doFilter);
        }
    },

    filtering = function() {
        var keycodes = {
            SPACE: 32,
            ENTER: 13,
            TAB: 9,
            ESC: 27,
            BACKSPACE: 8,
            SHIFT: 16,
            CTRL: 17,
            ALT: 18,
            CAPS: 20,
            LEFT: 37,
            UP: 38,
            RIGHT: 39,
            DOWN: 40
        },
        formActions = $('#filter .form-actions').hide(),
        toggle = $('#filter .toggle a'),
        input = $('#filter .visual .filter-group input[type="checkbox"]').each(function() {
            $(this).data('originallyChecked', $(this).is(':checked'));
        }),
        textbox = $('#filter .textual #text-filter'),
        typedText,
        placeholder = textbox.attr('placeholder'),
        suggestionList = $('#filter .textual .suggest').hide(),
        keywordGroups = $('#filter .visual .filter-group.keyword'),
        notKeywordGroups = $('#filter .visual .filter-group:not(.keyword)'),
        selected,
        removeFakePlaceholder = function() {
            if (textbox.val().indexOf(placeholder) !== -1) {
                textbox.val(null);
            }
            textbox.removeClass('placeholder');
        },
        updateFormActions = function() {
            if (input.filter(function() { return $(this).data('state') === 'changed'; }).length) {
                formActions.fadeIn('fast');
                $('.managelist').addClass('expired');
            } else {
                formActions.fadeOut('fast');
                $('.managelist').removeClass('expired');
            }
        },
        updateSuggestions = function() {
            typedText = textbox.val();
            suggestionList.empty();
            if (textbox.val().length) {
                var relevantFilters = notKeywordGroups.find('input[type="checkbox"]:not(:checked)').parent('li').filter(function() {
                        return $(this).children('label').html().toLowerCase().indexOf(typedText.toLowerCase()) !== -1;
                    });
                relevantFilters.each(function() {
                    var typedIndex = $(this).children('label').html().toLowerCase().indexOf(typedText.toLowerCase()),
                        preText = $(this).children('label').html().substring(0, typedIndex),
                        postText = $(this).children('label').html().substring(typedIndex + typedText.length),
                        type = $(this).children('input').attr('name'),
                        id = $(this).children('input').attr('id'),
                        newHTML = '
' + preText + '' + typedText + '' + postText + ' [' + type + ']
';
                    suggestionList.append(newHTML);
                });
                keywordGroups.each(function() {
                    var type = $(this).children('h5').html(),
                        name = $(this).data('name'),
                        keywordHTML = '
' + typedText + ' [' + type + ']
';
                    if ($(this).find('input[type="checkbox"]:checked').length) {
                        if ($(this).find('input[type="checkbox"][value^="^"][value$="$"]:checked').length === $(this).find('input[type="checkbox"]:checked').length) {
                            if (!($(this).find('input[type="checkbox"][value="' + typedText + '"]:checked').length) && typedText.indexOf('^') === 0 && typedText.lastIndexOf('$') === typedText.length - 1) {
                                suggestionList.append(keywordHTML);
                            }
                        }
                    } else {
                        suggestionList.append(keywordHTML);
                    }
                });
                suggestionList.find('li:first-child a').addClass('selected');
            }
        };

        toggle.click(function() {
            $('#filter .visual').toggleClass('compact expanded');
            return false;
        });

        formActions.find('.reset').click(function() {
            formActions.fadeOut('fast');
            $('.managelist').removeClass('expired');
            input.each(function() {
                $(this).data('state', null);
                $(this).prop('checked', $(this).data('originallyChecked'));
            });
            textbox.focus();
            suggestionList.hide();
            return false;
        });

        input.live('change', function() {
            if ($(this).data('originallyChecked') !== $(this).is(':checked')) {
                $(this).data('state', 'changed');
            } else {
                $(this).data('state', null);
            }
            textbox.focus();
            suggestionList.hide();
            updateFormActions();
        });

        textbox.keyup(function(event) {
            if ($(this).val() !== typedText && $(this).val() !== placeholder) {
                updateSuggestions();
            }
        }).keydown(function(event) {
            if (textbox.hasClass('placeholder')) {
                if (!event.metaKey && event.keyCode !== keycodes.SHIFT && event.keyCode !== keycodes.CTRL && event.keyCode !== keycodes.ALT && event.keyCode !== keycodes.CAPS && event.keyCode !== keycodes.ESC) {
                    removeFakePlaceholder();
                }
            }
            if (!suggestionList.is(':visible')) {
                if (!event.metaKey && event.keyCode !== keycodes.SHIFT && event.keyCode !== keycodes.CTRL && event.keyCode !== keycodes.ALT && event.keyCode !== keycodes.CAPS && event.keyCode !== keycodes.ESC) {
                    if (event.keyCode === keycodes.TAB && textbox.val() !== '') {
                        event.preventDefault();
                    }
                    if (event.keyCode === keycodes.ENTER && textbox.val() === '' && $('.managelist').hasClass('expired')) {
                        formActions.find('button[type="submit"]').click();
                        return false;
                    }
                    updateSuggestions();
                    suggestionList.show();
                }
            } else {
                if (event.keyCode === keycodes.UP) {
                    event.preventDefault();
                    if (!suggestionList.find('.selected').parent().is(':first-child')) {
                        suggestionList.find('.selected').removeClass('selected').parent().prev().children('a').addClass('selected');
                    }
                    return false;
                }
                if (event.keyCode === keycodes.DOWN) {
                    event.preventDefault();
                    if (!suggestionList.find('.selected').parent().is(':last-child')) {
                        suggestionList.find('.selected').removeClass('selected').parent().next().children('a').addClass('selected');
                    }
                    return false;
                }
                if (event.keyCode === keycodes.ENTER) {
                    event.preventDefault();
                    var thisFilterName = input.filter('#' + suggestionList.find('.selected').data('id')).siblings('label').html();
                    if (thisFilterName && textbox.val() !== thisFilterName) {
                        textbox.val(thisFilterName);
                    } else {
                        if (textbox.val() === '' && $('.managelist').hasClass('expired')) {
                            formActions.find('button[type="submit"]').click();
                        } else {
                            suggestionList.find('.selected').click();
                            suggestionList.show();
                        }
                    }
                    return false;
                }
                if (event.keyCode === keycodes.TAB) {
                    var thisFilterName = input.filter('#' + suggestionList.find('.selected').data('id')).siblings('label').html();
                    if (thisFilterName && textbox.val() !== thisFilterName) {
                        event.preventDefault();
                        textbox.val(thisFilterName);
                        return false;
                    } else {
                        if (suggestionList.find('.selected').length) {
                            event.preventDefault();
                            suggestionList.find('.selected').click();
                            return false;
                        }
                    }
                }
                if (event.keyCode === keycodes.ESC) {
                    event.preventDefault();
                    suggestionList.hide();
                    return false;
                }
                return true;
            }
        }).click(function() {
            if (textbox.hasClass('placeholder')) {
                removeFakePlaceholder();
            }
        }).focus(function() {
            textbox.data('clicked', false);
            if (textbox.val().length === 0 && textbox.hasClass('placeholder')) {
                textbox.val(placeholder);
                textbox.get(0).setSelectionRange(0, 0);
            }
        }).blur(function() {
            function hideList() {
                if (textbox.data('clicked') !== true) {
                    suggestionList.hide();
                    textbox.data('clicked', false);
                }
            }
            removeFakePlaceholder();
            window.setTimeout(hideList, 150);
        }).addClass('placeholder').focus();

        suggestionList.hover(function() {
            selected = $(this).find('.selected').removeClass('selected');
        }, function() {
            selected.addClass('selected');
        }).find('a').live({
            mousedown: function() {
                textbox.data('clicked', true);
            },
            click: function() {
                if ($(this).data('class') === 'keyword') {
                    var name = $(this).data('name'),
                        thisGroup = keywordGroups.filter(function() {
                            return $(this).data('name') === name;
                        }),
                        existingKeyword = thisGroup.find('input[type="checkbox"][value="' + typedText + '"][name="' + name + '"]'),
                        index = thisGroup.find('li').length + 1,
                        newHTML =
                            '
' +
                                '<input type="checkbox" name="' + name + '" value="' + typedText + '" id="id-' + name + '-' + index + '">' +
                                '' + typedText + '' +
                            '
';
                    if (existingKeyword.length) {
                        existingKeyword.prop('checked', true);
                        if (existingKeyword.data('originallyChecked') !== existingKeyword.is(':checked')) {
                            existingKeyword.data('state', 'changed');
                        }
                    } else {
                        thisGroup.removeClass('empty').children('ul').append(newHTML);
                        $('#id-' + name + '-' + index).data('state', 'changed').data('originallyChecked', false).prop('checked', true);
                        input = input.add('#id-' + name + '-' + index);
                    }
                } else {
                    var thisFilter = input.filter('#' + $(this).data('id')).prop('checked', true);
                    if (thisFilter.data('originallyChecked') !== thisFilter.is(':checked')) {
                        thisFilter.data('state', 'changed');
                    }
                }
                updateFormActions();
                textbox.val(null);
                typedText = null;
                suggestionList.empty().hide();
                return false;
            }
        });
    },

    listDetails = function() {
        $('#listcontent .items .item.details').live(
            'click',
            function(event) {
                if ($(event.target).is("button, a")) {
                    return;
                }
                var item = $(this),
                content = item.find('.content'),
                url = item.data('details-url');
                if (url && !content.hasClass('loaded')) {
                    content.css('min-height', '4.854em').addClass('loaded');
                    content.loadingOverlay();
                    $.get(url,
                          function(data) {
                              content.loadingOverlay('remove');
                              content.html(data.html);
                          });
                }
            });
    },

    manageActionsAjax = function() {
        $('.manage button[name^=action-]').live(
            'click',
            function() {
                var button = $(this),
                form = button.closest('form'),
                token = form.find('input[name=csrfmiddlewaretoken]'),
                url = form.attr('action'),
                method = form.attr('method'),
                replace = button.closest('.action-ajax-replace'),
                success = function(data) {
                    var replacement = $(data.html);
                    replace.replaceWith(replacement);
                    replacement.find('.details').html5accordion('.summary');
                    replace.loadingOverlay('remove');
                },
                data = {};
                data[button.attr('name')] = button.val();
                data['csrfmiddlewaretoken'] = token.val();
                replace.loadingOverlay();
                $.ajax(url, {
                           type: method,
                           data: data,
                           success: success
                       });
                return false;
            }
        );
    };

    $(function() {
        filtering();
        listDetails();
        manageActionsAjax();
        $('.details:not(html)').html5accordion('.summary');
        $('#messages').messages({
            handleAjax: true,
            closeLink: '.message'
        });
        $('input[placeholder], textarea[placeholder]').placeholder();
        $('input:not([type=radio], [type=checkbox]), textarea').blur(
            function() {
                $(this).addClass('hadfocus');
            }
        );
        $('.subnav .findertoggle').click(function() {
            $(this).add('.subnav .finder').toggleClass('expanded').toggleClass('compact');
            return false;
        });
        formOptionsFilter("#addsuite", "product-id", "#id_product", "#id_cases");
        formOptionsFilter("#addrun", "product-id", "#id_test_cycle", "#id_suites");
        $('.subnav').html5finder( {
            loading: true,
            ellipsis: true,
            horizontalScroll: true,
            scrollContainer: '.finder.expanded',
            headerSelector: '.listordering',
            sectionSelector: '.col',
            sectionContentSelector: '.colcontent',
            sectionClasses: [
                'products',
                'cycles',
                'runs',
                'cases',
                'results'
            ],
            sectionItemSelectors: [
                'input[name="product"]',
                'input[name="testcycle"]',
                'input[name="testrun"]',
                'input[name="testcase"]',
                'input[name="testresult"]'
            ]
        });
        $('.selectruns').html5finder( {
            loading: true,
            ellipsis: true,
            headerSelector: '.listordering',
            sectionSelector: '.col',
            sectionContentSelector: '.colcontent',
            sectionClasses: [
                'products',
                'cycles',
                'runs'
            ],
            sectionItemSelectors: [
                'input[name="product"]',
                'input[name="testcycle"]',
                'input[name="testrun"]'
            ],
            callback: function() {
                $('.selectruns + .environment').slideUp('fast');
            },
            lastChildCallback: function(choice) {
                var environments = $('.selectruns + .environment').css('min-height', '169px').slideDown('fast'),
                    ajaxUrl = $(choice).data("sub-url");
                environments.loadingOverlay();
                $.get(ajaxUrl, function(data) {
                    environments.loadingOverlay('remove');
                    environments.html(data.html);
                });
            }
        });
        $('.selectruns + .environment.empty').hide();
    });

    $(window).load(function() {
        $('#listcontent .items').find('.title, .product, .cycle, .run').ellipsis(true, 300);
        if ($('.manage').length && window.location.hash) {
            var hash = window.location.hash;
            $(hash).children('.summary').click();
        }
    });

})(jQuery);
<|endoftext|>


<commit_before>import SimpleSchema from 'simpl-schema';

/*

Look for type name in a few different places
Note: look into simplifying this

*/
export const isIntlField = fieldSchema => {
  const typeProperty = fieldSchema.type;
  let type;
  if (Array.isArray(typeProperty)) {
    type = typeProperty[0].type;
  } else {
    type = typeProperty.singleType ? typeProperty.singleType : typeProperty.definitions[0].type;
  }
  return type.name === 'IntlString';
}

/*

Generate custom IntlString SimpleSchema type
TODO: WIP (languages hardcoded)

*/
const schema = {};

['en', 'ja'].forEach(locale => {
  schema[locale] = {
    type: String,
    optional: true,
  };
});

export const IntlString = new SimpleSchema(schema);
IntlString.name = 'IntlString';
<commit_msg>Use function to get IntlString type<commit_after>import SimpleSchema from 'simpl-schema';
import { Strings } from './strings';

/*

Look for type name in a few different places
Note: look into simplifying this

*/
export const isIntlField = fieldSchema => {
  const typeProperty = fieldSchema.type;
  let type;
  if (Array.isArray(typeProperty)) {
    type = typeProperty[0].type;
  } else {
    type = typeProperty.singleType ? typeProperty.singleType : typeProperty.definitions[0].type;
  }
  return type.name === 'IntlString';
}

/*

Generate custom IntlString SimpleSchema type

*/
export const getIntlString = () => {

  const schema = {};

  Object.keys(Strings).forEach(locale => {
    schema[locale] = {
      type: String,
      optional: true,
    };
  });

  const IntlString = new SimpleSchema(schema);
  IntlString.name = 'IntlString';
  return IntlString;
}
<|endoftext|>


<commit_before>import _ from 'lodash';
import BPromise from 'bluebird';
import ValidationError from './error';
import ValidationErrorBundle from './error-bundle';

const DSL = Symbol('dsl');
const ERRORS = Symbol('errors');
const STATE = Symbol('state');
const ERROR_CLASS = Symbol('error-class');
const ERROR_BUNDLE_CLASS = Symbol('error-bundle-class');
const INITIALIZED = Symbol('initialized');

export default class ValidationContext {

  constructor(options) {
    options = _.extend({}, options);
    if (_.has(options, 'state') && !_.isObject(options.state)) {
      throw new Error('Validation context `state` option must be an object');
    }

    this[ERRORS] = [];
    this[DSL] = options.dsl ? Object.create(options.dsl) : {};
    this[STATE] = options.state ? Object.create(options.state) : {};
    this[ERROR_CLASS] = options.ValidationError || ValidationError;
    this[ERROR_BUNDLE_CLASS] = options.ValidationErrorBundle || ValidationErrorBundle;

    this.initialize();
    if (!this[INITIALIZED]) {
      throw new Error('A plugin overrode initialize but did not call the original function');
    }
  }

  initialize() {
    this[INITIALIZED] = true;
  }

  set(key, value) {
    if (_.isString(key) || _.isArray(key)) {
      _.set(this[STATE], key, value);
    } else if (_.isObject(key)) {
      for (let property in key) {
        this.set(property, key[property]);
      }
    } else {
      throw new Error('First argument must be a string, array or object');
    }

    return this;
  }

  get(key) {
    return _.get(this[STATE], key);
  }

  has(key) {
    return _.has(this[STATE], key);
  }

  pick(...properties) {
    return _.pick(this[STATE], properties);
  }

  remove(key) {
    _.unset(this[STATE], key);
    return this;
  }

  addError(properties) {
    this[ERRORS].push(this.createError(properties, Object.create(this[STATE])));
    return this;
  }

  createError(properties, state) {
    return new this[ERROR_CLASS](this.createErrorMessage(properties, state));
  }

  createErrorMessage(properties, state) {

    let message = properties.message || state.message || 'A validation error occurred';
    if (_.isFunction(message)) {
      message = message(_.merge({}, properties, state));
    }

    return message;
  }

  hasError(filter) {
    if (!this[ERRORS].length) {
      return false;
    }

    let predicate;
    if (_.isFunction(filter)) {
      predicate = error => filter(error, this);
    } else if (filter) {
      predicate = filter;
    } else {
      predicate = _.constant(true);
    }

    return _.find(this[ERRORS], predicate) !== undefined;
  }

  validate(...validators) {
    _.each(validators, (validator, i) => {
      if (!_.isFunction(validator)) {
        throw new Error(`Validator ${i} must be a function, got ${typeof(validator)}`);
      }
    });

    const execute = (context) => {
      const child = context.createChild();
      return child.recursivelyValidate(validators);
    };

    let promise;

    const validatorChain = (context) => {
      promise = promise || execute(context);
      return promise;
    };

    validatorChain.then = (resolve, reject) => {
      return validatorChain(this).then(resolve, reject);
    };

    return validatorChain;
  }

  ensureValid(...validators) {
    return this.validate(...validators).then(() => {
      if (!this[ERRORS].length) {
        return this;
      }

      throw new this[ERROR_BUNDLE_CLASS]('A validation error occurred.', this[ERRORS].slice());
    });
  }

  createChild() {
    const newContext = Object.create(this);
    newContext[STATE] = Object.create(this[STATE]);
    return newContext;
  }

  recursivelyValidate(validators) {
    return validators.length ? this.runValidator(validators.shift()).then(() => this.recursivelyValidate(validators)) : BPromise.resolve(this);
  }

  runValidator(validator) {

    const proxy = new Proxy(this, {
      get: (target, name) => {
        return this[name] || this[DSL][name];
      }
    });

    return BPromise.resolve(proxy).then(validator.bind(proxy)).then(result => {
      return _.isFunction(result) ? this.runValidator(result) : result;
    });
  }
}
<commit_msg>Fixme note<commit_after>import _ from 'lodash';
import BPromise from 'bluebird';
import ValidationError from './error';
import ValidationErrorBundle from './error-bundle';

const DSL = Symbol('dsl');
const ERRORS = Symbol('errors');
const STATE = Symbol('state');
const ERROR_CLASS = Symbol('error-class');
const ERROR_BUNDLE_CLASS = Symbol('error-bundle-class');
const INITIALIZED = Symbol('initialized');

export default class ValidationContext {

  constructor(options) {
    options = _.extend({}, options);
    if (_.has(options, 'state') && !_.isObject(options.state)) {
      throw new Error('Validation context `state` option must be an object');
    }

    this[ERRORS] = [];
    this[DSL] = options.dsl ? Object.create(options.dsl) : {};
    this[STATE] = options.state ? Object.create(options.state) : {};
    this[ERROR_CLASS] = options.ValidationError || ValidationError;
    this[ERROR_BUNDLE_CLASS] = options.ValidationErrorBundle || ValidationErrorBundle;

    this.initialize();
    if (!this[INITIALIZED]) {
      throw new Error('A plugin overrode initialize but did not call the original function');
    }
  }

  initialize() {
    this[INITIALIZED] = true;
  }

  set(key, value) {
    if (_.isString(key) || _.isArray(key)) {
      _.set(this[STATE], key, value);
    } else if (_.isObject(key)) {
      for (let property in key) {
        this.set(property, key[property]);
      }
    } else {
      throw new Error('First argument must be a string, array or object');
    }

    return this;
  }

  get(key) {
    return _.get(this[STATE], key);
  }

  has(key) {
    return _.has(this[STATE], key);
  }

  pick(...properties) {
    return _.pick(this[STATE], properties);
  }

  remove(key) {
    _.unset(this[STATE], key);
    return this;
  }

  addError(properties) {
    this[ERRORS].push(this.createError(properties, Object.create(this[STATE])));
    return this;
  }

  createError(properties, state) {
    return new this[ERROR_CLASS](this.createErrorMessage(properties, state));
  }

  createErrorMessage(properties, state) {

    let message = properties.message || state.message || 'A validation error occurred';
    if (_.isFunction(message)) {
      message = message(_.merge({}, properties, state));
    }

    return message;
  }

  hasError(filter) {
    if (!this[ERRORS].length) {
      return false;
    }

    let predicate;
    if (_.isFunction(filter)) {
      predicate = error => filter(error, this);
    } else if (filter) {
      predicate = filter;
    } else {
      predicate = _.constant(true);
    }

    return _.find(this[ERRORS], predicate) !== undefined;
  }

  validate(...validators) {
    _.each(validators, (validator, i) => {
      if (!_.isFunction(validator)) {
        throw new Error(`Validator ${i} must be a function, got ${typeof(validator)}`);
      }
    });

    const execute = (context) => {
      const child = context.createChild();
      return child.recursivelyValidate(validators);
    };

    let promise;

    const validatorChain = (context) => {
      promise = promise || execute(context);
      return promise;
    };

    validatorChain.then = (resolve, reject) => {
      return validatorChain(this).then(resolve, reject);
    };

    return validatorChain;
  }

  ensureValid(...validators) {
    return this.validate(...validators).then(() => {
      if (!this[ERRORS].length) {
        return this;
      }

      throw new this[ERROR_BUNDLE_CLASS]('A validation error occurred.', this[ERRORS].slice());
    });
  }

  createChild() {
    const newContext = Object.create(this);
    newContext[STATE] = Object.create(this[STATE]);
    return newContext;
  }

  recursivelyValidate(validators) {
    return validators.length ? this.runValidator(validators.shift()).then(() => this.recursivelyValidate(validators)) : BPromise.resolve(this);
  }

  runValidator(validator) {

    // FIXME: do not use proxy
    const proxy = new Proxy(this, {
      get: (target, name) => {
        return this[name] || this[DSL][name];
      }
    });

    return BPromise.resolve(proxy).then(validator.bind(proxy)).then(result => {
      return _.isFunction(result) ? this.runValidator(result) : result;
    });
  }
}
<|endoftext|>


<commit_before><commit_msg>astypes fix<commit_after><|endoftext|>


<commit_before>import sanitizeHtml from 'sanitize-html';
import { Utils } from '../modules';
import { throwError } from './errors.js';

Utils.sanitize = function(s) {
  return sanitizeHtml(s, {
    allowedTags: [
      'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul',
      'ol', 'nl', 'li', 'b', 'i', 'strong', 'em', 'strike',
      'code', 'hr', 'br', 'div', 'table', 'thead', 'caption',
      'tbody', 'tr', 'th', 'td', 'pre', 'img', 'figure', 'figcaption'
    ],
    allowedAttributes:  {
      ...sanitizeHtml.defaults.allowedAttributes,
      'figure': ['style']
    }
  });
};

Utils.performCheck = (operation, user, checkedObject, context, documentId, operationName, collectionName) => {

  if (!checkedObject) {
    throwError({ id: 'app.document_not_found', data: { documentId, operationName } });
  }

  if (!operation(user, checkedObject, context)) {
    throwError({ id: 'app.operation_not_allowed', data: { documentId, operationName } });
  }

};

export { Utils };
<commit_msg>limit possible styles<commit_after>import sanitizeHtml from 'sanitize-html';
import { Utils } from '../modules';
import { throwError } from './errors.js';

Utils.sanitize = function(s) {
  return sanitizeHtml(s, {
    allowedTags: [
      'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul',
      'ol', 'nl', 'li', 'b', 'i', 'strong', 'em', 'strike',
      'code', 'hr', 'br', 'div', 'table', 'thead', 'caption',
      'tbody', 'tr', 'th', 'td', 'pre', 'img', 'figure', 'figcaption'
    ],
    allowedAttributes:  {
      ...sanitizeHtml.defaults.allowedAttributes,
      'figure': ['style']
    },
    allowedStyles: {
      ...sanitizeHtml.defaults.allowedStyles,
      'figure': {
        'width': [/^\d+(?:px|em|%)$/]
      }
    }
  });
};

Utils.performCheck = (operation, user, checkedObject, context, documentId, operationName, collectionName) => {

  if (!checkedObject) {
    throwError({ id: 'app.document_not_found', data: { documentId, operationName } });
  }

  if (!operation(user, checkedObject, context)) {
    throwError({ id: 'app.operation_not_allowed', data: { documentId, operationName } });
  }

};

export { Utils };
<|endoftext|>


<commit_before>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { ExchangeError } = require ('./base/errors');

//  ---------------------------------------------------------------------------

module.exports = class lakebtc extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'lakebtc',
            'name': 'LakeBTC',
            'countries': 'US',
            'version': 'api_v2',
            'has': {
                'CORS': true,
                'createMarketOrder': false,
                'fetchTickers': true,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/28074120-72b7c38a-6660-11e7-92d9-d9027502281d.jpg',
                'api': 'https://api.lakebtc.com',
                'www': 'https://www.lakebtc.com',
                'doc': [
                    'https://www.lakebtc.com/s/api_v2',
                    'https://www.lakebtc.com/s/api',
                ],
            },
            'api': {
                'public': {
                    'get': [
                        'bcorderbook',
                        'bctrades',
                        'ticker',
                    ],
                },
                'private': {
                    'post': [
                        'buyOrder',
                        'cancelOrders',
                        'getAccountInfo',
                        'getExternalAccounts',
                        'getOrders',
                        'getTrades',
                        'openOrders',
                        'sellOrder',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'maker': 0.15 / 100,
                    'taker': 0.2 / 100,
                },
            },
        });
    }

    async fetchMarkets () {
        let markets = await this.publicGetTicker ();
        let result = [];
        let keys = Object.keys (markets);
        for (let k = 0; k < keys.length; k++) {
            let id = keys[k];
            let market = markets[id];
            let baseId = id.slice (0, 3);
            let quoteId = id.slice (3, 6);
            let base = baseId.toUpperCase ();
            let quote = quoteId.toUpperCase ();
            let symbol = base + '/' + quote;
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'baseId': baseId,
                'quoteId': quoteId,
                'info': market,
            });
        }
        return result;
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let response = await this.privatePostGetAccountInfo ();
        let balances = response['balance'];
        let result = { 'info': response };
        let ids = Object.keys (balances);
        for (let i = 0; i < ids.length; i++) {
            let id = ids[i];
            let code = id;
            if (id in this.currencies) {
                let currency = this.currencies[id];
                code = currency['code'];
            }
            let balance = parseFloat (balances[id]);
            let account = {
                'free': balance,
                'used': 0.0,
                'total': balance,
            };
            result[code] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let orderbook = await this.publicGetBcorderbook (this.extend ({
            'symbol': this.marketId (symbol),
        }, params));
        return this.parseOrderBook (orderbook);
    }

    parseTicker (ticker, market = undefined) {
        let timestamp = this.milliseconds ();
        let symbol = undefined;
        if (typeof market !== 'undefined')
            symbol = market['symbol'];
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': this.safeFloat (ticker, 'high'),
            'low': this.safeFloat (ticker, 'low'),
            'bid': this.safeFloat (ticker, 'bid'),
            'ask': this.safeFloat (ticker, 'ask'),
            'vwap': undefined,
            'open': undefined,
            'close': undefined,
            'first': undefined,
            'last': this.safeFloat (ticker, 'last'),
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': this.safeFloat (ticker, 'volume'),
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    async fetchTickers (symbols = undefined, params = {}) {
        await this.loadMarkets ();
        let tickers = await this.publicGetTicker (params);
        let ids = Object.keys (tickers);
        let result = {};
        for (let i = 0; i < ids.length; i++) {
            let symbol = ids[i];
            let ticker = tickers[symbol];
            let market = undefined;
            if (symbol in this.markets_by_id) {
                market = this.markets_by_id[symbol];
                symbol = market['symbol'];
            }
            result[symbol] = this.parseTicker (ticker, market);
        }
        return result;
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let tickers = await this.publicGetTicker (params);
        return this.parseTicker (tickers[market['id']], market);
    }

    parseTrade (trade, market) {
        let timestamp = trade['date'] * 1000;
        return {
            'info': trade,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': market['symbol'],
            'id': trade['tid'].toString (),
            'order': undefined,
            'type': undefined,
            'side': undefined,
            'price': parseFloat (trade['price']),
            'amount': parseFloat (trade['amount']),
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let response = await this.publicGetBctrades (this.extend ({
            'symbol': market['id'],
        }, params));
        return this.parseTrades (response, market, since, limit);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        if (type === 'market')
            throw new ExchangeError (this.id + ' allows limit orders only');
        let method = 'privatePost' + this.capitalize (side) + 'Order';
        let market = this.market (symbol);
        let order = {
            'params': [ price, amount, market['id'] ],
        };
        let response = await this[method] (this.extend (order, params));
        return {
            'info': response,
            'id': response['id'].toString (),
        };
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        return await this.privatePostCancelOrder ({ 'params': id });
    }

    nonce () {
        return this.microseconds ();
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'] + '/' + this.version;
        if (api === 'public') {
            url += '/' + path;
            if (Object.keys (params).length)
                url += '?' + this.urlencode (params);
        } else {
            this.checkRequiredCredentials ();
            let nonce = this.nonce ();
            if (Object.keys (params).length)
                params = params.join (',');
            else
                params = '';
            let query = this.urlencode ({
                'tonce': nonce,
                'accesskey': this.apiKey,
                'requestmethod': method.toLowerCase (),
                'id': nonce,
                'method': path,
                'params': params,
            });
            body = this.json ({
                'method': path,
                'params': params,
                'id': nonce,
            });
            let signature = this.hmac (this.encode (query), this.encode (this.secret), 'sha1');
            let auth = this.encode (this.apiKey + ':' + signature);
            headers = {
                'Json-Rpc-Tonce': nonce.toString (),
                'Authorization': 'Basic ' + this.decode (this.stringToBase64 (auth)),
                'Content-Type': 'application/json',
            };
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    async request (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let response = await this.fetch2 (path, api, method, params, headers, body);
        if ('error' in response)
            throw new ExchangeError (this.id + ' ' + this.json (response));
        return response;
    }
};
<commit_msg>lakebtc parseTicker consistency<commit_after>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { ExchangeError } = require ('./base/errors');

//  ---------------------------------------------------------------------------

module.exports = class lakebtc extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'lakebtc',
            'name': 'LakeBTC',
            'countries': 'US',
            'version': 'api_v2',
            'has': {
                'CORS': true,
                'createMarketOrder': false,
                'fetchTickers': true,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/28074120-72b7c38a-6660-11e7-92d9-d9027502281d.jpg',
                'api': 'https://api.lakebtc.com',
                'www': 'https://www.lakebtc.com',
                'doc': [
                    'https://www.lakebtc.com/s/api_v2',
                    'https://www.lakebtc.com/s/api',
                ],
            },
            'api': {
                'public': {
                    'get': [
                        'bcorderbook',
                        'bctrades',
                        'ticker',
                    ],
                },
                'private': {
                    'post': [
                        'buyOrder',
                        'cancelOrders',
                        'getAccountInfo',
                        'getExternalAccounts',
                        'getOrders',
                        'getTrades',
                        'openOrders',
                        'sellOrder',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'maker': 0.15 / 100,
                    'taker': 0.2 / 100,
                },
            },
        });
    }

    async fetchMarkets () {
        let markets = await this.publicGetTicker ();
        let result = [];
        let keys = Object.keys (markets);
        for (let k = 0; k < keys.length; k++) {
            let id = keys[k];
            let market = markets[id];
            let baseId = id.slice (0, 3);
            let quoteId = id.slice (3, 6);
            let base = baseId.toUpperCase ();
            let quote = quoteId.toUpperCase ();
            let symbol = base + '/' + quote;
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'baseId': baseId,
                'quoteId': quoteId,
                'info': market,
            });
        }
        return result;
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let response = await this.privatePostGetAccountInfo ();
        let balances = response['balance'];
        let result = { 'info': response };
        let ids = Object.keys (balances);
        for (let i = 0; i < ids.length; i++) {
            let id = ids[i];
            let code = id;
            if (id in this.currencies) {
                let currency = this.currencies[id];
                code = currency['code'];
            }
            let balance = parseFloat (balances[id]);
            let account = {
                'free': balance,
                'used': 0.0,
                'total': balance,
            };
            result[code] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let orderbook = await this.publicGetBcorderbook (this.extend ({
            'symbol': this.marketId (symbol),
        }, params));
        return this.parseOrderBook (orderbook);
    }

    parseTicker (ticker, market = undefined) {
        let timestamp = this.milliseconds ();
        let symbol = undefined;
        if (typeof market !== 'undefined')
            symbol = market['symbol'];
        let last = this.safeFloat (ticker, 'last');
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': this.safeFloat (ticker, 'high'),
            'low': this.safeFloat (ticker, 'low'),
            'bid': this.safeFloat (ticker, 'bid'),
            'bidVolume': undefined,
            'ask': this.safeFloat (ticker, 'ask'),
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': last,
            'last': last,
            'previousClose': undefined,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': this.safeFloat (ticker, 'volume'),
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    async fetchTickers (symbols = undefined, params = {}) {
        await this.loadMarkets ();
        let tickers = await this.publicGetTicker (params);
        let ids = Object.keys (tickers);
        let result = {};
        for (let i = 0; i < ids.length; i++) {
            let symbol = ids[i];
            let ticker = tickers[symbol];
            let market = undefined;
            if (symbol in this.markets_by_id) {
                market = this.markets_by_id[symbol];
                symbol = market['symbol'];
            }
            result[symbol] = this.parseTicker (ticker, market);
        }
        return result;
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let tickers = await this.publicGetTicker (params);
        return this.parseTicker (tickers[market['id']], market);
    }

    parseTrade (trade, market) {
        let timestamp = trade['date'] * 1000;
        return {
            'info': trade,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': market['symbol'],
            'id': trade['tid'].toString (),
            'order': undefined,
            'type': undefined,
            'side': undefined,
            'price': parseFloat (trade['price']),
            'amount': parseFloat (trade['amount']),
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let response = await this.publicGetBctrades (this.extend ({
            'symbol': market['id'],
        }, params));
        return this.parseTrades (response, market, since, limit);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        if (type === 'market')
            throw new ExchangeError (this.id + ' allows limit orders only');
        let method = 'privatePost' + this.capitalize (side) + 'Order';
        let market = this.market (symbol);
        let order = {
            'params': [ price, amount, market['id'] ],
        };
        let response = await this[method] (this.extend (order, params));
        return {
            'info': response,
            'id': response['id'].toString (),
        };
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        return await this.privatePostCancelOrder ({ 'params': id });
    }

    nonce () {
        return this.microseconds ();
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'] + '/' + this.version;
        if (api === 'public') {
            url += '/' + path;
            if (Object.keys (params).length)
                url += '?' + this.urlencode (params);
        } else {
            this.checkRequiredCredentials ();
            let nonce = this.nonce ();
            if (Object.keys (params).length)
                params = params.join (',');
            else
                params = '';
            let query = this.urlencode ({
                'tonce': nonce,
                'accesskey': this.apiKey,
                'requestmethod': method.toLowerCase (),
                'id': nonce,
                'method': path,
                'params': params,
            });
            body = this.json ({
                'method': path,
                'params': params,
                'id': nonce,
            });
            let signature = this.hmac (this.encode (query), this.encode (this.secret), 'sha1');
            let auth = this.encode (this.apiKey + ':' + signature);
            headers = {
                'Json-Rpc-Tonce': nonce.toString (),
                'Authorization': 'Basic ' + this.decode (this.stringToBase64 (auth)),
                'Content-Type': 'application/json',
            };
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    async request (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let response = await this.fetch2 (path, api, method, params, headers, body);
        if ('error' in response)
            throw new ExchangeError (this.id + ' ' + this.json (response));
        return response;
    }
};
<|endoftext|>


<commit_before>"use strict";
function runPage()
{
	$(document).ready('bootstrap_buttons', function() {
		$("#login").button("reset");
		$("#oid_url").attr("disabled", false);
		} );
	$("#loginOrRegister").bind("shown.bs.modal", function() { $("#oid_url").focus(); });
	spindivtext("Fertig.");
}

var oid_win;

function oid_modal()
{
	$("#loginOrRegister").modal("show");
}
function openiderror(data)
{
	progress("oid_progress", "100");
	$("#oid_progress").children().removeClass("progress-bar-info");
	if (data.status != 417)
	{
		$("#oid_progress").children().addClass("progress-bar-warning");
		$("#oid_general_error").show();
	}
	else
	{
		$("#oid_progress").children().addClass("progress-bar-danger");
		$("#oid_no_oid").show();
	}
	//Do something if this isn't a valid OpenID.
	$(".oid_inProgress").hide();
	$("#login").button("reset");
	$("#oid_url").attr("disabled", false);
}

function openid()
{
	$(".oid_error").hide();
	$("#oid_progress").children().addClass("progress-bar-info");
	$("#oid_progress").children().removeClass("progress-bar-danger");
	$("#oid_progress").children().removeClass("progress-bar-warning");
	$("#oid_progress").show();
	progress("oid_progress", "20");
	var oid = $("#oid_url").val();
	if (oid.search("http") != 0)
	{
		$("#noURL").show();
		progress("oid_progress", "100");
		$("#oid_progress").children().addClass("progress-bar-danger");
		$("#oid_progress").children().removeClass("progress-bar-info");
	}
	else
	{
		$("#oid_url").attr("disabled", true);
		$("#login").button("loading");
		if (sid == "")
		{
			$("#creatingSession").show();
			var sidreq = $.get("ajax.py?do=session|create");
			sidreq.error(openiderror);
			sidreq.success(function (data) {
				$("#creatingSession").hide();
				sid = data;
				localStory.setItem("sid", sid);
				oid_sidisready(oid);
			});
		}
		else
		{
			oid_sidisready(oid);
		}
	}
}

function oid_sidisready(oid)
{
	progress("oid_progress", "40");
	$("#gettingRURL").show();
	var rurlreq = $.get("ajax.py?do=openid|do|" + sid + "|" + oid)
	rurlreq.error(openiderror);
	rurlreq.success(oid_rurlisready);
}

function oid_rurlisready(rurl)
{
	progress("oid_progress", "60");
	$("#gettingRURL").hide();
	$("#oid_window_didnt_open").attr("href", rurl);
	$("#winOpened").show();
	oid_win = window.open(rurl, "", "height=800px, width=600px");
	setTimeout(check_oid_ready, 1000);
}

function check_oid_ready()
{
	if(oid_win.closed)
	{
		oid_done();
	}
	else
	{
			setTimeout(check_oid_ready, 1000);
	}
}

function oid_done()
{
	progress("oid_progress", "80");
	$("#winOpened").hide();
	$("#checking").show();
	var oid_check_req = $.get("ajax.py?do=openid|check|"+sid)
	oid_check_req.error(openiderror);
	oid_check_req.success(openidsuccess);
}

function openidsuccess()
{
	$(".oid_inProgress").hide();
	$("#oid_success").show();
	progress("oid_progress", "100");
	$("#oid_progress").children().addClass("progress-bar-success");
	$("#oid_progress").children().removeClass("progress-bar-info");
	$("#loginOrRegister").bind("hidden.bs.modal",function()  {
		$(".landing").hide();
		$(".loggedin").show();
		loadpage("home");
	});
	setTimeout(function() { $("#loginOrRegister").modal("hide"); }, 2500);
}
<commit_msg>Typo.<commit_after>"use strict";
function runPage()
{
	$(document).ready('bootstrap_buttons', function() {
		$("#login").button("reset");
		$("#oid_url").attr("disabled", false);
		} );
	$("#loginOrRegister").bind("shown.bs.modal", function() { $("#oid_url").focus(); });
	spindivtext("Fertig.");
}

var oid_win;

function oid_modal()
{
	$("#loginOrRegister").modal("show");
}
function openiderror(data)
{
	progress("oid_progress", "100");
	$("#oid_progress").children().removeClass("progress-bar-info");
	if (data.status != 417)
	{
		$("#oid_progress").children().addClass("progress-bar-warning");
		$("#oid_general_error").show();
	}
	else
	{
		$("#oid_progress").children().addClass("progress-bar-danger");
		$("#oid_no_oid").show();
	}
	//Do something if this isn't a valid OpenID.
	$(".oid_inProgress").hide();
	$("#login").button("reset");
	$("#oid_url").attr("disabled", false);
}

function openid()
{
	$(".oid_error").hide();
	$("#oid_progress").children().addClass("progress-bar-info");
	$("#oid_progress").children().removeClass("progress-bar-danger");
	$("#oid_progress").children().removeClass("progress-bar-warning");
	$("#oid_progress").show();
	progress("oid_progress", "20");
	var oid = $("#oid_url").val();
	if (oid.search("http") != 0)
	{
		$("#noURL").show();
		progress("oid_progress", "100");
		$("#oid_progress").children().addClass("progress-bar-danger");
		$("#oid_progress").children().removeClass("progress-bar-info");
	}
	else
	{
		$("#oid_url").attr("disabled", true);
		$("#login").button("loading");
		if (sid == "")
		{
			$("#creatingSession").show();
			var sidreq = $.get("ajax.py?do=session|create");
			sidreq.error(openiderror);
			sidreq.success(function (data) {
				$("#creatingSession").hide();
				sid = data;
				localStorage.setItem("sid", sid);
				oid_sidisready(oid);
			});
		}
		else
		{
			oid_sidisready(oid);
		}
	}
}

function oid_sidisready(oid)
{
	progress("oid_progress", "40");
	$("#gettingRURL").show();
	var rurlreq = $.get("ajax.py?do=openid|do|" + sid + "|" + oid)
	rurlreq.error(openiderror);
	rurlreq.success(oid_rurlisready);
}

function oid_rurlisready(rurl)
{
	progress("oid_progress", "60");
	$("#gettingRURL").hide();
	$("#oid_window_didnt_open").attr("href", rurl);
	$("#winOpened").show();
	oid_win = window.open(rurl, "", "height=800px, width=600px");
	setTimeout(check_oid_ready, 1000);
}

function check_oid_ready()
{
	if(oid_win.closed)
	{
		oid_done();
	}
	else
	{
			setTimeout(check_oid_ready, 1000);
	}
}

function oid_done()
{
	progress("oid_progress", "80");
	$("#winOpened").hide();
	$("#checking").show();
	var oid_check_req = $.get("ajax.py?do=openid|check|"+sid)
	oid_check_req.error(openiderror);
	oid_check_req.success(openidsuccess);
}

function openidsuccess()
{
	$(".oid_inProgress").hide();
	$("#oid_success").show();
	progress("oid_progress", "100");
	$("#oid_progress").children().addClass("progress-bar-success");
	$("#oid_progress").children().removeClass("progress-bar-info");
	$("#loginOrRegister").bind("hidden.bs.modal",function()  {
		$(".landing").hide();
		$(".loggedin").show();
		loadpage("home");
	});
	setTimeout(function() { $("#loginOrRegister").modal("hide"); }, 2500);
}
<|endoftext|>