<commit_before>(function ($, audiojs) {
    'use strict';

    $.fn.addPlayer = function (preload) {
        if ($(this).length !== 1) {
            throw new Error('Cannot instantiate player on ' +
                            'multiple/null selector');
        }
        if (!$(this).data('js-player')) {
            $(this).data('js-player', new Player($(this), preload));
        }
        return $(this).data('js-player');
    };

    var Track = function (src, title, dur, poster_src, pod_id, last_pos, played) {
        return {
            src: src,
            title: title,
            duration: dur,
            poster: poster_src,
            podcast: Number(pod_id),
            last_pos: (last_pos) ? last_pos : 0,
            played: (played) ? played : false
        };
    };

    var TrackElement = function (track) {
        var el = $('

' +
                   '
' +
                   '  ' +
                   '

' + track.title +
                   '

');
        return el;
    };

    var PlayMode = {
        continue: 0x01,
        repeat: 0x02
    };

    var Player = function (parentElement, preload) {
        if (!preload) preload = {};
        var P = {
            _dom: $('

'),
            _mode: (preload.mode) ? preload.mode : 0,
            header: new Header(),
            audio: new AudioPlayer(),
            playlist: new PlayList(preload.playlist),

            init: function (volume) {
                this.audio.init(this, volume);
                this._dom.find('.player-list ol').click(function (e) {
                    var li = ($(e.target).is('li')) ? $(e.target) :
                            $(e.target).closest('li'),
                        index = li.index(),
                        div = ($(e.target).is('div'))? $(e.target) :
                            $(e.target).closest('div');
                    if (div.hasClass('pl-btn-del')) {
                        P.delete(index);
                    }
                    else {
                        P.load(index);
                        P.play();
                    }
                });
            },
            error: function (e) {
                console.log(e);
                this.header.loadError(this.playlist.getTrack());
                this._showState('error');
            },
            load: function (index) {
                var track = this.playlist.load(index);
                this._showState('load');
                this.audio.load(track);
                this.header.load(track);
            },
            unload: function () {
                this.header.load();
                this._showState();
            },
            add: function (src, title, dur, poster_src, pod_id) {
                var i = this.playlist.add(
                    src, title, dur, poster_src, pod_id);
                if (i === 0) this.load(i);
            },
            delete: function (index) {
                var c = this.playlist._cur;
                if (c === index) {
                    this.stop();
                    if (this.playlist.count() > 1) this.nextTrack(true);
                    else this.unload();
                }
                this.playlist.delete(index);
            },
            addAndPlay: function (src, title, dur, poster_src, pod_id) {
                var i = this.playlist.insert(
                    src, title, dur, poster_src, pod_id);
                this.load(i);
                this.play();
                this._dom[0].scrollIntoView();
            },
            stop: function () {
                this.pause();
                this.reset();
            },
            play: function () {
                if (this.playlist.getTrack()) {
                    this.audio.play();
                    this._showState('play');
                }
            },
            pause: function () {
                if (this.playlist.getTrack()) {
                    this.audio.pause();
                    this._showState('pause');
                }
            },
            trackFinished: function () {
                this.playlist.finished();
                if (this.isMode(PlayMode.continue)) {
                    var t = this.playlist.next();
                    if (t !== -1 || this.isMode(PlayMode.repeat)) {
                        this.nextTrack();
                    }
                }
                else if (this.isMode(PlayMode.repeat)) {
                    this.reset();
                    this.play();
                }
            },
            reset: function () {
                this.audio.reset();
            },
            nextTrack: function (noplay) {
                var t = this.playlist.next();
                if (t === -1) t = 0;
                this.load(t);
                if (!noplay) this.play();
            },
            prevTrack: function () {
                var t = this.playlist.prev();
                if (t === -1) t = this.playlist.count() - 1;
                this.load(t);
                this.play();
            },
            skipAhead: function (sec) {
                this.audio.skipAhead(sec);
            },
            skipBack: function (sec) {
                this.audio.skipBack(sec);
            },
            addMode: function (mode) {
                mode = (Number(mode) == mode) ? mode : Modes[mode];
                this._mode = this._mode | mode;
            },
            remMode: function (mode) {
                mode = (Number(mode) == mode) ? mode : Modes[mode];
                this._mode = this._mode & ~mode;
            },
            isMode: function () {
                var i;
                if (arguments.length < 1) return false;
                for (i = 0; i < arguments.length; i++) {
                    if (!(this._mode & arguments[i])) return false;
                }
                return true;
            },
            setVolume: function (vol) {
                this.audio.setVolume(vol);
            },
            _showState: function (type) {
                var all = 'p-play p-pause p-load p-error',
                    pp = this._dom.find('.play-pause'),
                    Types = {
                    play: 'p-play',
                    pause: 'p-pause',
                    load: 'p-load',
                    error: 'p-error'
                };
                if (!type) pp.removeClass(all);
                else if (!Types[type]) throw new Error('Cannot display state: ' + type);
                else if (!pp.hasClass(Types[type])) {
                    pp.removeClass(all);
                    pp.addClass(Types[type]);
                }
            }
        };
        P.header._dom.append(P.audio._dom);
        P._dom.append(P.header._dom);
        P._dom.append(P.playlist._dom);
        parentElement.append(P._dom);
        P.init(preload.volume);
        return P;
    };

    var Header = function () {
        var H = {
            _dom: $('
' +
                    '
No track selected.
' +
                    '
'),
            _marquee_speed: 200, // miliseconds per character

            init: function () {
                this._insertTitle(this._dom.find('.titlebar').html());
            },

            load: function (track) {
                if (!track) this._unload();
                else {
                    this._insertTitle(track.title);
                }
            },

            loadError: function (track) {

            },

            _unload: function () {
                this._insertTitle("No track selected.");
            },

            _insertTitle: function (msg) {
                this._dom.find('.titlebar').html(msg).marquee({
                    duration: msg.length * this._marquee_speed,
                    gap: 0,
                    delayBeforeStart: 0,
                    direction: 'left',
                    duplicated: false
                });
            }
        };
        return H;
    };

    var AudioPlayer = function () {
        var AP = {
            _dom: $('
<audio preload></audio>
'),
            _audio: false,

            init: function (player, volume) {
                if (!volume) volume = 0.75;
                if ($(this._dom.getUnique()).length < 1) {
                    throw new Error('Cannot initialize AudioPlayer that is ' +
                                    'not attached to the current DOM.');
                }
                this._audio = audiojs.newInstance(this._dom.find('audio')[0], {
                    trackEnded: function () {
                        player.trackFinished();
                    }
                });
                this._audio.onError = function (e) {
                    player.error(e);
                };
                this._dom.find('.play-pause').click(function () {
                    console.log('playpause: \n\t');
                    console.log($(this));
                    if ($(this).hasClass('p-play')) {
                        player.pause();
                    }
                    else if ($(this).hasClass('p-pause')) {
                        player.play();
                    }
                });
                this._dom.find('.skip.ahead').click(function () {
                    player.skipAhead(30);
                });
                this._dom.find('.skip.back').click(function () {
                    player.skipBack(15);
                });
                this._dom.find('.volume').click(function () {
                    var time = $(this).closest('.audiojs').find('.time');
                    if (time.find('span').css('display') != 'none') {
                        $(this).newTip(true, 'Close');
                        time.find('span').css('display', 'none');
                        time.find('.slider').css('display', 'block');
                        $(this).css('color', '#ccc');
                    }
                    else {
                        $(this).newTip(true, 'Adjust Volume');
                        time.find('span').css('display', 'block');
                        time.find('.slider').css('display', 'none');
                        $(this).css('color', '#777');
                    }
                });
                this._dom.find('.slider').slider({
                    range: "min",
                    min: 0,
                    max: 40,
                    value: volume * 40,
                    slide: function (event, ui) {
                        player.setVolume(ui.value/40);
                    }
                });
                player.setVolume(this._dom.find('.slider').slider('value')/40);
                this._dom.find('[title]').newTip();
            },

            load: function (src) {
                if (!src) this._unload();
                else {
                    if (typeof(src) === 'object') src = src.src;
                    this._audio.load(src);
                }
            },

            _unload: function () {
            },

            play: function () {
                this._audio.play();
            },

            pause: function () {
                this._audio.pause();
            },

            playPause: function () {
                this._audio.playPause();
            },

            skipTo: function (position) {
                var percent, a = this._dom.find('audio')[0];
                position = (position < 0) ? 0 :
                        (position > a.duration) ? a.duration : position;
                percent = Math.floor(position / a.duration * 100) / 100;
                this._audio.skipTo(percent);
            },

            skipAhead: function (seconds) {
                var a = this._dom.find('audio')[0];
                this.skipTo(a.currentTime + seconds);
            },

            skipBack: function (seconds) {
                this.skipAhead(seconds * -1);
            },

            reset: function () {
                this.skipTo(0);
            },

            isPlaying: function () {
                return this._audio.playing;
            },

            getPosition: function () {
                return Math.floor(this._dom.find('audio')[0].currentTime);
            },

            setVolume: function (vol) {
                var el = this._dom.find('.volume');
                if (vol === this._dom.find('audio')[0].volume) return;
                this._audio.setVolume(vol);
                el.find('.glyphicon').css('display', 'none');
                if (vol === 0) {
                    el.find('.glyphicon-volume-off').css('display', 'block');
                }
                else if (vol === 1) {
                    el.find('.glyphicon-volume-up').css('display', 'block');
                }
                else {
                    el.find('.glyphicon-volume-down').css('display', 'block');
                }
            },

        };
        return AP;
    };

    var PlayList = function (list) {
        var PL = {
            _dom: $('

'),
            _list: [],
            _cur: 0,

            add: function (src, title, dur, poster_src, pod_id) {
                var track, played, index, el;
                if (typeof(src) === 'object') {
                    track = src;
                    autoload = title;
                }
                else {
                    track = new Track(src, title, dur, poster_src, pod_id);
                }
                if (this.hasTrack(track)) {
                    throw new Error('Track already in playlist.');
                }
                el = new TrackElement(track);
                this._list.push(track);
                this._appendElement(el);
                index = this.count() - 1;
                if (track.played) this._markPlayed(index);
                return index;
            },

            insert: function (src, title, dur, poster_src, pod_id) {
                var track, played, el;
                if (typeof(src) === 'object') {
                    track = src;
                    autoload = title;
                }
                else {
                    track = new Track(src, title, dur, poster_src, pod_id);
                }
                if (this.hasTrack(track)) {
                    throw new Error('Track already in playlist.');
                }
                el = new TrackElement(track);
                this._list.unshift(track);
                this._insertElement(el);
                if (track.played) this._markPlayed(0);
                if (this.count() !== 1) this._cur++;
                return 0;
            },

            delete: function (index) {
                var rem, element;
                if (this._list[index]) {
                    element = $(this._dom.find('li')[index]);
                    this._list.splice(index, 1);
                    this._removeElement(element);
                }
                if (index <= this._cur) this._cur--;
            },

            load: function (index) {
                var item, element;
                if (index < 0) index = this.count() - 1;
                if (index >= this.count()) index = 0;
                if (!this.getTrack(index)) {
                    return false;
                }
                this._cur = index;
                item = this.getTrack();
                element = $(this._dom.find('li')[index]);
                item.played = false;
                $(element).parent().find('.loaded').removeClass('loaded');
                $(element).removeClass('played');
                $(element).addClass('loaded');
                return item;
            },

            getTrack: function (index) {
                index = (Number(index) === index) ? index : this._cur;
                if (this.count() === 0 || !this._list[index]) {
                    return false;
                }
                return this._list[index];
            },

            hasTrack: function (track_or_src) {
                var src = track_or_src, filter;
                if (typeof(src) !== 'string') {
                    src = src.src;
                }
                filter = this._list.filter(function (track) {
                    return track.src === src;
                })[0];
                return (typeof(filter) !== 'undefined');
            },

            next: function () {
                if (!this._cur || this._cur === this.count() - 1) return -1;
                return this._cur + 1;
            },

            prev: function () {
                if (this._cur === 0) return -1;
                return this._cur - 1;
            },

            finished: function (index) {
                if (!index) index = this._cur;
                if (this._list[index]) {
                    this._list[index].played = true;
                    this._markPlayed(index);
                }
            },

            _markPlayed: function (index) {
                if (this._list[index]) {
                    $(this._list[index].selector).addClass('played');
                }
            },

            count: function () { return this._list.length; },

            _insertElement: function (el) {
                $(this._dom).find('ol').prepend(el);
                el.animate({opacity: 1}, 500);
            },

            _appendElement: function (el) {
                $(this._dom).find('ol').append(el);
                el.animate({opacity: 1}, 500);
            },

            _removeElement: function (el) {
                el.animate({height: '0px', opacity: 0}, 250, function () {
                    el.remove();
                });
            }
        };
        while (list && list.length > 0) {
            PL.insert(list.pop(), false);
        }
        return PL;
    };

}(jQuery, audiojs));<commit_msg>Initialize header after added to DOM.<commit_after>(function ($, audiojs) {
    'use strict';

    $.fn.addPlayer = function (preload) {
        if ($(this).length !== 1) {
            throw new Error('Cannot instantiate player on ' +
                            'multiple/null selector');
        }
        if (!$(this).data('js-player')) {
            $(this).data('js-player', new Player($(this), preload));
        }
        return $(this).data('js-player');
    };

    var Track = function (src, title, dur, poster_src, pod_id, last_pos, played) {
        return {
            src: src,
            title: title,
            duration: dur,
            poster: poster_src,
            podcast: Number(pod_id),
            last_pos: (last_pos) ? last_pos : 0,
            played: (played) ? played : false
        };
    };

    var TrackElement = function (track) {
        var el = $('

' +
                   '
' +
                   '  ' +
                   '

' + track.title +
                   '

');
        return el;
    };

    var PlayMode = {
        continue: 0x01,
        repeat: 0x02
    };

    var Player = function (parentElement, preload) {
        if (!preload) preload = {};
        var P = {
            _dom: $('

'),
            _mode: (preload.mode) ? preload.mode : 0,
            header: new Header(),
            audio: new AudioPlayer(),
            playlist: new PlayList(preload.playlist),

            init: function (volume) {
                this.header.init();
                this.audio.init(this, volume);
                this._dom.find('.player-list ol').click(function (e) {
                    var li = ($(e.target).is('li')) ? $(e.target) :
                            $(e.target).closest('li'),
                        index = li.index(),
                        div = ($(e.target).is('div'))? $(e.target) :
                            $(e.target).closest('div');
                    if (div.hasClass('pl-btn-del')) {
                        P.delete(index);
                    }
                    else {
                        P.load(index);
                        P.play();
                    }
                });
            },
            error: function (e) {
                console.log(e);
                this.header.loadError(this.playlist.getTrack());
                this._showState('error');
            },
            load: function (index) {
                var track = this.playlist.load(index);
                this._showState('load');
                this.audio.load(track);
                this.header.load(track);
            },
            unload: function () {
                this.header.load();
                this._showState();
            },
            add: function (src, title, dur, poster_src, pod_id) {
                var i = this.playlist.add(
                    src, title, dur, poster_src, pod_id);
                if (i === 0) this.load(i);
            },
            delete: function (index) {
                var c = this.playlist._cur;
                if (c === index) {
                    this.stop();
                    if (this.playlist.count() > 1) this.nextTrack(true);
                    else this.unload();
                }
                this.playlist.delete(index);
            },
            addAndPlay: function (src, title, dur, poster_src, pod_id) {
                var i = this.playlist.insert(
                    src, title, dur, poster_src, pod_id);
                this.load(i);
                this.play();
                this._dom[0].scrollIntoView();
            },
            stop: function () {
                this.pause();
                this.reset();
            },
            play: function () {
                if (this.playlist.getTrack()) {
                    this.audio.play();
                    this._showState('play');
                }
            },
            pause: function () {
                if (this.playlist.getTrack()) {
                    this.audio.pause();
                    this._showState('pause');
                }
            },
            trackFinished: function () {
                this.playlist.finished();
                if (this.isMode(PlayMode.continue)) {
                    var t = this.playlist.next();
                    if (t !== -1 || this.isMode(PlayMode.repeat)) {
                        this.nextTrack();
                    }
                }
                else if (this.isMode(PlayMode.repeat)) {
                    this.reset();
                    this.play();
                }
            },
            reset: function () {
                this.audio.reset();
            },
            nextTrack: function (noplay) {
                var t = this.playlist.next();
                if (t === -1) t = 0;
                this.load(t);
                if (!noplay) this.play();
            },
            prevTrack: function () {
                var t = this.playlist.prev();
                if (t === -1) t = this.playlist.count() - 1;
                this.load(t);
                this.play();
            },
            skipAhead: function (sec) {
                this.audio.skipAhead(sec);
            },
            skipBack: function (sec) {
                this.audio.skipBack(sec);
            },
            addMode: function (mode) {
                mode = (Number(mode) == mode) ? mode : Modes[mode];
                this._mode = this._mode | mode;
            },
            remMode: function (mode) {
                mode = (Number(mode) == mode) ? mode : Modes[mode];
                this._mode = this._mode & ~mode;
            },
            isMode: function () {
                var i;
                if (arguments.length < 1) return false;
                for (i = 0; i < arguments.length; i++) {
                    if (!(this._mode & arguments[i])) return false;
                }
                return true;
            },
            setVolume: function (vol) {
                this.audio.setVolume(vol);
            },
            _showState: function (type) {
                var all = 'p-play p-pause p-load p-error',
                    pp = this._dom.find('.play-pause'),
                    Types = {
                    play: 'p-play',
                    pause: 'p-pause',
                    load: 'p-load',
                    error: 'p-error'
                };
                if (!type) pp.removeClass(all);
                else if (!Types[type]) throw new Error('Cannot display state: ' + type);
                else if (!pp.hasClass(Types[type])) {
                    pp.removeClass(all);
                    pp.addClass(Types[type]);
                }
            }
        };
        P.header._dom.append(P.audio._dom);
        P._dom.append(P.header._dom);
        P._dom.append(P.playlist._dom);
        parentElement.append(P._dom);
        P.init(preload.volume);
        return P;
    };

    var Header = function () {
        var H = {
            _dom: $('
' +
                    '
No track selected.
' +
                    '
'),
            _marquee_speed: 200, // miliseconds per character

            init: function () {
                this._insertTitle(this._dom.find('.titlebar').html());
            },

            load: function (track) {
                if (!track) this._unload();
                else {
                    this._insertTitle(track.title);
                }
            },

            loadError: function (track) {

            },

            _unload: function () {
                this._insertTitle("No track selected.");
            },

            _insertTitle: function (msg) {
                this._dom.find('.titlebar').html(msg).marquee({
                    duration: msg.length * this._marquee_speed,
                    gap: 0,
                    delayBeforeStart: 0,
                    direction: 'left',
                    duplicated: false
                });
            }
        };
        return H;
    };

    var AudioPlayer = function () {
        var AP = {
            _dom: $('
<audio preload></audio>
'),
            _audio: false,

            init: function (player, volume) {
                if (!volume) volume = 0.75;
                if ($(this._dom.getUnique()).length < 1) {
                    throw new Error('Cannot initialize AudioPlayer that is ' +
                                    'not attached to the current DOM.');
                }
                this._audio = audiojs.newInstance(this._dom.find('audio')[0], {
                    trackEnded: function () {
                        player.trackFinished();
                    }
                });
                this._audio.onError = function (e) {
                    player.error(e);
                };
                this._dom.find('.play-pause').click(function () {
                    console.log('playpause: \n\t');
                    console.log($(this));
                    if ($(this).hasClass('p-play')) {
                        player.pause();
                    }
                    else if ($(this).hasClass('p-pause')) {
                        player.play();
                    }
                });
                this._dom.find('.skip.ahead').click(function () {
                    player.skipAhead(30);
                });
                this._dom.find('.skip.back').click(function () {
                    player.skipBack(15);
                });
                this._dom.find('.volume').click(function () {
                    var time = $(this).closest('.audiojs').find('.time');
                    if (time.find('span').css('display') != 'none') {
                        $(this).newTip(true, 'Close');
                        time.find('span').css('display', 'none');
                        time.find('.slider').css('display', 'block');
                        $(this).css('color', '#ccc');
                    }
                    else {
                        $(this).newTip(true, 'Adjust Volume');
                        time.find('span').css('display', 'block');
                        time.find('.slider').css('display', 'none');
                        $(this).css('color', '#777');
                    }
                });
                this._dom.find('.slider').slider({
                    range: "min",
                    min: 0,
                    max: 40,
                    value: volume * 40,
                    slide: function (event, ui) {
                        player.setVolume(ui.value/40);
                    }
                });
                player.setVolume(this._dom.find('.slider').slider('value')/40);
                this._dom.find('[title]').newTip();
            },

            load: function (src) {
                if (!src) this._unload();
                else {
                    if (typeof(src) === 'object') src = src.src;
                    this._audio.load(src);
                }
            },

            _unload: function () {
            },

            play: function () {
                this._audio.play();
            },

            pause: function () {
                this._audio.pause();
            },

            playPause: function () {
                this._audio.playPause();
            },

            skipTo: function (position) {
                var percent, a = this._dom.find('audio')[0];
                position = (position < 0) ? 0 :
                        (position > a.duration) ? a.duration : position;
                percent = Math.floor(position / a.duration * 100) / 100;
                this._audio.skipTo(percent);
            },

            skipAhead: function (seconds) {
                var a = this._dom.find('audio')[0];
                this.skipTo(a.currentTime + seconds);
            },

            skipBack: function (seconds) {
                this.skipAhead(seconds * -1);
            },

            reset: function () {
                this.skipTo(0);
            },

            isPlaying: function () {
                return this._audio.playing;
            },

            getPosition: function () {
                return Math.floor(this._dom.find('audio')[0].currentTime);
            },

            setVolume: function (vol) {
                var el = this._dom.find('.volume');
                if (vol === this._dom.find('audio')[0].volume) return;
                this._audio.setVolume(vol);
                el.find('.glyphicon').css('display', 'none');
                if (vol === 0) {
                    el.find('.glyphicon-volume-off').css('display', 'block');
                }
                else if (vol === 1) {
                    el.find('.glyphicon-volume-up').css('display', 'block');
                }
                else {
                    el.find('.glyphicon-volume-down').css('display', 'block');
                }
            },

        };
        return AP;
    };

    var PlayList = function (list) {
        var PL = {
            _dom: $('

'),
            _list: [],
            _cur: 0,

            add: function (src, title, dur, poster_src, pod_id) {
                var track, played, index, el;
                if (typeof(src) === 'object') {
                    track = src;
                    autoload = title;
                }
                else {
                    track = new Track(src, title, dur, poster_src, pod_id);
                }
                if (this.hasTrack(track)) {
                    throw new Error('Track already in playlist.');
                }
                el = new TrackElement(track);
                this._list.push(track);
                this._appendElement(el);
                index = this.count() - 1;
                if (track.played) this._markPlayed(index);
                return index;
            },

            insert: function (src, title, dur, poster_src, pod_id) {
                var track, played, el;
                if (typeof(src) === 'object') {
                    track = src;
                    autoload = title;
                }
                else {
                    track = new Track(src, title, dur, poster_src, pod_id);
                }
                if (this.hasTrack(track)) {
                    throw new Error('Track already in playlist.');
                }
                el = new TrackElement(track);
                this._list.unshift(track);
                this._insertElement(el);
                if (track.played) this._markPlayed(0);
                if (this.count() !== 1) this._cur++;
                return 0;
            },

            delete: function (index) {
                var rem, element;
                if (this._list[index]) {
                    element = $(this._dom.find('li')[index]);
                    this._list.splice(index, 1);
                    this._removeElement(element);
                }
                if (index <= this._cur) this._cur--;
            },

            load: function (index) {
                var item, element;
                if (index < 0) index = this.count() - 1;
                if (index >= this.count()) index = 0;
                if (!this.getTrack(index)) {
                    return false;
                }
                this._cur = index;
                item = this.getTrack();
                element = $(this._dom.find('li')[index]);
                item.played = false;
                $(element).parent().find('.loaded').removeClass('loaded');
                $(element).removeClass('played');
                $(element).addClass('loaded');
                return item;
            },

            getTrack: function (index) {
                index = (Number(index) === index) ? index : this._cur;
                if (this.count() === 0 || !this._list[index]) {
                    return false;
                }
                return this._list[index];
            },

            hasTrack: function (track_or_src) {
                var src = track_or_src, filter;
                if (typeof(src) !== 'string') {
                    src = src.src;
                }
                filter = this._list.filter(function (track) {
                    return track.src === src;
                })[0];
                return (typeof(filter) !== 'undefined');
            },

            next: function () {
                if (!this._cur || this._cur === this.count() - 1) return -1;
                return this._cur + 1;
            },

            prev: function () {
                if (this._cur === 0) return -1;
                return this._cur - 1;
            },

            finished: function (index) {
                if (!index) index = this._cur;
                if (this._list[index]) {
                    this._list[index].played = true;
                    this._markPlayed(index);
                }
            },

            _markPlayed: function (index) {
                if (this._list[index]) {
                    $(this._list[index].selector).addClass('played');
                }
            },

            count: function () { return this._list.length; },

            _insertElement: function (el) {
                $(this._dom).find('ol').prepend(el);
                el.animate({opacity: 1}, 500);
            },

            _appendElement: function (el) {
                $(this._dom).find('ol').append(el);
                el.animate({opacity: 1}, 500);
            },

            _removeElement: function (el) {
                el.animate({height: '0px', opacity: 0}, 250, function () {
                    el.remove();
                });
            }
        };
        while (list && list.length > 0) {
            PL.insert(list.pop(), false);
        }
        return PL;
    };

}(jQuery, audiojs));<|endoftext|>


<commit_before>var utils = require('./util');
var express = require('express');
var uuid = require('node-uuid');

//before we load the logger, make sure we have the directory we need
utils.ensureExists(__dirname + '/logs', 0744, function(err) {
  if (err) {console.log("Error trying to create logging directory : "+err.message);}
});

var config = require('./config');
var randomBuffers = require('./randomBuffers');
var log = config.accesslog;
var serverlog = config.serverlog;
var resultslog = config.resultslog;

serverlog.info('Server starting up');
var http = require('http');
http.globalAgent.maxSockets = 100;

// for the downloads, we'll keep 64kb of random buffer data in memory.
// we'll access this later via randomBuffers.grab()
// (we're trying to make our payloads less compressable enroute)
randomBuffers.generate(randomBuffers.size);// generate 4MB (64x64kB) of random buffer data in memory

var app = express();
app.enable('trust proxy') //this allows Express to collect proxy addresses

app.set('port', (process.env.PORT || 5000));

// Client authorization [protect the upload and download resources]
function restrict(req, res, next) {
  if (utils.ipInRange(config,req.ip)) {
    next();
  } else {
    serverlog.info("Denied client based on IP range: " +req.ip+ " is not expressed in ranges: "+config.authorizedRanges);
    res.status(403).json({message:"client unauthorized"});
  }
}

//enable CORS and logging middleware on all routes
app.use(function(req, res, next) {
  var start = Date.now();
  res.setHeader("Access-Control-Allow-Origin", "*");
  req.req_id = uuid.v4();                // augment HTTP request with a UUID
  if(!req.connection.customId){          // if it doesn't already have one
    req.connection.customId = uuid.v4(); //   augment the http connection with a UUID
  }                                      //   (http keep-alive lets us track per connection)
  log.info({req: req}, 'request start'); // log the HTTP request
  res.on('finish', function() {          // log the HTTP response on the finish event
    log.info({ inResponseTo: req.req_id, res: res, duration: Date.now() - start }, 'request finish');
  })
  next();
});

// for now, 302 to the client page
app.get('/', function(request, response) {
  response.redirect("client.html");
});

//enable static HTTP published resources
app.use(express.static(__dirname + '/public'));

//service end point providing client access to client IP
app.get('/myip', function(request, response) {
  response.json({ip:request.ip,ips:request.ips});
});

//service end point providing HTTP:HEAD support as a convenience method to test if the client is authorized to access.
app.head('/authcheck', restrict, function(request, response) {
  response.status(200).end();
});

/* Service end point for data upload
 * Expecting POST /upload
 * If the post data is too big, we kill it.
 * (Data POSTed here is black-holed)
 */
app.post('/upload', restrict, function(request, response) {
  utils.markConnection(request);
  var uploadsize = 0;
  request.on("data", function(d) {
    uploadsize += d.length;
    d = null; //dump the content
    if (uploadsize > config.upload.maxPayload) {
      var msg = "killing connection - upload was unacceptably large";
      serverlog.info(msg); //TODO - need to look at logging output for error case
      response.status(403).json({message:msg});
      request.connection.destroy();
      return;
    }
  });

  request.on("end", function() {
    var msg = "I just ate "+uploadsize+" bytes";
    response.json({message:msg});
  });
});

/*
 * Allow the client to discover the supported download packages
 */
app.get('/download/config', function(request, response) {
    var p = {
        "download":config.download,
        "upload":config.upload
    };
  response.json(p);
});

/* Service end point for data download
 * Expecting GET /download/:size where :size is an explicitly acceptable value
 * If the requested value is not acceptable, the request flows through to a 404.
 */
app.get('/download/:size', restrict, function(request, response) {
  utils.markConnection(request);
  var packages = config.download.packages;
  var packageSize = "_"+request.params.size.toUpperCase().trim();

  // test for acceptability
  if(!packages[packageSize]){
    response.status(403).json({code:403,message:"Forbidden",supported:packages});
    return;
  }

  var max = packages[packageSize].size;
  response.writeHead(200, {'Content-length': max});

  var bufSize=(randomBuffers.size*1024);
  for(var i = 0; i < max; i += bufSize) {
    var b = randomBuffers.grab(); //64kb of random randomness
    response.write((max - i >= bufSize)?b:b.slice(0,max%bufSize));
  }
  response.end();
});

/* Service end point for result data upload
 * (Data POSTed here is logged for later trending analysis)
 */
app.post('/results', restrict, function(request, response) {
    var payload = "";
    request.on("data", function(d) {
        payload += d;
        if (payload.length > 3*1024) { //never more that that
            var msg = "killing connection - results payload was unacceptably large";
            serverlog.info(msg); //TODO - need to look at logging output for error case
            response.status(403).json({message:msg});
            request.connection.destroy();
            return;
        }
    });
    request.on("end", function() {
        var resultsObject = utils.convertFormDataToJSON(payload);
        resultslog.info({connectionUsageCount:request.connection.usageCount,results:resultsObject,clientIp:request.ip},"results received on this connection");
        var msg = "Received results: "+payload.length+" bytes";
        response.json({message:msg,results:resultsObject});
    });
});

app.listen(app.get('port'), function() {
  console.log("yet-another-speed-test app is running at localhost:" + app.get('port'));
  var cpuCount = require('os').cpus().length;
  serverlog.info("yet-another-speed-test app is running at localhost:" + app.get('port'));
  serverlog.info("cpuCount: "+cpuCount);
});<commit_msg>added userAgent to the results log<commit_after>var utils = require('./util');
var express = require('express');
var uuid = require('node-uuid');

//before we load the logger, make sure we have the directory we need
utils.ensureExists(__dirname + '/logs', 0744, function(err) {
  if (err) {console.log("Error trying to create logging directory : "+err.message);}
});

var config = require('./config');
var randomBuffers = require('./randomBuffers');
var log = config.accesslog;
var serverlog = config.serverlog;
var resultslog = config.resultslog;

serverlog.info('Server starting up');
var http = require('http');
http.globalAgent.maxSockets = 100;

// for the downloads, we'll keep 64kb of random buffer data in memory.
// we'll access this later via randomBuffers.grab()
// (we're trying to make our payloads less compressable enroute)
randomBuffers.generate(randomBuffers.size);// generate 4MB (64x64kB) of random buffer data in memory

var app = express();
app.enable('trust proxy') //this allows Express to collect proxy addresses

app.set('port', (process.env.PORT || 5000));

// Client authorization [protect the upload and download resources]
function restrict(req, res, next) {
  if (utils.ipInRange(config,req.ip)) {
    next();
  } else {
    serverlog.info("Denied client based on IP range: " +req.ip+ " is not expressed in ranges: "+config.authorizedRanges);
    res.status(403).json({message:"client unauthorized"});
  }
}

//enable CORS and logging middleware on all routes
app.use(function(req, res, next) {
  var start = Date.now();
  res.setHeader("Access-Control-Allow-Origin", "*");
  req.req_id = uuid.v4();                // augment HTTP request with a UUID
  if(!req.connection.customId){          // if it doesn't already have one
    req.connection.customId = uuid.v4(); //   augment the http connection with a UUID
  }                                      //   (http keep-alive lets us track per connection)
  log.info({req: req}, 'request start'); // log the HTTP request
  res.on('finish', function() {          // log the HTTP response on the finish event
    log.info({ inResponseTo: req.req_id, res: res, duration: Date.now() - start }, 'request finish');
  })
  next();
});

// for now, 302 to the client page
app.get('/', function(request, response) {
  response.redirect("client.html");
});

//enable static HTTP published resources
app.use(express.static(__dirname + '/public'));

//service end point providing client access to client IP
app.get('/myip', function(request, response) {
  response.json({ip:request.ip,ips:request.ips});
});

//service end point providing HTTP:HEAD support as a convenience method to test if the client is authorized to access.
app.head('/authcheck', restrict, function(request, response) {
  response.status(200).end();
});

/* Service end point for data upload
 * Expecting POST /upload
 * If the post data is too big, we kill it.
 * (Data POSTed here is black-holed)
 */
app.post('/upload', restrict, function(request, response) {
  utils.markConnection(request);
  var uploadsize = 0;
  request.on("data", function(d) {
    uploadsize += d.length;
    d = null; //dump the content
    if (uploadsize > config.upload.maxPayload) {
      var msg = "killing connection - upload was unacceptably large";
      serverlog.info(msg); //TODO - need to look at logging output for error case
      response.status(403).json({message:msg});
      request.connection.destroy();
      return;
    }
  });

  request.on("end", function() {
    var msg = "I just ate "+uploadsize+" bytes";
    response.json({message:msg});
  });
});

/*
 * Allow the client to discover the supported download packages
 */
app.get('/download/config', function(request, response) {
    var p = {
        "download":config.download,
        "upload":config.upload
    };
  response.json(p);
});

/* Service end point for data download
 * Expecting GET /download/:size where :size is an explicitly acceptable value
 * If the requested value is not acceptable, the request flows through to a 404.
 */
app.get('/download/:size', restrict, function(request, response) {
  utils.markConnection(request);
  var packages = config.download.packages;
  var packageSize = "_"+request.params.size.toUpperCase().trim();

  // test for acceptability
  if(!packages[packageSize]){
    response.status(403).json({code:403,message:"Forbidden",supported:packages});
    return;
  }

  var max = packages[packageSize].size;
  response.writeHead(200, {'Content-length': max});

  var bufSize=(randomBuffers.size*1024);
  for(var i = 0; i < max; i += bufSize) {
    var b = randomBuffers.grab(); //64kb of random randomness
    response.write((max - i >= bufSize)?b:b.slice(0,max%bufSize));
  }
  response.end();
});

/* Service end point for result data upload
 * (Data POSTed here is logged for later trending analysis)
 */
app.post('/results', restrict, function(request, response) {
    var payload = "";
    request.on("data", function(d) {
        payload += d;
        if (payload.length > 3*1024) { //never more that that
            var msg = "killing connection - results payload was unacceptably large";
            serverlog.info(msg); //TODO - need to look at logging output for error case
            response.status(403).json({message:msg});
            request.connection.destroy();
            return;
        }
    });
    request.on("end", function() {
        var resultsObject = utils.convertFormDataToJSON(payload);
        resultslog.info({connectionUsageCount:request.connection.usageCount,results:resultsObject,clientIp:request.ip, userAgent:request.headers["user-agent"]},"results received on this connection");
        var msg = "Received results: "+payload.length+" bytes";
        response.json({message:msg, userAgent:request.headers["user-agent"], results:resultsObject});
    });
});

app.listen(app.get('port'), function() {
  console.log("yet-another-speed-test app is running at localhost:" + app.get('port'));
  var cpuCount = require('os').cpus().length;
  serverlog.info("yet-another-speed-test app is running at localhost:" + app.get('port'));
  serverlog.info("cpuCount: "+cpuCount);
});<|endoftext|>


<commit_before>var bookmarklet = {
    content: jQuery('#content'),
    neighborhoods: Array('Wellshire',  'CBD',  'University Hills',  'Overland',  'Speer',  'Gateway / Green Valley Ranch',  'Ruby Hill',  'Marston',  'North Capitol Hill',  'City Park',  'Indian Creek',  'Five Points',  'Sun Valley',  'Westwood',  'Cole',  'Washington Park West',  'Platt Park',  'Harvey Park South',  'Villa Park',  'Athmar Park',  'Skyland',  'North Park Hill',  'Sunnyside',  'Southmoor Park',  'Jefferson Park',  'Capitol Hill',  'Windsor',  'Barnum West',  'Virginia Village',  'Montbello',  'Bear Valley',  'Goldsmith',  'Stapleton',  'Chaffee Park',  'Cory-Merrill',  'Northeast Park Hill',  'Union Station',  'Washington Park',  'Barnum',  'Elyria-Swansea',  'Civic Center',  'Hampden South',  'Globeville',  'City Park West',  'Clayton',  'Cheesman Park',  'Country Club',  'Hale',  'Mar Lee',  'Lincoln Park',  'Berkeley',  'West Highland',  'Harvey Park',  'Regis',  'East Colfax',  'Whittier',  'Belcaro',  'Hampden',  'Fort Logan',  'College View / South Platte',  'West Colfax',  'Baker',  'Kennedy',  'Cherry Creek',  'DIA',  'Congress Park',  'South Park Hill',  'Rosedale',  'Valverde',  'Lowry Field',  'Washington Virginia Vale',  'Auraria',  'Hilltop',  'Highland',  'Montclair',  'University',  'University Park',  'Sloan Lake'),
    get_markup: function() {
        if ( this.type == '1' ) {
            return '[cq comment="ASIDE PLACED BELOW"]\n\n\

Denver Crime
\n\

See our index of reported crimes in Denver\'s ' + this.neighborhood + ' neighborhood, and our ranking of neighborhood crime rates.
\n\
[cq comment="ASIDE PLACED ABOVE"]';
        }
        else if ( this.type == '' ) {
            return '[cq comment="ASIDE PLACED BELOW"]\n\n\

Denver Crime
\n\

\n\

See our map, report and neighborhood rankings of ' + this.crime + ' in Denver.
\n\

New: Compare crime rates across Denver neighborhoods.
\n\
[cq comment="ASIDE PLACED ABOVE"]';
        }
    },
    feature_list: array({'Compare crime rates across Denver neighborhoods': 'http://crime.denverpost.com/neighborhood/compare/'}),
    random_feature: function () {
        // Pull a random item from this.feature_list
    },
    get_type: function () {
        this.type = prompt('Enter 1 for a neighborhood crime promo or hit enter for a crime-specific promo');
        return this.type;
    },
    get_neighborhood: function(message='') {
        this.neighborhood = prompt(message + 'Type in the name of the neighborhood');
        if ( this.neighborhoods.indexOf(this.neighborhood) === -1 ) {
            if ( message == '' ) this.get_neighborhood("That's not a valid neighborhood\n");
            else this.get_neighborhood("This is a list of valid neighborhoods: " + this.neighborhoods.join(", "));
        }
        this.slug = this.slugify(this.neighborhood);
    },
    get_crime: function() {
        crime_id = prompt('Hit enter for Violent Crimes, type 1 for Assaults, 2 for Bank Robberies, 3 for Bike Thefts, \
4 for Burglaries, 5 for Car Thefts, 6 for DUIs, \
7 for hit and runs, 8 for Domestic Violence, 9 for Homicides, 10 for Property Crimes, \
11 for Sexual Assault, 12 for Rape, 13 for Robberies, 14 for Drug & Alcohol, 15 for Larceny');
        this.crime = 'violent crimes'; this.slug = 'violent';
        if ( crime_id.indexOf('10') >= 0 ) { this.crime = 'property crimes'; this.slug = 'property'; }
        else if ( crime_id.indexOf('11') >= 0 ) { this.crime = 'sexual assaults'; this.slug = 'sexual-assault'; }
        else if ( crime_id.indexOf('12') >= 0 ) { this.crime = 'rapes'; this.slug = 'sexual-assault/rape'; }
        else if ( crime_id.indexOf('13') >= 0 ) { this.crime = 'robberies'; this.slug = 'robbery'; }
        else if ( crime_id.indexOf('14') >= 0 ) { this.crime = 'drug and alcohol crimes'; this.slug = 'drug-alcohol'; }
        else if ( crime_id.indexOf('15') >= 0 ) { this.crime = 'larceny'; this.slug = 'larceny'; }
        else if ( crime_id.indexOf('16') >= 0 ) { this.crime = ''; this.slug = ''; }
        else if ( crime_id.indexOf('17') >= 0 ) { this.crime = ''; this.slug = ''; }
        else if ( crime_id.indexOf('18') >= 0 ) { this.crime = ''; this.slug = ''; }
        else if ( crime_id.indexOf('19') >= 0 ) { this.crime = ''; this.slug = ''; }
        else if ( crime_id.indexOf('20') >= 0 ) { this.crime = ''; this.slug = ''; }
        else if ( crime_id.indexOf('1') >= 0 ) { this.crime = 'assaults'; this.slug = 'assault'; }
        else if ( crime_id.indexOf('2') >= 0 ) { this.crime = 'bank robberies'; this.slug = 'robbery/robbery-bank'; }
        else if ( crime_id.indexOf('3') >= 0 ) { this.crime = 'bike thefts'; this.slug = 'theft-bicycle'; }
        else if ( crime_id.indexOf('4') >= 0 ) { this.crime = 'burglaries'; this.slug = 'burglary'; }
        else if ( crime_id.indexOf('5') >= 0 ) { this.crime = 'car thefts'; this.slug = 'auto-theft'; }
        else if ( crime_id.indexOf('6') >= 0 ) { this.crime = 'DUIs'; this.slug = 'traffic-accident-dui-duid'; }
        else if ( crime_id.indexOf('7') >= 0 ) { this.crime = 'hit-and-runs'; this.slug = 'traffic-accident-hit-and-run'; }
        else if ( crime_id.indexOf('8') >= 0 ) { this.crime = 'domestic violence'; this.slug = 'dv'; }
        else if ( crime_id.indexOf('9') >= 0 ) { this.crime = 'homicides'; this.slug = 'homicide'; }
    },
    init: function () {
        this.grafs = this.content.text().split('\n\n');
        this.pos = this.grafs.length;
        if ( this.grafs.length > 5 ) this.pos = this.grafs.length - 3;

        if ( this.get_type() == '1' ) this.get_neighborhood();
        else this.get_crime();

        this.grafs.splice(this.pos, 0, this.get_markup());
        jQuery('#content').text(this.grafs.join('\n\n'));
    },
    slugify: function(str)
    {
        // Cribbed from https://github.com/andrefarzat/slugify/blob/master/slugify.js
        var from = 'àáäãâèéëêìíïîòóöôõùúüûñç·/_,:;',
        to = 'aaaaaeeeeiiiiooooouuuunc------';

        var i = 0,
            len = from.length;

        str = str.toLowerCase();

        for ( ; i < len; i++ )
        {
            str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
        }

        return str.replace(/^\s+|\s+$/g, '') //trim
            .replace(/[^-a-zA-Z0-9\s]+/ig, '')
            .replace(/\s/gi, "-");
    }
}
bookmarklet.init();
<commit_msg>Make the crime include more dynamic<commit_after>var bookmarklet = {
    content: jQuery('#content'),
    neighborhoods: Array('Wellshire',  'CBD',  'University Hills',  'Overland',  'Speer',  'Gateway / Green Valley Ranch',  'Ruby Hill',  'Marston',  'North Capitol Hill',  'City Park',  'Indian Creek',  'Five Points',  'Sun Valley',  'Westwood',  'Cole',  'Washington Park West',  'Platt Park',  'Harvey Park South',  'Villa Park',  'Athmar Park',  'Skyland',  'North Park Hill',  'Sunnyside',  'Southmoor Park',  'Jefferson Park',  'Capitol Hill',  'Windsor',  'Barnum West',  'Virginia Village',  'Montbello',  'Bear Valley',  'Goldsmith',  'Stapleton',  'Chaffee Park',  'Cory-Merrill',  'Northeast Park Hill',  'Union Station',  'Washington Park',  'Barnum',  'Elyria-Swansea',  'Civic Center',  'Hampden South',  'Globeville',  'City Park West',  'Clayton',  'Cheesman Park',  'Country Club',  'Hale',  'Mar Lee',  'Lincoln Park',  'Berkeley',  'West Highland',  'Harvey Park',  'Regis',  'East Colfax',  'Whittier',  'Belcaro',  'Hampden',  'Fort Logan',  'College View / South Platte',  'West Colfax',  'Baker',  'Kennedy',  'Cherry Creek',  'DIA',  'Congress Park',  'South Park Hill',  'Rosedale',  'Valverde',  'Lowry Field',  'Washington Virginia Vale',  'Auraria',  'Hilltop',  'Highland',  'Montclair',  'University',  'University Park',  'Sloan Lake'),
    get_markup: function() {
        if ( this.type == '1' ) {
            return '[cq comment="ASIDE PLACED BELOW"]\n\n\

Denver Crime
\n\

See our index of reported crimes in Denver\'s ' + this.neighborhood + ' neighborhood, and our ranking of neighborhood crime rates.
\n\
[cq comment="ASIDE PLACED ABOVE"]';
        }
        else if ( this.type == '' ) {
            return '[cq comment="ASIDE PLACED BELOW"]\n\n\

Denver Crime
\n\

\n\

See our map, report and neighborhood rankings of ' + this.crime + ' in Denver.
\n\

Also, ' + this.get_random_feature() + '.
\n\
[cq comment="ASIDE PLACED ABOVE"]';
        }
    },
    image_list: array('http://www.denverpost.com/wp-content/uploads/2017/01/denver-crime-map11.png', 'http://www.denverpost.com/wp-content/uploads/2017/01/denver-crime-map4.png', 'http://www.denverpost.com/wp-content/uploads/2017/01/denver-crime-map3.png', 'http://www.denverpost.com/wp-content/uploads/2017/01/denver-crime-map2.png', 'http://www.denverpost.com/wp-content/uploads/2016/10/denver-crime-map.png'),
    get_random_image: function() {
        var ceiling = this.image_list.length;
        var index = Math.floor(Math.random() * ceiling);
        return this.image_list[index];
    },
    feature_list: array({'compare crime rates across Denver neighborhoods': 'http://crime.denverpost.com/neighborhood/compare/'}, {'see our Denver crime map': 'http://crime.denverpost.com/map/'}, {'see the Denver-city crime report': 'http://crime.denverpost.com/city/'}, {'see our list of neighborhood crime reports': 'http://crime.denverpost.com/neighborhood/'}),
    get_random_feature: function () {
        // Pull a random item from this.feature_list
        var ceiling = this.feature_list.length;
        var index = Math.floor(Math.random() * ceiling);
        var item = this.feature_list[index];
        var key = keys(item)[0];
        return '' + key + '';
    },
    get_type: function () {
        this.type = prompt('Enter 1 for a neighborhood crime promo or hit enter for a crime-specific promo');
        return this.type;
    },
    get_neighborhood: function(message='') {
        this.neighborhood = prompt(message + 'Type in the name of the neighborhood');
        if ( this.neighborhoods.indexOf(this.neighborhood) === -1 ) {
            if ( message == '' ) this.get_neighborhood("That's not a valid neighborhood\n");
            else this.get_neighborhood("This is a list of valid neighborhoods: " + this.neighborhoods.join(", "));
        }
        this.slug = this.slugify(this.neighborhood);
    },
    get_crime: function() {
        crime_id = prompt('Hit enter for Violent Crimes, type 1 for Assaults, 2 for Bank Robberies, 3 for Bike Thefts, \
4 for Burglaries, 5 for Car Thefts, 6 for DUIs, \
7 for hit and runs, 8 for Domestic Violence, 9 for Homicides, 10 for Property Crimes, \
11 for Sexual Assault, 12 for Rape, 13 for Robberies, 14 for Drug & Alcohol, 15 for Larceny');
        this.crime = 'violent crimes'; this.slug = 'violent';
        if ( crime_id.indexOf('10') >= 0 ) { this.crime = 'property crimes'; this.slug = 'property'; }
        else if ( crime_id.indexOf('11') >= 0 ) { this.crime = 'sexual assaults'; this.slug = 'sexual-assault'; }
        else if ( crime_id.indexOf('12') >= 0 ) { this.crime = 'rapes'; this.slug = 'sexual-assault/rape'; }
        else if ( crime_id.indexOf('13') >= 0 ) { this.crime = 'robberies'; this.slug = 'robbery'; }
        else if ( crime_id.indexOf('14') >= 0 ) { this.crime = 'drug and alcohol crimes'; this.slug = 'drug-alcohol'; }
        else if ( crime_id.indexOf('15') >= 0 ) { this.crime = 'larceny'; this.slug = 'larceny'; }
        else if ( crime_id.indexOf('16') >= 0 ) { this.crime = ''; this.slug = ''; }
        else if ( crime_id.indexOf('17') >= 0 ) { this.crime = ''; this.slug = ''; }
        else if ( crime_id.indexOf('18') >= 0 ) { this.crime = ''; this.slug = ''; }
        else if ( crime_id.indexOf('19') >= 0 ) { this.crime = ''; this.slug = ''; }
        else if ( crime_id.indexOf('20') >= 0 ) { this.crime = ''; this.slug = ''; }
        else if ( crime_id.indexOf('1') >= 0 ) { this.crime = 'assaults'; this.slug = 'assault'; }
        else if ( crime_id.indexOf('2') >= 0 ) { this.crime = 'bank robberies'; this.slug = 'robbery/robbery-bank'; }
        else if ( crime_id.indexOf('3') >= 0 ) { this.crime = 'bike thefts'; this.slug = 'theft-bicycle'; }
        else if ( crime_id.indexOf('4') >= 0 ) { this.crime = 'burglaries'; this.slug = 'burglary'; }
        else if ( crime_id.indexOf('5') >= 0 ) { this.crime = 'car thefts'; this.slug = 'auto-theft'; }
        else if ( crime_id.indexOf('6') >= 0 ) { this.crime = 'DUIs'; this.slug = 'traffic-accident-dui-duid'; }
        else if ( crime_id.indexOf('7') >= 0 ) { this.crime = 'hit-and-runs'; this.slug = 'traffic-accident-hit-and-run'; }
        else if ( crime_id.indexOf('8') >= 0 ) { this.crime = 'domestic violence'; this.slug = 'dv'; }
        else if ( crime_id.indexOf('9') >= 0 ) { this.crime = 'homicides'; this.slug = 'homicide'; }
    },
    init: function () {
        this.grafs = this.content.text().split('\n\n');
        this.pos = this.grafs.length;
        if ( this.grafs.length > 5 ) this.pos = this.grafs.length - 3;

        if ( this.get_type() == '1' ) this.get_neighborhood();
        else this.get_crime();

        this.grafs.splice(this.pos, 0, this.get_markup());
        jQuery('#content').text(this.grafs.join('\n\n'));
    },
    slugify: function(str)
    {
        // Cribbed from https://github.com/andrefarzat/slugify/blob/master/slugify.js
        var from = 'àáäãâèéëêìíïîòóöôõùúüûñç·/_,:;',
        to = 'aaaaaeeeeiiiiooooouuuunc------';

        var i = 0,
            len = from.length;

        str = str.toLowerCase();

        for ( ; i < len; i++ )
        {
            str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
        }

        return str.replace(/^\s+|\s+$/g, '') //trim
            .replace(/[^-a-zA-Z0-9\s]+/ig, '')
            .replace(/\s/gi, "-");
    }
}
bookmarklet.init();
<|endoftext|>


<commit_before>'use strict';

var mongoose = require('mongoose'),
  path = require('path'),
  User = mongoose.model('User'),
  // Poll = mongoose.model('Poll'),
  // Opt = mongoose.model('Opt'),
  // Cmt = mongoose.model('Cmt'),
  // Vote = mongoose.model('Vote'),
  // Voteopt = mongoose.model('Voteopt'),
  // Polltag = mongoose.model('Polltag'),
  // Polluser = mongoose.model('Polluser'),
  // Report = mongoose.model('Report'),
  // Bookmark = mongoose.model('Bookmark'),
  // Category = mongoose.model('Category'),
  // View = mongoose.model('View'),
  // Like = mongoose.model('Like'),
  Userreport = mongoose.model('Userreport');

exports.excute = function () {
  get_users()
    .then(users => {
      console.log(users);
    })
    .catch(err => {
      console.log(err);
    });
};

function get_users() {
  return new Promise((resolve, reject) => {
    var users = User.query({ 'roles': { '$not': { '$all': ['user', 'admin'] } } })
      .then(users => {
        return resolve(users);
      }, err => {
        return reject(err);
      });
  });
}<commit_msg>Commited from HaNhatLenh at Sun, Aug 27, 2017  3:49:24 PM<commit_after>'use strict';

var mongoose = require('mongoose');
  // path = require('path'),
  // User = mongoose.model('User'),
  // Poll = mongoose.model('Poll'),
  // Opt = mongoose.model('Opt'),
  // Cmt = mongoose.model('Cmt'),
  // Vote = mongoose.model('Vote'),
  // Voteopt = mongoose.model('Voteopt'),
  // Polltag = mongoose.model('Polltag'),
  // Polluser = mongoose.model('Polluser'),
  // Report = mongoose.model('Report'),
  // Bookmark = mongoose.model('Bookmark'),
  // Category = mongoose.model('Category'),
  // View = mongoose.model('View'),
  // Like = mongoose.model('Like'),
  //Userreport = mongoose.model('Userreport');

exports.excute = function () {
  get_users()
    .then(users => {
      console.log(users);
    })
    .catch(err => {
      console.log(err);
    });
};

function get_users() {
  return new Promise((resolve, reject) => {
    var User = mongoose.model('User');
    var users = User.query({ 'roles': { '$not': { '$all': ['user', 'admin'] } } })
      .then(users => {
        return resolve(users);
      }, err => {
        return reject(err);
      });
  });
}<|endoftext|>


<commit_before>var fork = require('child_process').fork;
var fs = require('fs');

var scMaster;
var logFileName = process.cwd() + '/socketcluster.out';

var logMessage = function (message) {
  if (typeof message != 'string') {
    message = message.toString();
  }
  process.stdout.write(message);
  fs.appendFileSync(logFileName, message);
};

module.exports.run = function (fileName, args) {
  if (scMaster) {
    scMaster.kill('SIGTERM');
  }

  logMessage('>>>> SocketCluster runner launched - PID: ' + process.pid + '\n');

  var runMaster = function () {
    scMaster = fork(fileName, args, {silent: true});

    scMaster.stdout.on('data', logMessage);
    scMaster.stderr.on('data', logMessage);

    scMaster.on('exit', function (code, signal) {
      try {
        logMessage(Date.now() + ' - SocketCluster master exited with code: ' + code + ', signal: ' + signal + '\n');
      } catch (e) {
        console.log("Could not write to log file '" + logFileName + "' -", e.stack || e.message);
      }
      runMaster();
    });
  };

  runMaster();
};

process.on('SIGTERM', function () {
  logMessage('>>>> SocketCluster runner was terminated by SIGTERM\n');
  scMaster.kill('SIGTERM');
  process.exit();
});

// Capture SIGHUP and ignore
process.on('SIGHUP', function () {});
<commit_msg>Added line to log to allow keeping track of respawned master PIDs<commit_after>var fork = require('child_process').fork;
var fs = require('fs');

var scMaster;
var logFileName = process.cwd() + '/socketcluster.out';

var logMessage = function (message) {
  if (typeof message != 'string') {
    message = message.toString();
  }
  process.stdout.write(message);
  fs.appendFileSync(logFileName, message);
};

module.exports.run = function (fileName, args) {
  if (scMaster) {
    scMaster.kill('SIGTERM');
  }

  logMessage('>>>> SocketCluster runner launched - PID: ' + process.pid + '\n');

  var runMaster = function () {
    scMaster = fork(fileName, args, {silent: true});

    logMessage('>>>> Spawned master - PID: ' + scMaster.pid + '\n');

    scMaster.stdout.on('data', logMessage);
    scMaster.stderr.on('data', logMessage);

    scMaster.on('exit', function (code, signal) {
      try {
        logMessage(Date.now() + ' - SocketCluster master exited with code: ' + code + ', signal: ' + signal + '\n');
      } catch (e) {
        console.log("Could not write to log file '" + logFileName + "' -", e.stack || e.message);
      }
      runMaster();
    });
  };

  runMaster();
};

process.on('SIGTERM', function () {
  logMessage('>>>> SocketCluster runner was terminated by SIGTERM\n');
  scMaster.kill('SIGTERM');
  process.exit();
});

// Capture SIGHUP and ignore
process.on('SIGHUP', function () {});
<|endoftext|>


<commit_before>import React, { PureComponent } from 'react';
import styled from 'styled-components';
import PropTypes from 'prop-types';
import { documentToHtmlString } from '@contentful/rich-text-html-renderer';

import Box from 'react/components/UI/Box';
import Text from 'react/components/UI/Text';

import { Headline, Subheadline, Description } from 'react/pages/about/components/Text';
import { GenericButtonLink as Button } from 'react/components/UI/GenericButton';
import { Table, TableSection, Column, LightColumn, ColumnHeader, Cell } from 'react/pages/about/RoadmapPage/components/Table';

const Container = styled(Box).attrs({
  mt: 9,
})``;

const Paragraph = styled(Description).attrs({
  mx: 'auto',
  my: 7,
  align: 'left',
})`
  max-width: 470px;
  width: 100%;
`;

const ContributeButton = styled(Button).attrs({
  f: 5,
  flex: 1,
  alignSelf: 'center',
})`
  background-color: ${x => x.theme.colors.state.supporter};
  border-color: ${x => x.theme.colors.state.supporter};
  color: white;

  &:hover {
    border-color: ${x => x.theme.colors.state.supporter};
    background-color: white;
    color: ${x => x.theme.colors.state.supporter};
  }
`;

export default class RoadmapPage extends PureComponent {
  static propTypes = {
    roadmap: PropTypes.shape.isRequired,
  }

  render() {
    const { roadmap } = this.props;
    const dateOptions = {
      weekday: 'long', year: 'numeric', month: 'long', day: 'numeric',
    };
    const lastUpdated = new Date(roadmap.sys.updatedAt).toLocaleDateString('en-US', dateOptions);

    return (
      <Container pb={10}>
        <Headline color="gray.bold">
          Here's where we're at.
        </Headline>

        <Paragraph>
          Welcome to the Are.na roadmap.
          Here you can see what we’ve shipped recently, what we’re building next,
          and how we’re doing as a company.
        </Paragraph>

        <Paragraph>
          By sharing this information we aim to demystify the weird and wonderful process of
          working on a mostly bootstrapped web company.
          We’re working our hardest to build a space that’s mindful,
          respectful, and accountable to our thousands of lovely members.
          We have lots of ideas for how to do a better job, as well as lots of challenges.
        </Paragraph>

        <Paragraph pb={8}>
          This is meant to be as transparent as reasonably possible.
          If there’s something you don’t see here that you’d like to know,
          just email everyone@are.na.
        </Paragraph>

        <Headline color="gray.bold">
          Become a monthly supporter
        </Headline>

        <Paragraph>
          Chip in a little extra to help Are.na develop new features and reach sustainability.
          Monthly supporters will receive regular emails from the team,
          plus a unique piece of Are.na merch.
        </Paragraph>

        <Box justifyContent="center" mt={7} mb={10} display="flex">


<commit_before>require('coffeescript/register')
pageHelper = require('../helpers/pageHelper.coffee')

module.exports = {
  'can_sign_up_a_user': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_dashboard_as_visitor')
    page.fillIn('.auth-email-form__email input', 'max_von_sydow@example.com')
    page.click('.auth-email-form__submit')
    page.fillIn('.auth-signup-form__name input', 'Max Von Sydow')
    page.click('.auth-signup-form__legal-accepted .v-input--selection-controls__input')
    page.click('.auth-signup-form__submit')
    page.expectText('.auth-complete', 'Check your email', 3000)
    page.loadPath('use_last_login_token')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')

    // page.expectText('.dashboard-page__heading', 'Recent Threads')
  },

  'can_sign_up_a_new_user_through_the_discussion_page': (test) => {
    page = pageHelper(test)

    page.loadPath('view_open_discussion_as_visitor')
    page.click('.add-comment-panel__sign-in-btn')
    page.fillIn('.auth-email-form__email input', 'max_von_sydow@example.com')
    page.click('.auth-email-form__submit')
    page.fillIn('.auth-signup-form__name input', 'Max Von Sydow')
    page.click('.auth-signup-form__legal-accepted .v-input--selection-controls__input')
    page.click('.auth-signup-form__submit')
    page.expectElement('.auth-complete')
    page.loadPath('use_last_login_token')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
    page.expectText('.context-panel__heading', 'I carried a watermelon')
    page.click('.add-comment-panel__join-actions button')
    page.expectFlash('You are now a member of Open Dirty Dancing Shoes')
    page.expectElement('.comment-form__submit-button')
  },

  'can_login_via_token': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_login_token')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
  },

  'can_use_a_shareable_link': (test) => {
    page = pageHelper(test)

    page.loadPath('view_closed_group_with_shareable_link')
    page.fillIn('.auth-email-form__email input', 'max_von_sydow@example.com')
    page.click('.auth-email-form__submit')
    page.fillIn('.auth-signup-form__name input', 'Max Von Sydow')
    page.click('.auth-signup-form__legal-accepted .v-input--selection-controls__input')
    page.click('.auth-signup-form__submit')
    page.expectText('.auth-complete', 'Check your email')
    page.loadPath('use_last_login_token')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
    // page.expectText('.group-cover-image', 'Dirty Dancing Shoes')
  },

  'does_not_log_in_when_password_is_incorrect': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_explore_as_visitor')
    page.click('.navbar__sign-in')
    page.fillIn('.auth-email-form__email input', 'patrick_swayze@example.com')
    page.click('.auth-email-form__submit')
    page.fillIn('.auth-signin-form__password input', 'w0rstmovie')
    page.click('.auth-signin-form__submit')
    page.expectText('.lmo-validation-error__message', "that password doesn't match")
  },

  'can_send_login_link_to_user_with_a_password': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_dashboard_as_visitor')
    page.fillIn('.auth-email-form__email input', 'patrick_swayze@example.com')
    page.click('.auth-email-form__submit')
    page.click('.auth-signin-form__login-link')
    page.expectText('.auth-complete', 'Check your email')
    page.loadPath('use_last_login_token')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
    // page.expectText('.dashboard-page__heading', 'Recent Threads')
  },

  'does_not_log_in_an_invalid_token': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_used_login_token')
    page.click('.auth-signin-form__submit')
    page.expectText('.lmo-validation-error__message', 'Click below to send another one')
    page.click('.auth-signin-form__submit')
    page.loadPath('use_last_login_token')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
  },

  'can_login_from_the_dashboard': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_dashboard_as_visitor')
    page.fillIn('.auth-email-form__email input', 'jennifer_grey@example.com')
    page.click('.auth-email-form__submit')
    page.click('.auth-signin-form__submit')
    page.expectText('.auth-complete', 'Check your email')
    page.loadPath('use_last_login_token')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
    // page.expectText('.dashboard-page__heading', 'Recent Threads')
  },

  'can_login_from_a_discussion_page': (test) => {
    page = pageHelper(test)

    page.loadPath('view_open_discussion_as_visitor')
    page.click('.add-comment-panel__sign-in-btn')
    page.fillIn('.auth-email-form__email input', 'patrick_swayze@example.com')
    page.click('.auth-email-form__submit')
    page.fillIn('.auth-signin-form__password input', 'gh0stmovie')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
    page.fillIn('.comment-form .ProseMirror', 'I am new!')
    page.click('.comment-form__submit-button')
    page.expectFlash('Comment added')
  },

  'can_login_from_the_explore_page': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_explore_as_visitor')
    page.click('.navbar__sign-in')
    page.fillIn('.auth-email-form__email input', 'patrick_swayze@example.com')
    page.click('.auth-email-form__submit')
    page.fillIn('.auth-signin-form__password input', 'gh0stmovie')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
  },

  'can_login_from_the_explore_page_via_link': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_explore_as_visitor')
    page.click('.navbar__sign-in')
    page.fillIn('.auth-email-form__email input', 'jennifer_grey@example.com')
    page.click('.auth-email-form__submit')
    page.click('.auth-signin-form__submit')
    page.expectText('.auth-complete', 'Check your email')
    page.loadPath('use_last_login_token')
    page.click('.auth-signin-form__submit')

    page.expectFlash('Signed in successfully')
    // page.expectText('.explore-page', 'Explore groups')
  },

  'can_login_from_a_closed_group_page': (test) => {
    page = pageHelper(test)

    page.loadPath('view_closed_group_as_visitor')
    page.click('.navbar__sign-in')
    page.fillIn('.auth-email-form__email input', 'patrick_swayze@example.com')
    page.click('.auth-email-form__submit')
    page.fillIn('.auth-signin-form__password input', 'gh0stmovie')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
    // page.expectText('.group-cover-image', 'Closed Dirty Dancing Shoes')
    // page.expectText('.thread-preview-collection__container', 'This thread is private')
  },

  'can_login_from_a_secret_group_page': (test) => {
    page = pageHelper(test)

    page.loadPath('view_secret_group_as_visitor')
    page.fillIn('.auth-email-form__email input', 'patrick_swayze@example.com')
    page.click('.auth-email-form__submit')
    page.fillIn('.auth-signin-form__password input', 'gh0stmovie')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
    // page.expectText('.group-cover-image', 'Secret Dirty Dancing Shoes')
  },

  'can_invite_existing_user': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_invitation_to_user_with_password')
    page.click('.auth-email-form__submit')
    page.expectText('.auth-signin-form', 'Welcome back, Jennifer!')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
    // page.expectText('.group-cover-image', 'Dirty Dancing Shoes')
    // page.expectNoElement('.join-group-button')
  },

  'can_invite_new_user': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_invitation_to_visitor')
    page.click('.auth-email-form__submit')
    page.expectText('.auth-signup-form', 'New to')
    page.fillIn('.auth-signup-form__name input', 'Billy Jeans')
    page.click('.auth-signup-form__legal-accepted .v-input--selection-controls__input')
    page.click('.auth-signup-form__submit')
    page.expectFlash('Signed in successfully')
    // page.expectText('.group-cover-image', 'Dirty Dancing Shoes')
  },

  // commented out because selenium clearValue is broken on Chrome.
  // 'requires_verification_if_email_is_changed': (test) => {
  //   page = pageHelper(test)
  //
  //   page.loadPath('setup_invitation_to_visitor')
  //   page.fillIn('.auth-email-form__email input', 'max_von_sydow@merciless.com')
  //   // GK: NB: clearValue is not working right now - so the existing input value is being appended to instead
  //   // https://github.com/nightwatchjs/nightwatch/issues/1939
  //   page.click('.auth-email-form__submit')
  //   page.expectText('.auth-signup-form', 'New to')
  //   page.fillIn('.auth-signup-form__name input', 'Billy Jeans')
  //   page.click('.auth-signup-form__legal-accepted .v-input--selection-controls__input')
  //   page.click('.auth-signup-form__submit')
  //   page.expectText('.auth-complete', 'Check your email')
  // },

  'prompts_reactivation_if_required': (test) => {
    page = pageHelper(test)
    page.loadPath('setup_deactivated_user')
    page.fillIn('.auth-email-form__email input', 'patrick_swayze@example.com')
    page.click('.auth-email-form__submit')
    page.expectText('.auth-inactive-form', 'has been deactivated')
    page.expectElement('.auth-inactive-form__reactivate')
  },

  'can_reactivate_the_account': (test) =>  {
    page = pageHelper(test)

    page.loadPath('setup_user_reactivation_email')
    page.click('.base-mailer__button')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
  }

}
<commit_msg>fixing auth e2es<commit_after>require('coffeescript/register')
pageHelper = require('../helpers/pageHelper.coffee')

module.exports = {
  'can_sign_up_a_user': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_dashboard_as_visitor')
    page.fillIn('.auth-email-form__email input', 'max_von_sydow@example.com')
    page.click('.auth-email-form__submit')
    page.fillIn('.auth-signup-form__name input', 'Max Von Sydow')
    page.click('.auth-signup-form__legal-accepted .v-input--selection-controls__input')
    page.click('.auth-signup-form__submit')
    page.expectText('.auth-complete', 'Check your email', 3000)
    page.loadPath('use_last_login_token')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
  },

  'can_sign_up_a_new_user_through_the_discussion_page': (test) => {
    page = pageHelper(test)

    page.loadPath('view_open_discussion_as_visitor')
    page.click('.add-comment-panel__sign-in-btn')
    page.fillIn('.auth-email-form__email input', 'max_von_sydow@example.com')
    page.click('.auth-email-form__submit')
    page.fillIn('.auth-signup-form__name input', 'Max Von Sydow')
    page.click('.auth-signup-form__legal-accepted .v-input--selection-controls__input')
    page.click('.auth-signup-form__submit')
    page.expectElement('.auth-complete')
    page.loadPath('use_last_login_token')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
    // page.expectText('.context-panel__heading', 'I carried a watermelon')
    // page.click('.add-comment-panel__join-actions button')
    // page.expectFlash('You are now a member of Open Dirty Dancing Shoes')
    // page.expectElement('.comment-form__submit-button')
  },

  'can_login_via_token': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_login_token')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
  },

  'can_use_a_shareable_link': (test) => {
    page = pageHelper(test)

    page.loadPath('view_closed_group_with_shareable_link')
    page.fillIn('.auth-email-form__email input', 'max_von_sydow@example.com')
    page.click('.auth-email-form__submit')
    page.fillIn('.auth-signup-form__name input', 'Max Von Sydow')
    page.click('.auth-signup-form__legal-accepted .v-input--selection-controls__input')
    page.click('.auth-signup-form__submit')
    page.expectText('.auth-complete', 'Check your email')
    page.loadPath('use_last_login_token')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
    // page.expectText('.group-cover-image', 'Dirty Dancing Shoes')
  },

  'does_not_log_in_when_password_is_incorrect': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_explore_as_visitor')
    page.click('.navbar__sign-in')
    page.fillIn('.auth-email-form__email input', 'patrick_swayze@example.com')
    page.click('.auth-email-form__submit')
    page.fillIn('.auth-signin-form__password input', 'w0rstmovie')
    page.click('.auth-signin-form__submit')
    page.expectText('.lmo-validation-error__message', "that password doesn't match")
  },

  'can_send_login_link_to_user_with_a_password': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_dashboard_as_visitor')
    page.fillIn('.auth-email-form__email input', 'patrick_swayze@example.com')
    page.click('.auth-email-form__submit')
    page.click('.auth-signin-form__login-link')
    page.expectText('.auth-complete', 'Check your email')
    page.loadPath('use_last_login_token')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
    // page.expectText('.dashboard-page__heading', 'Recent Threads')
  },

  'does_not_log_in_an_invalid_token': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_used_login_token')
    page.click('.auth-signin-form__submit')
    page.expectText('.lmo-validation-error__message', 'Click below to send another one')
    page.click('.auth-signin-form__submit')
    page.loadPath('use_last_login_token')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
  },

  'can_login_from_the_dashboard': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_dashboard_as_visitor')
    page.fillIn('.auth-email-form__email input', 'jennifer_grey@example.com')
    page.click('.auth-email-form__submit')
    page.click('.auth-signin-form__submit')
    page.expectText('.auth-complete', 'Check your email')
    page.loadPath('use_last_login_token')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
    // page.expectText('.dashboard-page__heading', 'Recent Threads')
  },

  'can_login_from_a_discussion_page': (test) => {
    page = pageHelper(test)

    page.loadPath('view_open_discussion_as_visitor')
    page.click('.add-comment-panel__sign-in-btn')
    page.fillIn('.auth-email-form__email input', 'patrick_swayze@example.com')
    page.click('.auth-email-form__submit')
    page.fillIn('.auth-signin-form__password input', 'gh0stmovie')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
    // page.fillIn('.comment-form .ProseMirror', 'I am new!')
    // page.click('.dismiss-modal-button')
    // page.click('.comment-form__submit-button')
    // page.expectFlash('Comment added')
  },

  'can_login_from_the_explore_page': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_explore_as_visitor')
    page.click('.navbar__sign-in')
    page.fillIn('.auth-email-form__email input', 'patrick_swayze@example.com')
    page.click('.auth-email-form__submit')
    page.fillIn('.auth-signin-form__password input', 'gh0stmovie')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
  },

  'can_login_from_the_explore_page_via_link': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_explore_as_visitor')
    page.click('.navbar__sign-in')
    page.fillIn('.auth-email-form__email input', 'jennifer_grey@example.com')
    page.click('.auth-email-form__submit')
    page.click('.auth-signin-form__submit')
    page.expectText('.auth-complete', 'Check your email')
    page.loadPath('use_last_login_token')
    page.click('.auth-signin-form__submit')

    page.expectFlash('Signed in successfully')
    // page.expectText('.explore-page', 'Explore groups')
  },

  'can_login_from_a_closed_group_page': (test) => {
    page = pageHelper(test)

    page.loadPath('view_closed_group_as_visitor')
    page.click('.navbar__sign-in')
    page.fillIn('.auth-email-form__email input', 'patrick_swayze@example.com')
    page.click('.auth-email-form__submit')
    page.fillIn('.auth-signin-form__password input', 'gh0stmovie')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
    page.expectText('.v-toolbar__title', 'Closed Dirty Dancing Shoes')
    page.expectText('.thread-previews', 'This thread is private')
  },

  'can_login_from_a_secret_group_page': (test) => {
    page = pageHelper(test)

    page.loadPath('view_secret_group_as_visitor')
    page.fillIn('.auth-email-form__email input', 'patrick_swayze@example.com')
    page.click('.auth-email-form__submit')
    page.fillIn('.auth-signin-form__password input', 'gh0stmovie')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
    page.expectText('.v-toolbar__title', 'Secret Dirty Dancing Shoes')
  },

  'can_invite_existing_user': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_invitation_to_user_with_password')
    page.click('.auth-email-form__submit')
    page.expectText('.auth-signin-form', 'Welcome back, Jennifer!')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
    // page.expectText('.group-cover-image', 'Dirty Dancing Shoes')
    // page.expectNoElement('.join-group-button')
  },

  'can_invite_new_user': (test) => {
    page = pageHelper(test)

    page.loadPath('setup_invitation_to_visitor')
    page.click('.auth-email-form__submit')
    page.expectText('.auth-signup-form', 'New to')
    page.fillIn('.auth-signup-form__name input', 'Billy Jeans')
    page.click('.auth-signup-form__legal-accepted .v-input--selection-controls__input')
    page.click('.auth-signup-form__submit')
    page.expectFlash('Signed in successfully')
    // page.expectText('.group-cover-image', 'Dirty Dancing Shoes')
  },

  // commented out because selenium clearValue is broken on Chrome.
  // 'requires_verification_if_email_is_changed': (test) => {
  //   page = pageHelper(test)
  //
  //   page.loadPath('setup_invitation_to_visitor')
  //   page.fillIn('.auth-email-form__email input', 'max_von_sydow@merciless.com')
  //   // GK: NB: clearValue is not working right now - so the existing input value is being appended to instead
  //   // https://github.com/nightwatchjs/nightwatch/issues/1939
  //   page.click('.auth-email-form__submit')
  //   page.expectText('.auth-signup-form', 'New to')
  //   page.fillIn('.auth-signup-form__name input', 'Billy Jeans')
  //   page.click('.auth-signup-form__legal-accepted .v-input--selection-controls__input')
  //   page.click('.auth-signup-form__submit')
  //   page.expectText('.auth-complete', 'Check your email')
  // },

  'prompts_reactivation_if_required': (test) => {
    page = pageHelper(test)
    page.loadPath('setup_deactivated_user')
    page.fillIn('.auth-email-form__email input', 'patrick_swayze@example.com')
    page.click('.auth-email-form__submit')
    page.expectText('.auth-inactive-form', 'has been deactivated')
    page.expectElement('.auth-inactive-form__reactivate')
  },

  'can_reactivate_the_account': (test) =>  {
    page = pageHelper(test)

    page.loadPath('setup_user_reactivation_email')
    page.click('.base-mailer__button')
    page.click('.auth-signin-form__submit')
    page.expectFlash('Signed in successfully')
  }

}
<|endoftext|>