<commit_before>/*!
 * coo-coo v0.0.0, https://github.com/hoho/coo-coo
 * (c) 2013 Marat Abdullin, MIT license
 */
var fs = require('fs'),
    util = require('./util.js');

var INDENT_WITH = ' ',
    INDENT = INDENT_WITH + INDENT_WITH + INDENT_WITH + INDENT_WITH,

    COO_COMMAND_PART_STRING = 'string',
    COO_COMMAND_PART_JS = 'javascript',
    COO_COMMAND_PART_IDENTIFIER = 'identifier';

function CooCommand() {

}

CooCommand.prototype = {
    _setget: function(name, val) {
        if (val === undefined) { return this[name]; }
        else { this[name] = val; }
    },

    valuePusher: function(val) { return this._setget('_valuePusher', val); },
    valueRequired: function(val) { return this._setget('_valueRequired', val); },
    hasSubblock: function(val) { return this._setget('_hasSubblock', val); },
    parts: function(val) { return this._setget('_parts', val); }
};

function CooCommandPart(type, lineAt, charAt) {
    this._type = type;
    this._lineAt = lineAt;
    this._charAt = charAt;
}

CooCommandPart.prototype = {
    type: function() { return this._type; },
    value: function(val) { return CooCommand.prototype._setget.call(this, val); }
};

function CooFile(filename) {
    var data = fs.readFileSync(filename, {encoding: 'utf8'});

    this.filename = filename;
    this.src = data.split(/\n\r|\r\n|\r|\n/);
    this.code = data.split(/\n\r|\r\n|\r|\n/);

    util.cooClearComments(this.code);
}

CooFile.prototype = {
    read: function(ret) {
        var oldRet = this.ret,
            oldLineAt = this.lineAt,
            oldCharAt = this.charAt,
            oldBlockIndent = this.blockIndent;

        this.ret = ret;
        this.lineAt = this.charAt = 0;
        this.blockIndent = 0;

        while (this.skipEmptyLines()) {
            this.readCommand();
        }

        this.ret = oldRet;
        this.lineAt = oldLineAt;
        this.charAt = oldCharAt;
        this.blockIndent = oldBlockIndent;
    },

    skipEmptyLines: function() {
        for (var i = this.lineAt; i < this.code.length; i++) {
            if (this.code[i] !== '') {
                break;
            }
        }

        this.lineAt = i;
        this.charAt = 0;

        return this.lineAt < this.code.length;
    },

    readCommand: function(parent) {
        var i,
            line = this.code[this.lineAt],
            cmd = new CooCommand();

        for (i = 0; i < this.blockIndent; i++) {
            if (line[i] !== INDENT_WITH) {
                this.errorBadIndentation(i);
            }
        }

        i = this.blockIndent;

        if (line[i] === '+') {
            if (!parent || !parent.valueRequired()) {
                // Pretty dumb error messages.
                this.error(
                    parent ?
                        '"' + parent.name + '" command does not require return value.'
                        :
                        'No place to return value to.',
                    i
                );
            } else {
                // This command pushes value to parent one.
                cmd.valuePusher(true);
                i++;
            }
        }

        if (line[i].match(/[a-zA-Z"'(_]/)) {
            var parts = this.readCommandParts(i);

            cmd.parts(parts);

            if (parts[0].type() === COO_COMMAND_PART_STRING ||
                parts[0].type() === COO_COMMAND_PART_JS)
            {
                // Check for certain conditions in case command begins with
                // a string or with a JavaScript expression.
                if (parent && parent.valueRequired() && cmd.valuePusher()) {
                    // TODO: Implement.

                    if (parts.length > 1) { this.errorUnexpectedPart(parts[1]); }

                    this.nextLine();
                } else {
                    this.errorUnexpectedPart(parts[0]);
                }
            } else {
                // Match command and run it's callback.
                // TODO: Implement.

                if (cmd.hasSubblock()||1) {
                    this.readBlock(cmd);
                } else {
                    this.nextLine();
                }
            }
        } else {
            if (line[i] === INDENT_WITH) { this.errorBadIndentation(i); }
            else { this.errorUnexpectedSymbol(i); }
        }
    },

    readCommandParts: function(charAt) {
        var parts = [];

        this.charAt = charAt;

        while (this.charAt < this.code[this.lineAt].length) {
            switch (this.code[this.lineAt][this.charAt]) {
                case '"':
                /* jshint -W109 */
                case "'":
                /* jshint +W109 */
                    parts.push(this.readString());
                    break;

                case '(':
                    parts.push(this.readJS(0));
                    break;

                default:
                    parts.push(this.readIdentifier());
            }
        }

        return parts;
    },

    readString: function() {
        var part = new CooCommandPart(COO_COMMAND_PART_STRING, this.lineAt, this.charAt);

        this.charAt++;

        return part;
    },

    readJS: function(indent) {
        var part = new CooCommandPart(COO_COMMAND_PART_JS, this.lineAt, this.charAt),
            val = [];

        if (!indent) {
            this.charAt++;
        }

        part.value(val);

        return part;
    },

    readIdentifier: function() {
        var part = new CooCommandPart(COO_COMMAND_PART_IDENTIFIER, this.lineAt, this.charAt);

        this.charAt++;

        return part;
    },

    readBlock: function(parent) {
        if (!this.nextLine()) {
            return false;
        }

        var oldIndent = this.blockIndent,
            indent,
            curIndent;

        indent = this.getIndent();

        if (indent > oldIndent) {
            this.blockIndent = indent;

            curIndent = indent;

            while (curIndent === indent) {
                this.readCommand(parent);
                curIndent = this.nextLine() ? this.getIndent() : 0;
            }

            this.blockIndent = oldIndent;
        }
    },

    nextLine: function() {
        this.lineAt++;
        this.charAt = 0;

        return this.skipEmptyLines();
    },

    getIndent: function() {
        var indent = 0;

        while (this.code[this.lineAt][indent] === INDENT_WITH) {
            indent++;
        }

        return indent;
    },

    skipWhitespaces: function() {

    },

    error: function(msg, charAt, lineAt) {
        var line = (lineAt === undefined ? this.lineAt : lineAt) + 1,
            col = charAt + 1;

        throw new Error(this.filename + ': ' + msg + ' (line: ' + line + ', col: ' + col + '):\n' +
                        this.src[line - 1] + '\n' + (new Array(col).join(' ')) + '^\n');
    },

    errorBadIndentation: function(charAt) {
        this.error('Bad indentation', charAt);
    },

    errorUnexpectedSymbol: function(charAt) {
        this.error('Unexpected symbol', charAt);
    },

    errorUnexpectedPart: function(part) {
        this.error('Unexpected ' + part.type(), part._charAt, part._lineAt);
    }
};

function cooRunGenerators(gen, code, level) {
    var g = gen.gen,
        i,
        indent = (new Array(level)).join(INDENT);

    if (gen.before) {
        code.push(indent + gen.before());
    }

    if (g) {
        for (i = 0; i < g.length; i++) {
            cooRunGenerators(g[i], code, level + 1);
        }
    }

    if (gen.after) {
        code.push(indent + gen.after());
    }
}

function CooCoo(filenames, commons, project) {
    var ret = {
        common: {core: true},
        postParse: {},
        gen: []
    };

    var i,
        file,
        tmp,
        func,
        code = [];

    for (i = 0; i < filenames.length; i++) {
        file = new CooFile(filenames[i]);
        file.read(ret);
    }

    tmp = ret.postParse;
    for (func in tmp) {
        func();
    }

    tmp = ret.gen;
    for (i = 0; i < tmp.length; i++) {
        cooRunGenerators(tmp[i], code, 0);
    }

    console.log(commons, project, code.join('\n'));
}

CooCoo.cmd = {};

module.exports = CooCoo;
<commit_msg>String, JS and identifier readers.<commit_after>/*!
 * coo-coo v0.0.0, https://github.com/hoho/coo-coo
 * (c) 2013 Marat Abdullin, MIT license
 */
var fs = require('fs'),
    util = require('./util.js');

var INDENT_WITH = ' ',
    INDENT = INDENT_WITH + INDENT_WITH + INDENT_WITH + INDENT_WITH,

    COO_COMMAND_PART_STRING = 'string',
    COO_COMMAND_PART_JS = 'javascript',
    COO_COMMAND_PART_IDENTIFIER = 'identifier';

function CooCommand() {

}

CooCommand.prototype = {
    _setget: function(name, val) {
        if (val === undefined) { return this[name]; }
        else { this[name] = val; }
    },

    valuePusher: function(val) { return this._setget('_valuePusher', val); },
    valueRequired: function(val) { return this._setget('_valueRequired', val); },
    hasSubblock: function(val) { return this._setget('_hasSubblock', val); },
    parts: function(val) { return this._setget('_parts', val); }
};

function CooCommandPart(type, lineAt, charAt) {
    this._type = type;
    this._lineAt = lineAt;
    this._charAt = charAt;
}

CooCommandPart.prototype = {
    type: function() { return this._type; },
    value: function(val) { return CooCommand.prototype._setget.call(this, '_value', val); }
};

function CooFile(filename) {
    var data = fs.readFileSync(filename, {encoding: 'utf8'});

    this.filename = filename;
    this.src = data.split(/\n\r|\r\n|\r|\n/);
    this.code = data.split(/\n\r|\r\n|\r|\n/);

    util.cooClearComments(this.code);
}

CooFile.prototype = {
    read: function(ret) {
        var oldRet = this.ret,
            oldLineAt = this.lineAt,
            oldCharAt = this.charAt,
            oldBlockIndent = this.blockIndent;

        this.ret = ret;
        this.lineAt = this.charAt = 0;
        this.blockIndent = 0;

        while (this.skipEmptyLines()) {
            this.readCommand();
        }

        this.ret = oldRet;
        this.lineAt = oldLineAt;
        this.charAt = oldCharAt;
        this.blockIndent = oldBlockIndent;
    },

    skipEmptyLines: function() {
        for (var i = this.lineAt; i < this.code.length; i++) {
            if (this.code[i] !== '') {
                break;
            }
        }

        this.lineAt = i;
        this.charAt = 0;

        return this.lineAt < this.code.length;
    },

    readCommand: function(parent) {
        var i,
            line = this.code[this.lineAt],
            cmd = new CooCommand();

        for (i = 0; i < this.blockIndent; i++) {
            if (line[i] !== INDENT_WITH) {
                this.errorBadIndentation(i);
            }
        }

        i = this.blockIndent;

        if (line[i] === '+') {
            if (!parent || !parent.valueRequired()) {
                // Pretty dumb error messages.
                this.error(
                    parent ?
                        '"' + parent.name + '" command does not require return value.'
                        :
                        'No place to return value to.',
                    i
                );
            } else {
                // This command pushes value to parent one.
                cmd.valuePusher(true);
                i++;
            }
        }

        if (line[i].match(/[a-zA-Z"'(_]/)) {
            var parts = this.readCommandParts(i);

            cmd.parts(parts);

            if (parts[0].type() === COO_COMMAND_PART_STRING ||
                parts[0].type() === COO_COMMAND_PART_JS)
            {
                // Check for certain conditions in case command begins with
                // a string or with a JavaScript expression.
                if (parent && parent.valueRequired() && cmd.valuePusher()) {
                    // TODO: Implement.

                    if (parts.length > 1) { this.errorUnexpectedPart(parts[1]); }

                    this.nextLine();
                } else {
                    this.errorUnexpectedPart(parts[0]);
                }
            } else {
                // Match command and run it's callback.
                // TODO: Implement.

                if (cmd.hasSubblock() || 1) {
                    this.readBlock(cmd);
                } else {
                    this.nextLine();
                }
            }
        } else {
            if (line[i] === INDENT_WITH) { this.errorBadIndentation(i); }
            else { this.errorUnexpectedSymbol(i); }
        }
    },

    readCommandParts: function(charAt) {
        var parts = [];

        this.charAt = charAt;

        while (this.charAt < this.code[this.lineAt].length) {
            switch (this.code[this.lineAt][this.charAt]) {
                case '"':
                /* jshint -W109 */
                case "'":
                /* jshint +W109 */
                    parts.push(this.readString());
                    break;

                case '(':
                    parts.push(this.readJS(0));
                    break;

                default:
                    parts.push(this.readIdentifier());
            }
        }

        return parts;
    },

    readString: function() {
        var part = new CooCommandPart(COO_COMMAND_PART_STRING, this.lineAt, this.charAt),
            line = this.code[this.lineAt],
            startPos = this.charAt,
            starter = line[startPos];

        /* jshint -W109 */
        if (starter !== '"' && starter !== "'") {
        /* jshint +W109 */
            this.errorUnexpectedSymbol();
        }

        this.charAt++;

        while (this.charAt < line.length) {
            if (line[this.charAt] === starter && line[this.charAt - 1] !== '\\') {
                break;
            } else {
                this.charAt++;
            }
        }

        if (this.charAt < line.length) {
            part.value(line.substring(startPos, this.charAt + 1));
            this.charAt++;
            this.skipWhitespaces();
        } else {
            this.error('Unterminated string', startPos);
        }

        return part;
    },

    readJS: function(indent) {
        var part = new CooCommandPart(COO_COMMAND_PART_JS, this.lineAt, this.charAt),
            val = [];

        if (!indent) {
            if (this.code[this.lineAt][this.charAt] !== '(') {
                this.errorUnexpectedSymbol();
            }

            var brackets,
                startLine = this.lineAt,
                startChar = this.charAt,
                inString;

            brackets = 1;
            this.charAt++;

            if ((this.charAt === this.code[this.lineAt].length) && !this.nextLine()) {
                this.error('Unterminated expression', startChar, startLine);
            }

            while (brackets > 0 && (this.charAt < this.code[this.lineAt].length)) {
                if (!inString) {
                    if (this.code[this.lineAt][this.charAt] === '(') {
                        brackets++;
                    } else if (this.code[this.lineAt][this.charAt] === ')') {
                        brackets--;

                        if (brackets === 0) {
                            this.charAt++;
                            break;
                        }
                    /* jshint -W109 */
                    } else if (this.code[this.lineAt][this.charAt] === '"' ||
                               this.code[this.lineAt][this.charAt] === "'")
                    /* jshint +W109 */
                    {
                        inString = this.code[this.lineAt][this.charAt];
                    }
                } else {
                    if (this.code[this.lineAt][this.charAt] === inString &&
                        this.code[this.lineAt][this.charAt - 1] !== '\\')
                    {
                        inString = false;
                    }
                }

                val.push(this.code[this.lineAt][this.charAt]);

                this.charAt++;

                if (this.charAt === this.code[this.lineAt].length) {
                    val.push('\n');

                    if (!this.nextLine()) {
                        this.error('Unterminated expression', startChar, startLine);
                    }
                }
            }

            this.charAt++;
            this.skipWhitespaces();
        } else {
            while (this.nextLine() && this.getIndent() > indent) {
                val.push(this.code[this.lineAt].substring(indent + 1));
            }
        }

        part.value(val.join(indent ? '\n' : ''));

        return part;
    },

    readIdentifier: function() {
        var part = new CooCommandPart(COO_COMMAND_PART_IDENTIFIER, this.lineAt, this.charAt),
            line = this.code[this.lineAt],
            val = [line[this.charAt]];

        if (!line[this.charAt].match(/[a-zA-Z_]/)) {
            this.errorUnexpectedSymbol();
        }

        this.charAt++;

        while (this.charAt < line.length && line[this.charAt].match(/[a-zA-Z0-9_]/)) {
            val.push(line[this.charAt]);
            this.charAt++;
        }

        this.skipWhitespaces();

        part.value(val.join(''));

        return part;
    },

    readBlock: function(parent) {
        if (!this.nextLine()) {
            return false;
        }

        var oldIndent = this.blockIndent,
            indent,
            curIndent;

        indent = this.getIndent();

        if (indent > oldIndent) {
            this.blockIndent = indent;

            curIndent = indent;

            while (curIndent === indent) {
                this.readCommand(parent);
                curIndent = this.getIndent();
            }

            this.blockIndent = oldIndent;
        }
    },

    nextLine: function() {
        this.lineAt++;
        this.charAt = 0;

        return this.skipEmptyLines();
    },

    getIndent: function() {
        var indent = 0;

        while (this.code[this.lineAt][indent] === INDENT_WITH) {
            indent++;
        }

        return indent;
    },

    skipWhitespaces: function() {
        var line = this.code[this.lineAt];
        while (this.charAt < line.length && line[this.charAt].match(/[\x20\t\r\n\f]/)) {
            this.charAt++;
        }
    },

    error: function(msg, charAt, lineAt) {
        var line = (lineAt === undefined ? this.lineAt : lineAt) + 1,
            col = charAt + 1;

        throw new Error(this.filename + ': ' + msg + ' (line: ' + line + ', col: ' + col + '):\n' +
                        this.src[line - 1] + '\n' + (new Array(col).join(' ')) + '^\n');
    },

    errorBadIndentation: function(charAt) {
        this.error('Bad indentation', charAt);
    },

    errorUnexpectedSymbol: function(charAt) {
        this.error('Unexpected symbol', charAt === undefined ? this.charAt : charAt);
    },

    errorUnexpectedPart: function(part) {
        this.error('Unexpected ' + part.type(), part._charAt, part._lineAt);
    }
};

function cooRunGenerators(gen, code, level) {
    var g = gen.gen,
        i,
        indent = (new Array(level)).join(INDENT);

    if (gen.before) {
        code.push(indent + gen.before());
    }

    if (g) {
        for (i = 0; i < g.length; i++) {
            cooRunGenerators(g[i], code, level + 1);
        }
    }

    if (gen.after) {
        code.push(indent + gen.after());
    }
}

function CooCoo(filenames, commons, project) {
    var ret = {
        common: {core: true},
        postParse: {},
        gen: []
    };

    var i,
        file,
        tmp,
        func,
        code = [];

    for (i = 0; i < filenames.length; i++) {
        file = new CooFile(filenames[i]);
        file.read(ret);
    }

    tmp = ret.postParse;
    for (func in tmp) {
        func();
    }

    tmp = ret.gen;
    for (i = 0; i < tmp.length; i++) {
        cooRunGenerators(tmp[i], code, 0);
    }

    console.log(commons, project, code.join('\n'));
}

CooCoo.cmd = {};

module.exports = CooCoo;
<|endoftext|>


<commit_before>/**
 * @fileOverview Requirejs module containing samsung maple media wrapper
 *
 * @preserve Copyright (c) 2013 British Broadcasting Corporation
 * (http://www.bbc.co.uk) and TAL Contributors (1)
 *
 * (1) TAL Contributors are listed in the AUTHORS file and at
 *     https://github.com/fmtvp/TAL/AUTHORS - please extend this file,
 *     not this notice.
 *
 * @license Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * All rights reserved
 * Please contact us for an alternative licence
 */

require.def(
    'antie/devices/media/samsung_maple',
    [
        'antie/devices/device',
        'antie/widgets/media',
        'antie/events/mediaevent',
        'antie/events/mediaerrorevent',
        'antie/events/mediasourceerrorevent',
        'antie/mediasource'
    ],
    function(Device, Media, MediaEvent, MediaErrorEvent, MediaSourceErrorEvent, MediaSource) {
        function audioLevelCorrection(t) {
            return t * 40.0;
        }
        function invertAudioLevelCorrection(x) {
            return x / 40.0;
        }
        var SamsungPlayer = Media.extend({
            init: function(id, mediaType) {
                this._super(id);

                this.playerPlugin = document.getElementById('playerPlugin');
                this.audioPlugin = document.getElementById('audioPlugin');
                this.tvmwPlugin = document.getElementById('pluginObjectTVMW');
                this.originalSource = this.tvmwPlugin.GetSource();

                this.mediaSource = null;

                var self = this;
                window.addEventListener('unload', function () {
                    self.playerPlugin.Stop();
                    self.tvmwPlugin.SetSource(self.originalSource);
                }, false);

                if (mediaType == "audio") {
                    this._mediaType = "audio";
                } else if (mediaType == "video") {
                    this._mediaType = "video";
                } else {
                    throw new Error('Unrecognised media type: ' + mediaType);
                }

                this.videoPlayerState = {
                    durationSeconds  : 0,
                    currentTime: 0,
                    playbackRate: undefined,
                    paused: false,
                    ended: false,
                    seeking: false,
                    playing: false
                };

                this.registerEventHandlers();
            },

            registerEventHandlers : function() {

                // All functions attached to the window that start SamsungMapleOn
                // will be intercepted and logged, only when test/emit_video_events.js is included
                // for cucumber. Only those that are attached to the window will be intercepted, not
                // functions attached later.
                var self = this;

                window.SamsungMapleOnBufferingStart = function() {
                    self.bubbleEvent(new MediaEvent("waiting", self));
                };
                this.playerPlugin.OnBufferingStart = 'SamsungMapleOnBufferingStart';

                window.SamsungMapleOnBufferingComplete = function() {
                    self.bubbleEvent(new MediaEvent("playing", self));
                };
                this.playerPlugin.OnBufferingComplete = 'SamsungMapleOnBufferingComplete';

                window.SamsungMapleOnConnectionFailed = function() {
                    self.bubbleEvent(new MediaErrorEvent(self, "Connection failed"));
                };
                this.playerPlugin.OnConnectionFailed = 'SamsungMapleOnConnectionFailed';

                window.SamsungMapleOnNetworkDisconnected = function() {
                    self.bubbleEvent(new MediaErrorEvent(self, "Network disconnected"));
                };
                this.playerPlugin.OnNetworkDisconnected = 'SamsungMapleOnNetworkDisconnected';

                window.SamsungMapleOnRenderError = function() {
                    self.bubbleEvent(new MediaErrorEvent(self, "Render error"));
                };
                this.playerPlugin.OnRenderError = 'SamsungMapleOnRenderError';

                window.SamsungMapleOnStreamNotFound = function() {
                    self.bubbleEvent(new MediaErrorEvent(self, "Stream not found"));
                };
                this.playerPlugin.OnStreamNotFound = 'SamsungMapleOnStreamNotFound';

                window.SamsungMapleOnRenderingComplete = function () {
                    self.videoPlayerState.ended = true;
                    window.SamsungMapleOnTimeUpdate(self.videoPlayerState.durationSeconds);
                    self.bubbleEvent(new MediaEvent("ended", self));
                };
                this.playerPlugin.OnRenderingComplete = 'SamsungMapleOnRenderingComplete';

                window.SamsungMapleOnStreamInfoReady = function () {
                    self.videoPlayerState.durationSeconds = self.playerPlugin.GetDuration() / 1000;
                    self.bubbleEvent(new MediaEvent("loadedmetadata", self));
                    self.bubbleEvent(new MediaEvent("durationchange", self));
                    self.bubbleEvent(new MediaEvent("canplay", self));
                    self.bubbleEvent(new MediaEvent("canplaythrough", self));

                };
                this.playerPlugin.OnStreamInfoReady = 'SamsungMapleOnStreamInfoReady';

                window.SamsungMapleOnCurrentPlayTime = function (timeMs) {
                    var seconds = timeMs / 1000.0;
                    if ((self.mediaSource.isLiveStream() && self.videoPlayerState.ended == false) ||
                        (seconds >= 0 && seconds < self.videoPlayerState.durationSeconds)) {
                        self.videoPlayerState.currentTime = seconds;
                        if (self.videoPlayerState.seeking) {
                            self.videoPlayerState.seeking = false;
                            self.bubbleEvent(new MediaEvent('seeked', self));
                        }
                        if (self.videoPlayerState.playing === false) {
                            self.bubbleEvent(new MediaEvent('play', self));
                            self.bubbleEvent(new MediaEvent('playing', self));
                            self.videoPlayerState.playing = true;
                        }
                        else {
                            // don't throw a timeupdate on the first event
                            window.SamsungMapleOnTimeUpdate(seconds);
                        }
                    }
                };
                this.playerPlugin.OnCurrentPlayTime = 'SamsungMapleOnCurrentPlayTime';

                window.SamsungMapleOnTimeUpdate = function(seconds) {
                    self.bubbleEvent(new MediaEvent("timeupdate", self));
                };
            },

            render: function(device) {
                if (!this.outputElement) {
                    this.outputElement = document.createElement("div");
                }
                return this.outputElement;
            },

            // (not part of HTML5 media)
            setWindow: function(left, top, width, height) {
                if (this._mediaType == "audio") {
                    throw new Error('Unable to set window size for Samsung audio.');
                }
                this.playerPlugin.SetDisplayArea(left, top, width, height);
            },
            // readonly attribute MediaError error;
            getError: function() {
                // TODO: Samsung implementation
            },
            // Similar to src attribute or 'source' child elements:
            // attribute DOMString src;
            setSources: function(sources, tags) {
                var dimensions;
                this.videoPlayerState = {
                    durationSeconds  : 0,
                    currentTime: 0,
                    playbackRate: undefined,
                    paused: false,
                    ended: false,
                    seeking: false,
                    playing: false
                };

                this.mediaSource = sources[0];
                this.playerPlugin.Stop();
                // SamsungMaple.pluginAPI.setOffScreenSaver(); // @see http://www.samsungdforum.com/Board/FAQView?BoardID=28797
                this.tvmwPlugin.SetMediaSource();

                this._getSamsungFormattedUrl = this.mediaSource.getURL(tags);
                if (this.mediaSource.isLiveStream()) {
                    this._getSamsungFormattedUrl += "|COMPONENT=HLS";
                }

                dimensions = this.getCurrentApplication().getDevice().getScreenSize();
                this.setWindow(0, 0, dimensions.width, dimensions.height);
            },
            getSources: function() {
                return [this.mediaSource];
            },
            // readonly attribute DOMString currentSrc;
            getCurrentSource: function() {
                return this.mediaSource.src;
            },
            /*
             const unsigned short NETWORK_EMPTY = 0;
             const unsigned short NETWORK_IDLE = 1;
             const unsigned short NETWORK_LOADING = 2;
             const unsigned short NETWORK_NO_SOURCE = 3;
             readonly attribute unsigned short networkState;
             */
            getNetworkState: function() {
                // TODO: Samsung implementation
            },
            // attribute DOMString preload;
            // @returns "none", "metadata" or "auto"
            getPreload: function() {
                // TODO: Samsung implementation
                return "none";
            },
            setPreload: function(preload) {
                // TODO: Samsung implementation
            },
            // readonly attribute TimeRanges buffered;
            getBuffered: function() {
                // TODO: Samsung implementation
                return [];
            },
            // void load();
            load: function() {
                this.videoPlayerState.playbackRate = 1;
                this.videoPlayerState.paused = false;
                this.videoPlayerState.ended = false;
                this.videoPlayerState.playing = false;

                if (this.videoPlayerState.currentTime > 0) {
                    this.playerPlugin.ResumePlay(this._getSamsungFormattedUrl, this.videoPlayerState.currentTime);
                }
                else {
                    this.playerPlugin.Play(this._getSamsungFormattedUrl);
                }
            },
            // DOMString canPlayType(in DOMString type);
            canPlayType: function(type) {
                // TODO: Samsung implementation
                return true;
            },
            /*
             const unsigned short HAVE_NOTHING = 0;
             const unsigned short HAVE_METADATA = 1;
             const unsigned short HAVE_CURRENT_DATA = 2;
             const unsigned short HAVE_FUTURE_DATA = 3;
             const unsigned short HAVE_ENOUGH_DATA = 4;
             readonly attribute unsigned short readyState;
             */
            getReadyState: function() {
                // TODO: Samsung implementation
                return 0;
            },
            // readonly attribute boolean seeking;
            getSeeking: function() {
                // TODO: Samsung implementation
                return false;
            },
            setCurrentTime: function(timeToSeekTo) {
                var offsetInSeconds = timeToSeekTo - this.videoPlayerState.currentTime;
                if (offsetInSeconds > 0) {
                    var jumped = this.playerPlugin.JumpForward(offsetInSeconds);
                    // Jump forward appears not to work consistently in the initial moments of a video playback.
                    // if we are in the initial set up, lets try resuming instead
                    if ((!jumped || jumped < 0) && this.videoPlayerState.currentTime < 1) {
                        this.playerPlugin.Stop();
                        this.playerPlugin.ResumePlay(this._getSamsungFormattedUrl, timeToSeekTo);
                    }
                } else if (offsetInSeconds < 0) {
                    this.playerPlugin.JumpBackward(Math.abs(offsetInSeconds));
                }
                this.videoPlayerState.seeking = true;
                this.bubbleEvent(new MediaEvent('seeking', this));
                this.videoPlayerState.currentTime = timeToSeekTo;
            },
            getCurrentTime: function() {
                // TODO: Samsung implementation
                return this.videoPlayerState.currentTime;
            },
            // readonly attribute double initialTime;
            getInitialTime: function() {
                // TODO: Samsung implementation
                return 0;
            },
            // readonly attribute double duration;
            getDuration: function() {
                // TODO: Samsung implementation
                return this.videoPlayerState.durationSeconds;
            },
            // readonly attribute Date startOffsetTime;
            getStartOffsetTime: function() {
                // TODO: Samsung implementation
                return 0;
            },
            // readonly attribute boolean paused;
            getPaused: function() {
                return this.videoPlayerState.paused;
            },
            // attribute double defaultPlaybackRate;
            getDefaultPlaybackRate: function() {
                // TODO: Samsung implementation
                return 1;
            },
            // attribute double playbackRate;
            getPlaybackRate: function() {
                // TODO: Samsung implementation
                return 1;
            },
            setPlaybackRate: function(playbackRate) {
                // TODO: Samsung implementation
            },
            // readonly attribute TimeRanges played;
            getPlayed: function() {
                // TODO: Samsung implementation
                return [];
            },
            // readonly attribute TimeRanges seekable;
            getSeekable: function() {
                // TODO: Samsung implementation
                return [];
            },
            // readonly attribute boolean ended;
            getEnded: function() {
                // TODO: Samsung implementation
                return false;
            },
            // attribute boolean autoplay;
            getAutoPlay: function() {
                // TODO: Samsung implementation
                return false;
            },
            setAutoPlay: function(autoplay) {
                // TODO: Samsung implementation
            },
            // attribute boolean loop;
            getLoop: function() {
                // TODO: Samsung implementation
                return false;
            },
            setLoop: function(loop) {
                // TODO: Samsung implementation
            },
            // void play();
            play: function() {
                if (this.videoPlayerState.paused) {
                    this.playerPlugin.Resume();
                    this.videoPlayerState.paused = false;
                    this.bubbleEvent(new MediaEvent("play", this));
                    this.bubbleEvent(new MediaEvent("playing", this));
                }
            },
            stop: function() {
                this.playerPlugin.Stop();
            },
            // void pause();
            pause: function() {
                var self = this;
                self.playerPlugin.Pause();
                self.videoPlayerState.paused = true;
                window.setTimeout(function() {
                    self.bubbleEvent(new MediaEvent("pause", self))
                }, 0);
            },
            // attribute boolean controls;
            setNativeControls: function(controls) {
                // TODO: Samsung implementation
            },
            getNativeControls: function() {
                // TODO: Samsung implementation
                return false;
            },
            destroy: function() {
                this.stop();
            }
        });

        Device.prototype.createPlayer = function(id, mediaType) {
            return new SamsungPlayer(id, mediaType);
        };
        Device.prototype.getPlayerEmbedMode = function(mediaType) {
            return Media.EMBED_MODE_BACKGROUND;
        };
        /**
         * Check to see if volume control is supported on this device.
         * @returns Boolean true if volume control is supported.
         */
        Device.prototype.isVolumeControlSupported = function() {
            return true;
        };
        /**
         * Get the current volume.
         * @returns The current volume (0.0 to 1.0)
         */
        Device.prototype.getVolume = function() {
            var audio = document.getElementById('audioPlugin');
            return invertAudioLevelCorrection(audio.GetVolume());
        };
        /**
         * Set the current volume.
         * @param {Float} volume The new volume level (0.0 to 1.0).
         */
        Device.prototype.setVolume = function(volume) {
            var audio = document.getElementById('audioPlugin');
            if (volume > 1.0) {
                this.getLogger().warn("Samsung setVolume - Invalid volume specified (" + volume + " > 1.0). Clipped to 1.0");
                volume = 1.0;
            } else if (volume < 0.0) {
                this.getLogger().warn("Samsung setVolume - Invalid volume specified (" + volume + " < 0.0). Clipped to 0.0");
                volume = 0;
            }

            var currentVolume = audio.GetVolume();
            var newVolume = audioLevelCorrection(volume);

            if ((newVolume > currentVolume) && (newVolume - currentVolume < 1.0)) {
                newVolume = currentVolume + 1;
            } else if ((newVolume < currentVolume) && (currentVolume - newVolume < 1.0)) {
                newVolume = currentVolume - 1;
            }
            audio.SetVolume(newVolume);
            return newVolume;
        };
        /**
         * Check to see if the volume is currently muted.
         * @returns Boolean true if the device is currently muted. Otherwise false.
         */
        Device.prototype.getMuted = function() {
            var audio = document.getElementById('audioPlugin');
            return audio.GetSystemMute();
        };
        /**
         * Mute or unmute the device.
         * @param {Boolean} muted The new muted state. Boolean true to mute, false to unmute.
         */
        Device.prototype.setMuted = function(muted) {
            var audio = document.getElementById('audioPlugin');
            audio.SetSystemMute(muted);
        };
    }
);
<commit_msg>Fix Samsung Maple for audio playback.<commit_after>/**
 * @fileOverview Requirejs module containing samsung maple media wrapper
 *
 * @preserve Copyright (c) 2013 British Broadcasting Corporation
 * (http://www.bbc.co.uk) and TAL Contributors (1)
 *
 * (1) TAL Contributors are listed in the AUTHORS file and at
 *     https://github.com/fmtvp/TAL/AUTHORS - please extend this file,
 *     not this notice.
 *
 * @license Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * All rights reserved
 * Please contact us for an alternative licence
 */

require.def(
    'antie/devices/media/samsung_maple',
    [
        'antie/devices/device',
        'antie/widgets/media',
        'antie/events/mediaevent',
        'antie/events/mediaerrorevent',
        'antie/events/mediasourceerrorevent',
        'antie/mediasource'
    ],
    function(Device, Media, MediaEvent, MediaErrorEvent, MediaSourceErrorEvent, MediaSource) {
        function audioLevelCorrection(t) {
            return t * 40.0;
        }
        function invertAudioLevelCorrection(x) {
            return x / 40.0;
        }
        var SamsungPlayer = Media.extend({
            init: function(id, mediaType) {
                this._super(id);

                this.playerPlugin = document.getElementById('playerPlugin');
                this.audioPlugin = document.getElementById('audioPlugin');
                this.tvmwPlugin = document.getElementById('pluginObjectTVMW');
                this.originalSource = this.tvmwPlugin.GetSource();

                this.mediaSource = null;

                var self = this;
                window.addEventListener('unload', function () {
                    self.playerPlugin.Stop();
                    self.tvmwPlugin.SetSource(self.originalSource);
                }, false);

                if (mediaType == "audio") {
                    this._mediaType = "audio";
                } else if (mediaType == "video") {
                    this._mediaType = "video";
                } else {
                    throw new Error('Unrecognised media type: ' + mediaType);
                }

                this.videoPlayerState = {
                    durationSeconds  : 0,
                    currentTime: 0,
                    playbackRate: undefined,
                    paused: false,
                    ended: false,
                    seeking: false,
                    playing: false
                };

                this.registerEventHandlers();
            },

            registerEventHandlers : function() {

                // All functions attached to the window that start SamsungMapleOn
                // will be intercepted and logged, only when test/emit_video_events.js is included
                // for cucumber. Only those that are attached to the window will be intercepted, not
                // functions attached later.
                var self = this;

                window.SamsungMapleOnBufferingStart = function() {
                    self.bubbleEvent(new MediaEvent("waiting", self));
                };
                this.playerPlugin.OnBufferingStart = 'SamsungMapleOnBufferingStart';

                window.SamsungMapleOnBufferingComplete = function() {
                    self.bubbleEvent(new MediaEvent("playing", self));
                };
                this.playerPlugin.OnBufferingComplete = 'SamsungMapleOnBufferingComplete';

                window.SamsungMapleOnConnectionFailed = function() {
                    self.bubbleEvent(new MediaErrorEvent(self, "Connection failed"));
                };
                this.playerPlugin.OnConnectionFailed = 'SamsungMapleOnConnectionFailed';

                window.SamsungMapleOnNetworkDisconnected = function() {
                    self.bubbleEvent(new MediaErrorEvent(self, "Network disconnected"));
                };
                this.playerPlugin.OnNetworkDisconnected = 'SamsungMapleOnNetworkDisconnected';

                window.SamsungMapleOnRenderError = function() {
                    self.bubbleEvent(new MediaErrorEvent(self, "Render error"));
                };
                this.playerPlugin.OnRenderError = 'SamsungMapleOnRenderError';

                window.SamsungMapleOnStreamNotFound = function() {
                    self.bubbleEvent(new MediaErrorEvent(self, "Stream not found"));
                };
                this.playerPlugin.OnStreamNotFound = 'SamsungMapleOnStreamNotFound';

                window.SamsungMapleOnRenderingComplete = function () {
                    self.videoPlayerState.ended = true;
                    window.SamsungMapleOnTimeUpdate(self.videoPlayerState.durationSeconds);
                    self.bubbleEvent(new MediaEvent("ended", self));
                };
                this.playerPlugin.OnRenderingComplete = 'SamsungMapleOnRenderingComplete';

                window.SamsungMapleOnStreamInfoReady = function () {
                    self.videoPlayerState.durationSeconds = self.playerPlugin.GetDuration() / 1000;
                    self.bubbleEvent(new MediaEvent("loadedmetadata", self));
                    self.bubbleEvent(new MediaEvent("durationchange", self));
                    self.bubbleEvent(new MediaEvent("canplay", self));
                    self.bubbleEvent(new MediaEvent("canplaythrough", self));

                };
                this.playerPlugin.OnStreamInfoReady = 'SamsungMapleOnStreamInfoReady';

                window.SamsungMapleOnCurrentPlayTime = function (timeMs) {
                    var seconds = timeMs / 1000.0;
                    if ((self.mediaSource.isLiveStream() && self.videoPlayerState.ended == false) ||
                        (seconds >= 0 && seconds < self.videoPlayerState.durationSeconds)) {
                        self.videoPlayerState.currentTime = seconds;
                        if (self.videoPlayerState.seeking) {
                            self.videoPlayerState.seeking = false;
                            self.bubbleEvent(new MediaEvent('seeked', self));
                        }
                        if (self.videoPlayerState.playing === false) {
                            self.bubbleEvent(new MediaEvent('play', self));
                            self.bubbleEvent(new MediaEvent('playing', self));
                            self.videoPlayerState.playing = true;
                        }
                        else {
                            // don't throw a timeupdate on the first event
                            window.SamsungMapleOnTimeUpdate(seconds);
                        }
                    }
                };
                this.playerPlugin.OnCurrentPlayTime = 'SamsungMapleOnCurrentPlayTime';

                window.SamsungMapleOnTimeUpdate = function(seconds) {
                    self.bubbleEvent(new MediaEvent("timeupdate", self));
                };
            },

            render: function(device) {
                if (!this.outputElement) {
                    this.outputElement = document.createElement("div");
                }
                return this.outputElement;
            },

            // (not part of HTML5 media)
            setWindow: function(left, top, width, height) {
                if (this._mediaType == "audio") {
                    throw new Error('Unable to set window size for Samsung audio.');
                }
                this.playerPlugin.SetDisplayArea(left, top, width, height);
            },
            // readonly attribute MediaError error;
            getError: function() {
                // TODO: Samsung implementation
            },
            // Similar to src attribute or 'source' child elements:
            // attribute DOMString src;
            setSources: function(sources, tags) {
                var dimensions;
                this.videoPlayerState = {
                    durationSeconds  : 0,
                    currentTime: 0,
                    playbackRate: undefined,
                    paused: false,
                    ended: false,
                    seeking: false,
                    playing: false
                };

                this.mediaSource = sources[0];
                this.playerPlugin.Stop();
                // SamsungMaple.pluginAPI.setOffScreenSaver(); // @see http://www.samsungdforum.com/Board/FAQView?BoardID=28797
                this.tvmwPlugin.SetMediaSource();

                this._getSamsungFormattedUrl = this.mediaSource.getURL(tags);
                if (this.mediaSource.isLiveStream()) {
                    this._getSamsungFormattedUrl += "|COMPONENT=HLS";
                }

                if (this._mediaType === "video") {
                    dimensions = this.getCurrentApplication().getDevice().getScreenSize();
                    this.setWindow(0, 0, dimensions.width, dimensions.height);
                }
            },
            getSources: function() {
                return [this.mediaSource];
            },
            // readonly attribute DOMString currentSrc;
            getCurrentSource: function() {
                return this.mediaSource.src;
            },
            /*
             const unsigned short NETWORK_EMPTY = 0;
             const unsigned short NETWORK_IDLE = 1;
             const unsigned short NETWORK_LOADING = 2;
             const unsigned short NETWORK_NO_SOURCE = 3;
             readonly attribute unsigned short networkState;
             */
            getNetworkState: function() {
                // TODO: Samsung implementation
            },
            // attribute DOMString preload;
            // @returns "none", "metadata" or "auto"
            getPreload: function() {
                // TODO: Samsung implementation
                return "none";
            },
            setPreload: function(preload) {
                // TODO: Samsung implementation
            },
            // readonly attribute TimeRanges buffered;
            getBuffered: function() {
                // TODO: Samsung implementation
                return [];
            },
            // void load();
            load: function() {
                this.videoPlayerState.playbackRate = 1;
                this.videoPlayerState.paused = false;
                this.videoPlayerState.ended = false;
                this.videoPlayerState.playing = false;

                if (this.videoPlayerState.currentTime > 0) {
                    this.playerPlugin.ResumePlay(this._getSamsungFormattedUrl, this.videoPlayerState.currentTime);
                }
                else {
                    this.playerPlugin.Play(this._getSamsungFormattedUrl);
                }
            },
            // DOMString canPlayType(in DOMString type);
            canPlayType: function(type) {
                // TODO: Samsung implementation
                return true;
            },
            /*
             const unsigned short HAVE_NOTHING = 0;
             const unsigned short HAVE_METADATA = 1;
             const unsigned short HAVE_CURRENT_DATA = 2;
             const unsigned short HAVE_FUTURE_DATA = 3;
             const unsigned short HAVE_ENOUGH_DATA = 4;
             readonly attribute unsigned short readyState;
             */
            getReadyState: function() {
                // TODO: Samsung implementation
                return 0;
            },
            // readonly attribute boolean seeking;
            getSeeking: function() {
                // TODO: Samsung implementation
                return false;
            },
            setCurrentTime: function(timeToSeekTo) {
                var offsetInSeconds = timeToSeekTo - this.videoPlayerState.currentTime;
                if (offsetInSeconds > 0) {
                    var jumped = this.playerPlugin.JumpForward(offsetInSeconds);
                    // Jump forward appears not to work consistently in the initial moments of a video playback.
                    // if we are in the initial set up, lets try resuming instead
                    if ((!jumped || jumped < 0) && this.videoPlayerState.currentTime < 1) {
                        this.playerPlugin.Stop();
                        this.playerPlugin.ResumePlay(this._getSamsungFormattedUrl, timeToSeekTo);
                    }
                } else if (offsetInSeconds < 0) {
                    this.playerPlugin.JumpBackward(Math.abs(offsetInSeconds));
                }
                this.videoPlayerState.seeking = true;
                this.bubbleEvent(new MediaEvent('seeking', this));
                this.videoPlayerState.currentTime = timeToSeekTo;
            },
            getCurrentTime: function() {
                // TODO: Samsung implementation
                return this.videoPlayerState.currentTime;
            },
            // readonly attribute double initialTime;
            getInitialTime: function() {
                // TODO: Samsung implementation
                return 0;
            },
            // readonly attribute double duration;
            getDuration: function() {
                // TODO: Samsung implementation
                return this.videoPlayerState.durationSeconds;
            },
            // readonly attribute Date startOffsetTime;
            getStartOffsetTime: function() {
                // TODO: Samsung implementation
                return 0;
            },
            // readonly attribute boolean paused;
            getPaused: function() {
                return this.videoPlayerState.paused;
            },
            // attribute double defaultPlaybackRate;
            getDefaultPlaybackRate: function() {
                // TODO: Samsung implementation
                return 1;
            },
            // attribute double playbackRate;
            getPlaybackRate: function() {
                // TODO: Samsung implementation
                return 1;
            },
            setPlaybackRate: function(playbackRate) {
                // TODO: Samsung implementation
            },
            // readonly attribute TimeRanges played;
            getPlayed: function() {
                // TODO: Samsung implementation
                return [];
            },
            // readonly attribute TimeRanges seekable;
            getSeekable: function() {
                // TODO: Samsung implementation
                return [];
            },
            // readonly attribute boolean ended;
            getEnded: function() {
                // TODO: Samsung implementation
                return false;
            },
            // attribute boolean autoplay;
            getAutoPlay: function() {
                // TODO: Samsung implementation
                return false;
            },
            setAutoPlay: function(autoplay) {
                // TODO: Samsung implementation
            },
            // attribute boolean loop;
            getLoop: function() {
                // TODO: Samsung implementation
                return false;
            },
            setLoop: function(loop) {
                // TODO: Samsung implementation
            },
            // void play();
            play: function() {
                if (this.videoPlayerState.paused) {
                    this.playerPlugin.Resume();
                    this.videoPlayerState.paused = false;
                    this.bubbleEvent(new MediaEvent("play", this));
                    this.bubbleEvent(new MediaEvent("playing", this));
                }
            },
            stop: function() {
                this.playerPlugin.Stop();
            },
            // void pause();
            pause: function() {
                var self = this;
                self.playerPlugin.Pause();
                self.videoPlayerState.paused = true;
                window.setTimeout(function() {
                    self.bubbleEvent(new MediaEvent("pause", self))
                }, 0);
            },
            // attribute boolean controls;
            setNativeControls: function(controls) {
                // TODO: Samsung implementation
            },
            getNativeControls: function() {
                // TODO: Samsung implementation
                return false;
            },
            destroy: function() {
                this.stop();
            }
        });

        Device.prototype.createPlayer = function(id, mediaType) {
            return new SamsungPlayer(id, mediaType);
        };
        Device.prototype.getPlayerEmbedMode = function(mediaType) {
            return Media.EMBED_MODE_BACKGROUND;
        };
        /**
         * Check to see if volume control is supported on this device.
         * @returns Boolean true if volume control is supported.
         */
        Device.prototype.isVolumeControlSupported = function() {
            return true;
        };
        /**
         * Get the current volume.
         * @returns The current volume (0.0 to 1.0)
         */
        Device.prototype.getVolume = function() {
            var audio = document.getElementById('audioPlugin');
            return invertAudioLevelCorrection(audio.GetVolume());
        };
        /**
         * Set the current volume.
         * @param {Float} volume The new volume level (0.0 to 1.0).
         */
        Device.prototype.setVolume = function(volume) {
            var audio = document.getElementById('audioPlugin');
            if (volume > 1.0) {
                this.getLogger().warn("Samsung setVolume - Invalid volume specified (" + volume + " > 1.0). Clipped to 1.0");
                volume = 1.0;
            } else if (volume < 0.0) {
                this.getLogger().warn("Samsung setVolume - Invalid volume specified (" + volume + " < 0.0). Clipped to 0.0");
                volume = 0;
            }

            var currentVolume = audio.GetVolume();
            var newVolume = audioLevelCorrection(volume);

            if ((newVolume > currentVolume) && (newVolume - currentVolume < 1.0)) {
                newVolume = currentVolume + 1;
            } else if ((newVolume < currentVolume) && (currentVolume - newVolume < 1.0)) {
                newVolume = currentVolume - 1;
            }
            audio.SetVolume(newVolume);
            return newVolume;
        };
        /**
         * Check to see if the volume is currently muted.
         * @returns Boolean true if the device is currently muted. Otherwise false.
         */
        Device.prototype.getMuted = function() {
            var audio = document.getElementById('audioPlugin');
            return audio.GetSystemMute();
        };
        /**
         * Mute or unmute the device.
         * @param {Boolean} muted The new muted state. Boolean true to mute, false to unmute.
         */
        Device.prototype.setMuted = function(muted) {
            var audio = document.getElementById('audioPlugin');
            audio.SetSystemMute(muted);
        };
    }
);
<|endoftext|>


<commit_before>/*
 *
 * Upload
 *
 */

import _ from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';
import Script from 'react-load-script';
import { connect } from 'react-redux';
import { withStyles } from 'material-ui/styles';
import Paper from 'material-ui/Paper';
import Popover from 'material-ui/Popover';
import Button from 'material-ui/Button';
import Grid from 'material-ui/Grid';
import {
  MdRefresh,
  MdThumbUp,
  MdChevronRight,
  MdPublic,
  MdDelete,
} from 'react-icons/lib/md';
import Modal from 'material-ui/Modal';
import IFrame from 'react-iframe';
import ReactGA from 'react-ga';

import { createStructuredSelector } from 'reselect';
import axios from 'axios';

/* import { apiRoot, uploadGraphqlRoot } from 'utils/constants';*/
/* import { apiRoot } from 'utils/constants';*/
import * as snackbarActions from 'containers/AppSnackBar/actions';
import PublicationView from 'components/PublicationView';
import { prettyPrintReference } from 'utils/functions';
import { apiRoot } from 'utils/constants';

import { styles } from './styles';
import makeSelectUpload from './selectors';

/* const apiRoot = 'https://catappdatabase2-pr-63.herokuapp.com';*/
/* const apiRoot = 'http://localhost:5000';*/
const backendRoot = `${apiRoot}/apps/upload`;
const url = `${backendRoot}/upload_dataset/`;
const userInfoUrl = `${backendRoot}/user_info`;
const logoutUrl = `${backendRoot}/logout`;
const releaseUrl = `${backendRoot}/release`;
const endorseUrl = `${backendRoot}/endorse`;
const deleteUrl = `${backendRoot}/delete`;

// TODO: COMMENT OUT IN PRODUCTION
/* const uploadGraphqlRoot = 'http://localhost:5000/apps/upload/graphql';*/
const uploadGraphqlRoot = `${apiRoot}/apps/upload/graphql`;

export class Upload extends React.Component { // eslint-disable-line react/prefer-stateless-function
  constructor(props) {
    super(props);
    this.state = {
      uploadError: '',
      loginModalOpen: false,
      loginUrl: '',
      userInfo: {},
      datasets: [],
      pubId: '',
      showHelp: true,
      pubEntries: {},
      popoverAnchorElement: null,
    };

    this.logout = this.logout.bind(this);
    this.fetchUserInfo = this.fetchUserInfo.bind(this);
    this.getDatasets = this.getDatasets.bind(this);
    this.handleFileDrop = this.handleFileDrop.bind(this);
    this.handleSocialLogin = this.handleSocialLogin.bind(this);
    this.handleSocialLoginFailure = this.handleSocialLoginFailure.bind(this);
    this.handleRelease = this.handleRelease.bind(this);
    this.handleEndorse = this.handleEndorse.bind(this);
    this.handleDelete = this.handleDelete.bind(this);
    this.handlePopoverOpen = this.handlePopoverOpen.bind(this);
    this.handlePopoverClose = this.handlePopoverClose.bind(this);
    this.login = this.login.bind(this);
    this.setDataset = this.setDataset.bind(this);
    this.toggleHelp = this.toggleHelp.bind(this);
    this.windowLogin = this.windowLogin.bind(this);
  }

  componentDidMount() {
    if (_.get(this.props, 'location.query.login') === 'success') {
      this.fetchUserInfo();
      this.getDatasets();
    }
  }

  componentWillReceiveProps(nextProps) {
    if (_.get(nextProps, 'location.query.login') === 'success') {
      this.fetchUserInfo();
      this.getDatasets();
    }
  }

  getDatasets() {
    const datasetQuery = `{publications { totalCount edges { node {
    title authors doi pubId journal volume pages year
  } } }}`;
    axios.default.withCredentials = true;
    axios.post(uploadGraphqlRoot, {}, {
      method: 'POST',
      data: {
        query: datasetQuery,
      },
      withCredentials: true,
    }).then((response) => {
      this.setState({
        datasets: response.data.data.publications.edges.map(
          (edge) => edge.node),
      });
    });
    const pubEntryQuery = `{reactions(username:"~", distinct: true) {
  edges { node { pubId username } } }}`;
    axios({
      url: uploadGraphqlRoot,
      method: 'POST',
      data: {
        query: pubEntryQuery,
      },
      withCredentials: true,
    }).then((response) => {
      const pubEntries = _.groupBy(response.data.data.reactions.edges.map((x) => x.node),
        'pubId');

      this.setState({
        pubEntries,
      });
    });
  }

  setDataset(dataset) {
    this.setState({
      pubId: dataset.pubId,
    });
  }

  handlePopoverOpen(event) {
    this.setState({
      popoverAnchorElement: event.currentTarget,
    });
  }

  handlePopoverClose() {
    this.setState({
      popoverAnchorElement: null,
    });
  }

  handleEndorse(dataset) {
    ReactGA.event({
      category: 'Endorse',
      action: 'Endorse a Dataset',
      label: dataset.pubId,
    });

    const correspondentQuery = `{reactions(first: 1, pubId: "${dataset.pubId}") {
  edges {
    node {
      id
      username
    }
  }
}}`;
    axios.post(uploadGraphqlRoot, {}, {
      method: 'POST',
      data: {
        query: correspondentQuery,
      },
      withCredentials: true,
    }).then((response) => {
      axios.post(endorseUrl, {
        dataset,
        userInfo: this.state.userInfo,
        corresponding_email: response.data.data.reactions.edges[0].node.username,
      }).then((messageResponse) => {
        this.props.openSnackbar(messageResponse.data.message);
      });
    });
  }

  handleRelease(dataset) {
    const correspondentQuery = `{reactions(first: 1, pubId: "${dataset.pubId}") {
  edges {
    node {
      id
      username
    }
  }
}}`;
    axios.post(uploadGraphqlRoot, {}, {
      method: 'POST',
      data: {
        query: correspondentQuery,
      },
      withCredentials: true,
    }).then((response) => {
      axios.post(releaseUrl, {
        dataset,
        userInfo: this.state.userInfo,
        corresponding_email: response.data.data.reactions.edges[0].node.username,
      }).then((messageResponse) => {
        this.props.openSnackbar(messageResponse.data.message);
      });
    });
  }

  handleDelete(dataset) {
    // TODO: Implement confirmation dialogue
    const correspondentQuery = `{reactions(first: 1, pubId: "${dataset.pubId}") {
  edges {
    node {
      id
      username
    }
  }
}}`;
    axios.post(uploadGraphqlRoot, {}, {
      method: 'POST',
      data: {
        query: correspondentQuery,
      },
      withCredentials: true,
    }).then((response) => {
      axios.post(deleteUrl, {
        dataset,
        userInfo: this.state.userInfo,
        corresponding_email: response.data.data.reactions.edges[0].node.username,
      }).then((messageResponse) => {
        this.props.openSnackbar(messageResponse.data.message);
        this.getDatasets();
      });
    });
  }

  handleSocialLogin() {
  }

  handleSocialLoginFailure() {
  }

  fetchUserInfo() {
    axios.get(userInfoUrl, {
      data: {},
      withCredentials: true,
    }).then((response) => {
      this.setState({
        userInfo: response.data,

      });
    });
  }

  login() {
    const uploadUrl = `${apiRoot}/apps/upload/submit`;
    axios.get(uploadUrl).then((response) => {
      this.setState({
        loginModalOpen: true,
        loginUrl: response.data.location,
      });
    });
  }

  logout() {
    axios(logoutUrl, {
      method: 'post',
      data: {},
      withCredentials: true,
    }).then(() => {
      this.setState({
        userInfo: {},
        datasets: [],
        pubId: '',
      });
    });
  }

  windowLogin() {
    const uploadUrl = `${apiRoot}/apps/upload/`;
    /* console.log("WINDOW LOGIN")*/
    /* console.log(uploadUrl)*/
    axios(uploadUrl, {
      method: 'get',
      mode: 'no-cors',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      withCredentials: true,
      credentials: 'same-origin',
    }).then((response) => {
      /* console.log(response)*/
      window.open(response.data.location);
      window.focus();
      window.close();
    });
  }

  handleClose() {
    this.setState({
      loginModalOpen: false,
    });
  }

  handleFileDrop(files) {
    const formData = new FormData();
    formData.append('file', files[0]);
    axios.post(url, formData, { headers: { 'content-type': 'multipart/form-data' } }).then((response) => response);
  }

  toggleHelp() {
    this.setState({
      showHelp: !this.state.showHelp,
    });
  }

  render() {
    return (


<commit_before>var React = require('react');
var Transition = React.addons.CSSTransitionGroup;
var classnames = require('classnames');
var utils = require('../utils.js');

var CurrentListStore = require('../stores/CurrentListStore');

var ListFiltersAddForm = require('./ListFiltersAddForm');
var Popout = require('./Popout');
var PopoutList = require('./PopoutList');

var { Button, FormField, FormInput, InputGroup } = require('elemental');

function pluck(arr, key) {
	return arr.map(obj => obj[key]);
}

var ListFiltersAdd = React.createClass({

	displayName: 'ListFiltersAdd',

	getDefaultProps () {
		return {
			maxHeight: 360
		};
	},

	getInitialState () {
		return this.getStateFromStore();
	},

	componentWillReceiveProps (nextProps) {
		this.setState({ isOpen: nextProps.isOpen });
	},

	getStateFromStore () {
		return {
			activeFilters: CurrentListStore.getActiveFilters(),
			availableFilters: CurrentListStore.getAvailableColumns(),
			innerHeight: 0,
			isOpen: false,
			searchString: '',
			selectedField: false,
		};
	},

	updateSearch (e) {
		this.setState({ searchString: e.target.value });
	},

	openPopout () {
		this.setState({
			isOpen: true
		}, this.focusSearch);
	},

	closePopout () {
		this.setState({ isOpen: false, selectedField: false, searchString: '', innerHeight: 0 });
	},

	setPopoutHeight (height) {
		this.setState({ innerHeight: Math.min(this.props.maxHeight, height) });
	},

	navigateBack () {
		this.setState({
			selectedField: false,
			searchString: '',
			innerHeight: 0
		}, this.focusSearch);
	},

	focusSearch () {
		React.findDOMNode(this.refs.search).focus();
	},

	selectField (field) {
		this.setState({
			selectedField: field
		});
	},

	applyFilter (value) {
		CurrentListStore.setFilter(this.state.selectedField.path, value);
		this.closePopout();
	},

	renderList () {
		let activeFilterFields = pluck(this.state.activeFilters, 'field');
		let activeFilterPaths = pluck(activeFilterFields, 'path');

		let { availableFilters, searchString } = this.state;
		let searchRegex = new RegExp(searchString);

		function searchFilter (filter) {
			if (filter.type === 'heading') return false;
			return searchRegex.test(filter.field.label.toLowerCase());
		};

		let filteredFilters = searchString ? availableFilters.filter(searchFilter) : availableFilters;

		var popoutList = filteredFilters.map((el, i) => {
			if (el.type === 'heading') {
				return <PopoutList.Heading key={'heading_' + i}>{el.content}</PopoutList.Heading>;
			}
			var filterIsActive = activeFilterPaths.length && (activeFilterPaths.indexOf(el.field.path) > -1);
			return (
				<PopoutList.Item
					key={'item_' + el.field.path}
					icon={filterIsActive ? 'check' : 'chevron-right'}
					iconHover={filterIsActive ? 'check' : 'chevron-right'}
					isSelected={!!filterIsActive}
					label={el.field.label}
					onClick={() => { this.selectField(el.field); }} />
			);
		});

		return (
			<Popout.Pane onLayout={this.setPopoutHeight} key="list">
				<Popout.Body>
					<FormField style={{ borderBottom: '1px dashed rgba(0,0,0,0.1)', paddingBottom: '1em' }}>
						<FormInput ref="search" value={this.state.searchString} onChange={this.updateSearch} placeholder="Find a filter..." />
					</FormField>
					{popoutList}
				</Popout.Body>
			</Popout.Pane>
		);
	},

	renderForm () {
		return (
			<Popout.Pane onLayout={this.setPopoutHeight} key="form">
				<ListFiltersAddForm field={this.state.selectedField} onApply={this.applyFilter} onCancel={this.closePopout} onBack={this.navigateBack} maxHeight={this.props.maxHeight} />
			</Popout.Pane>
		);
	},

	render () {
		let { selectedField } = this.state;
		let popoutBodyStyle = this.state.innerHeight ? { height: this.state.innerHeight } : null;
		let popoutPanesClassname = classnames('Popout__panes', {
			'Popout__scrollable-area': !selectedField
		});

		return (
			<InputGroup.Section className={this.props.className}>
				<Button id="listHeaderFilterButton" isActive={this.state.isOpen} onClick={this.state.isOpen ? this.closePopout : this.openPopout}>

					Filter

				</Button>
				<Popout isOpen={this.state.isOpen} onCancel={this.closePopout} relativeToID="listHeaderFilterButton">
					<Popout.Header
						leftAction={selectedField ? this.navigateBack : null}
						leftIcon={selectedField ? 'chevron-left' : null}
						title={selectedField ? selectedField.label : 'Filter'}
						transitionDirection={!!selectedField ? 'next' : 'prev'} />
					<Transition style={popoutBodyStyle} className={popoutPanesClassname} transitionName={!!selectedField ? 'Popout__pane-next' : 'Popout__pane-prev'} component="div">
						{selectedField ? this.renderForm() : this.renderList()}
					</Transition>
				</Popout>
			</InputGroup.Section>
		);
	}

});

module.exports = ListFiltersAdd;
<commit_msg>Cleaning up ListFiltersAdd<commit_after>var React = require('react');
var Transition = React.addons.CSSTransitionGroup;
var classnames = require('classnames');

var CurrentListStore = require('../stores/CurrentListStore');
var ListFiltersAddForm = require('./ListFiltersAddForm');
var Popout = require('./Popout');
var PopoutList = require('./PopoutList');
var { Button, FormField, FormInput, InputGroup } = require('elemental');

function pluck(arr, key) {
	return arr.map(obj => obj[key]);
}

var ListFiltersAdd = React.createClass({

	displayName: 'ListFiltersAdd',

	getDefaultProps () {
		return {
			maxHeight: 360
		};
	},

	getInitialState () {
		return this.getStateFromStore();
	},

	componentWillReceiveProps (nextProps) {
		this.setState({ isOpen: nextProps.isOpen });
	},

	getStateFromStore () {
		return {
			activeFilters: CurrentListStore.getActiveFilters(),
			availableFilters: CurrentListStore.getAvailableColumns(),
			innerHeight: 0,
			isOpen: false,
			searchString: '',
			selectedField: false,
		};
	},

	updateSearch (e) {
		this.setState({ searchString: e.target.value });
	},

	openPopout () {
		this.setState({
			isOpen: true
		}, this.focusSearch);
	},

	closePopout () {
		this.setState({ isOpen: false, selectedField: false, searchString: '', innerHeight: 0 });
	},

	setPopoutHeight (height) {
		this.setState({ innerHeight: Math.min(this.props.maxHeight, height) });
	},

	navigateBack () {
		this.setState({
			selectedField: false,
			searchString: '',
			innerHeight: 0
		}, this.focusSearch);
	},

	focusSearch () {
		React.findDOMNode(this.refs.search).focus();
	},

	selectField (field) {
		this.setState({
			selectedField: field
		});
	},

	applyFilter (value) {
		CurrentListStore.setFilter(this.state.selectedField.path, value);
		this.closePopout();
	},

	renderList () {
		let activeFilterFields = pluck(this.state.activeFilters, 'field');
		let activeFilterPaths = pluck(activeFilterFields, 'path');

		let { availableFilters, searchString } = this.state;
		let searchRegex = new RegExp(searchString);

		function searchFilter (filter) {
			if (filter.type === 'heading') return false;
			return searchRegex.test(filter.field.label.toLowerCase());
		};

		let filteredFilters = searchString ? availableFilters.filter(searchFilter) : availableFilters;

		var popoutList = filteredFilters.map((el, i) => {
			if (el.type === 'heading') {
				return <PopoutList.Heading key={'heading_' + i}>{el.content}</PopoutList.Heading>;
			}
			var filterIsActive = activeFilterPaths.length && (activeFilterPaths.indexOf(el.field.path) > -1);
			return (
				<PopoutList.Item
					key={'item_' + el.field.path}
					icon={filterIsActive ? 'check' : 'chevron-right'}
					iconHover={filterIsActive ? 'check' : 'chevron-right'}
					isSelected={!!filterIsActive}
					label={el.field.label}
					onClick={() => { this.selectField(el.field); }} />
			);
		});

		return (
			<Popout.Pane onLayout={this.setPopoutHeight} key="list">
				<Popout.Body>
					<FormField style={{ borderBottom: '1px dashed rgba(0,0,0,0.1)', paddingBottom: '1em' }}>
						<FormInput ref="search" value={this.state.searchString} onChange={this.updateSearch} placeholder="Find a filter..." />
					</FormField>
					{popoutList}
				</Popout.Body>
			</Popout.Pane>
		);
	},

	renderForm () {
		return (
			<Popout.Pane onLayout={this.setPopoutHeight} key="form">
				<ListFiltersAddForm field={this.state.selectedField} onApply={this.applyFilter} onCancel={this.closePopout} onBack={this.navigateBack} maxHeight={this.props.maxHeight} />
			</Popout.Pane>
		);
	},

	render () {
		let { selectedField } = this.state;
		let popoutBodyStyle = this.state.innerHeight ? { height: this.state.innerHeight } : null;
		let popoutPanesClassname = classnames('Popout__panes', {
			'Popout__scrollable-area': !selectedField
		});

		return (
			<InputGroup.Section className={this.props.className}>
				<Button id="listHeaderFilterButton" isActive={this.state.isOpen} onClick={this.state.isOpen ? this.closePopout : this.openPopout}>

					Filter

				</Button>
				<Popout isOpen={this.state.isOpen} onCancel={this.closePopout} relativeToID="listHeaderFilterButton">
					<Popout.Header
						leftAction={selectedField ? this.navigateBack : null}
						leftIcon={selectedField ? 'chevron-left' : null}
						title={selectedField ? selectedField.label : 'Filter'}
						transitionDirection={!!selectedField ? 'next' : 'prev'} />
					<Transition style={popoutBodyStyle} className={popoutPanesClassname} transitionName={!!selectedField ? 'Popout__pane-next' : 'Popout__pane-prev'} component="div">
						{selectedField ? this.renderForm() : this.renderList()}
					</Transition>
				</Popout>
			</InputGroup.Section>
		);
	}

});

module.exports = ListFiltersAdd;
<|endoftext|>


<commit_before>'use strict';

var config = require('./config.webgme'),
    path = require('path'),
    os = require('os');

config.server.port = 8001;

config.authentication.enable = true;
config.authentication.allowGuests = true;
config.authentication.guestAccount = 'demo';
//config.authentication.logOutUrl = 'http://' + os.hostname(); // FIXME: use config.server.https.enable to decide on protocol
config.authentication.jwt.privateKey = path.join(__dirname, '..', '..', '..', 'token_keys', 'private_key');
config.authentication.jwt.publicKey = path.join(__dirname, '..', '..', '..', 'token_keys', 'public_key');
config.requirejsPaths['widgets/DiagramDesigner'] =
    './node_modules/webgme-bip-editors/src/visualizers/widgets/DiagramDesigner';

config.requirejsPaths['bipsrc'] = './node_modules/webgme-bip/src';

config.plugin.allowServerExecution = false;
config.executor.enable = false;
config.addOn.enable = false;

config.mongo.uri = 'mongodb://127.0.0.1:27017/webgme';

config.seedProjects.basePaths.push('./seeds');
config.seedProjects.defaultProject = 'Boilerplate';

config.server.behindSecureProxy = true;

config.client.errorReporting.enable = true;
config.client.errorReporting.DSN = 'https://3118066a25db430086ad064fb35af2e8@sentry.io/118310';

//TODO This should probably not be configured from here (for now it will do)
config.visualization.svgDirs.push('./node_modules/power/Icons');
config.visualization.svgDirs.push('./node_modules/webgme-bip/src/svgs');

module.exports = config;
<commit_msg>Set logOutUrl to empty -> will logout to webgme.org is coming from there<commit_after>'use strict';

var config = require('./config.webgme'),
    path = require('path'),
    os = require('os');

config.server.port = 8001;

config.authentication.enable = true;
config.authentication.allowGuests = true;
config.authentication.guestAccount = 'demo';
config.authentication.logOutUrl = '';
config.authentication.jwt.privateKey = path.join(__dirname, '..', '..', '..', 'token_keys', 'private_key');
config.authentication.jwt.publicKey = path.join(__dirname, '..', '..', '..', 'token_keys', 'public_key');
config.requirejsPaths['widgets/DiagramDesigner'] =
    './node_modules/webgme-bip-editors/src/visualizers/widgets/DiagramDesigner';

config.requirejsPaths['bipsrc'] = './node_modules/webgme-bip/src';

config.plugin.allowServerExecution = false;
config.executor.enable = false;
config.addOn.enable = false;

config.mongo.uri = 'mongodb://127.0.0.1:27017/webgme';

config.seedProjects.basePaths.push('./seeds');
config.seedProjects.defaultProject = 'Boilerplate';

config.server.behindSecureProxy = true;

config.client.errorReporting.enable = true;
config.client.errorReporting.DSN = 'https://3118066a25db430086ad064fb35af2e8@sentry.io/118310';

//TODO This should probably not be configured from here (for now it will do)
config.visualization.svgDirs.push('./node_modules/power/Icons');
config.visualization.svgDirs.push('./node_modules/webgme-bip/src/svgs');

module.exports = config;
<|endoftext|>


<commit_before>/*
 * Motion test on mouse event
 */

$(function(){
	var $canvas = $('#main')
	var canvas = $canvas.get(0);
	var speed = 30;
	var height = $canvas.attr('height');
	var width = $canvas.attr('width');

	var cellHeight = 20;
	var cellWidth = 20;
	var strokeWidth = 1;
	var strokeStyle = 'rgb(40,40,40)';
	var rows = height/20;
	var cols = width/20;
	var defaultColor = 'rgba(10,40,200, 1)';

	var grid = new Array();
	var gridBuffer = new Array();

	var STARTING_RADIUS = 20
		, MAX_RADIUS = 40;

	var radius = STARTING_RADIUS,
		expanding = true;

	var c_x = 200
		c_y = 200;

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

	function init(){
		//Initialize grids
		draw();
	}

	function updateRadius(){
		if(radius < STARTING_RADIUS) {
			expanding = true;
		}
		else if(radius > MAX_RADIUS) {
			expanding = false;
		}
		if(expanding){
			radius += 2;
		}
		else{
			radius -= 2;
		}
	}

	function addAlpha(ctx){
		ctx.beginPath();
		ctx.rect(0,0,width,height);
		ctx.fillStyle = 'rgba(256,256,256, .5)';
		ctx.fill();
	}

	function draw(){
		if (canvas.getContext) {
		  var context = canvas.getContext("2d");
		  context.beginPath();
		  context.arc(c_x,c_y,radius,0,Math.PI*2,true);
		  context.fillStyle = 'rgb(0,0,100)';
		  context.fill();
			context.strokeStyle = 'rgb(40,40,40)';
			context.lineWidth = strokeWidth;
			context.stroke();
			updateRadius();
			addAlpha(context);
			// Future-proof: when feature is fully standardized
			if (window.requestAnimationFrame) window.requestAnimationFrame(draw);
			// IE implementation
			else if (window.msRequestAnimationFrame) window.msRequestAnimationFrame(draw);
			// Firefox implementation
			else if (window.mozRequestAnimationFrame) window.mozRequestAnimationFrame(draw);
			// Chrome implementation
			else if (window.webkitRequestAnimationFrame) window.webkitRequestAnimationFrame(draw);
			// Other browsers that do not yet support feature
			else setTimeout(draw, PERIOD);
		}
	}
	$canvas.on('mousemove', function(e){
		c_x = (e.pageX-$(this).offset().left);
    	c_y = (e.pageY-$(this).offset().top);
  	});
	init();
});
<commit_msg>Added cursor hiding<commit_after>/*
 * Motion test on mouse event
 */

$(function(){
	var $canvas = $('#main')
	var canvas = $canvas.get(0);
	var speed = 30;
	var height = $canvas.attr('height');
	var width = $canvas.attr('width');

	var cellHeight = 20;
	var cellWidth = 20;
	var strokeWidth = 1;
	var strokeStyle = 'rgb(40,40,40)';
	var rows = height/20;
	var cols = width/20;
	var defaultColor = 'rgba(10,40,200, 1)';

	var grid = new Array();
	var gridBuffer = new Array();

	var STARTING_RADIUS = 20
		, MAX_RADIUS = 40;

	var radius = STARTING_RADIUS,
		expanding = true;

	var c_x = 200
		c_y = 200;

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

	function init(){
		//Initialize grids
		draw();
	}

	function updateRadius(){
		if(radius < STARTING_RADIUS) {
			expanding = true;
		}
		else if(radius > MAX_RADIUS) {
			expanding = false;
		}
		if(expanding){
			radius += 2;
		}
		else{
			radius -= 2;
		}
	}

	function addAlpha(ctx){
		ctx.beginPath();
		ctx.rect(0,0,width,height);
		ctx.fillStyle = 'rgba(256,256,256, .5)';
		ctx.fill();
	}

	function draw(){
		if (canvas.getContext) {
		  var context = canvas.getContext("2d");
		  context.beginPath();
		  context.arc(c_x,c_y,radius,0,Math.PI*2,true);
		  context.fillStyle = 'rgb(0,0,100)';
		  context.fill();
			context.strokeStyle = 'rgb(40,40,40)';
			context.lineWidth = strokeWidth;
			context.stroke();
			updateRadius();
			addAlpha(context);
			// Future-proof: when feature is fully standardized
			if (window.requestAnimationFrame) window.requestAnimationFrame(draw);
			// IE implementation
			else if (window.msRequestAnimationFrame) window.msRequestAnimationFrame(draw);
			// Firefox implementation
			else if (window.mozRequestAnimationFrame) window.mozRequestAnimationFrame(draw);
			// Chrome implementation
			else if (window.webkitRequestAnimationFrame) window.webkitRequestAnimationFrame(draw);
			// Other browsers that do not yet support feature
			else setTimeout(draw, PERIOD);
		}
	}
	$canvas.on('mousemove', function(e){
		c_x = (e.pageX-$(this).offset().left);
    	c_y = (e.pageY-$(this).offset().top);
  	});
  	$canvas.css('cursor', 'none');
	init();
});
<|endoftext|>


<commit_before>/*
 *  Circular require should work in CommonJS.
 */

/*---
{
    "custom": true
}
---*/

/*===
require.find foo
loading foo
require.find bar
loading bar
foo.val=123
foo.val + bar.val = 357
123
===*/

require.find = function (id) {
    print('require.find', id);
    if (id == 'foo') {
        return "print('loading foo');\n" +
               "exports.val = 123;\n" +
               "print('foo.val + bar.val = ' + (require('foo').val + require('bar').val));\n"
    } else if (id == 'bar') {
        return "print('loading bar');\n" +
               "print('foo.val=' + require('foo').val);\n" +
               "exports.val = 234;\n";
    } else {
        throw new Error('no such module: ' + id);
    }
}

try {
    print(require('foo').val);
} catch (e) {
    print(e);
}
<commit_msg>fix testcase to use Duktape.find; this will change again though<commit_after>/*
 *  Circular require should work in CommonJS.
 */

/*---
{
    "custom": true
}
---*/

/*===
Duktape.find foo
loading foo
Duktape.find bar
loading bar
foo.val=123
foo.val + bar.val = 357
123
===*/

Duktape.find = function (id) {
    print('Duktape.find', id);
    if (id == 'foo') {
        return "print('loading foo');\n" +
               "exports.val = 123;\n" +
               "print('foo.val + bar.val = ' + (require('foo').val + require('bar').val));\n"
    } else if (id == 'bar') {
        return "print('loading bar');\n" +
               "print('foo.val=' + require('foo').val);\n" +
               "exports.val = 234;\n";
    } else {
        throw new Error('no such module: ' + id);
    }
}

try {
    print(require('foo').val);
} catch (e) {
    print(e);
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

const React = require('react')
const ReactDOM = require('react-dom')
const ImmutableComponent = require('./immutableComponent')
const Tab = require('./tab')
const windowActions = require('../actions/windowActions')
const appActions = require('../actions/appActions')
const siteTags = require('../constants/siteTags')
const dragTypes = require('../constants/dragTypes')
const siteUtil = require('../state/siteUtil')
const dnd = require('../dnd')
const dndData = require('../dndData')

class PinnedTabs extends ImmutableComponent {
  constructor () {
    super()
    this.onDragOver = this.onDragOver.bind(this)
    this.onDrop = this.onDrop.bind(this)
  }

  onDrop (e) {
    const clientX = e.clientX
    const sourceDragData = dndData.getDragData(e.dataTransfer, dragTypes.TAB)

    // This must be executed async because the state change that this causes
    // will cause the onDragEnd to never run
    setTimeout(() => {
      const key = sourceDragData.get('key')
      let droppedOnTab = dnd.closestFromXOffset(this.tabRefs.filter((tab) => tab && tab.props.frameProps.get('key') !== key), clientX).selectedRef
      if (droppedOnTab) {
        const isLeftSide = dnd.isLeftSide(ReactDOM.findDOMNode(droppedOnTab), clientX)
        const droppedOnFrameProps = this.props.frames.find((frame) => frame.get('key') === droppedOnTab.props.frameProps.get('key'))
        windowActions.moveTab(sourceDragData, droppedOnFrameProps, isLeftSide)
        if (!sourceDragData.get('pinnedLocation')) {
          windowActions.setPinned(sourceDragData, true)
        } else {
          appActions.moveSite(siteUtil.getDetailFromFrame(sourceDragData, siteTags.PINNED),
            siteUtil.getDetailFromFrame(droppedOnFrameProps, siteTags.PINNED),
            isLeftSide)
        }
      }
    }, 0)
  }

  onDragOver (e) {
    e.dataTransfer.dropEffect = 'move'
    e.preventDefault()
  }

  render () {
    this.tabRefs = []
    return

       {
          this.props.frames
            .filter((frameProps) => frameProps.get('pinnedLocation'))
            .map((frameProps) =>
              <Tab activeDraggedTab={this.props.tabs.get('activeDraggedTab')}
                ref={(node) => this.tabRefs.push(node)}
                draggingOverData={this.props.draggingOverData}
                frameProps={frameProps}
                frames={this.props.frames}
                key={'tab-' + frameProps.get('key')}
                paintTabs={this.props.paintTabs}
                previewTabs={this.props.previewTabs}
                isActive={this.props.activeFrame === frameProps}
                isPrivate={frameProps.get('isPrivate')}
                partOfFullPageSet={this.props.partOfFullPageSet} />)
      }

  }
}

module.exports = PinnedTabs
<commit_msg>Drag and drop should not be allowed to pin a tab for about:blank and about:newtab tabs<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

const React = require('react')
const ReactDOM = require('react-dom')
const ImmutableComponent = require('./immutableComponent')
const Tab = require('./tab')
const windowActions = require('../actions/windowActions')
const appActions = require('../actions/appActions')
const siteTags = require('../constants/siteTags')
const dragTypes = require('../constants/dragTypes')
const siteUtil = require('../state/siteUtil')
const dnd = require('../dnd')
const dndData = require('../dndData')
const {isIntermediateAboutPage} = require('../lib/appUrlUtil')

class PinnedTabs extends ImmutableComponent {
  constructor () {
    super()
    this.onDragOver = this.onDragOver.bind(this)
    this.onDrop = this.onDrop.bind(this)
  }

  onDrop (e) {
    const clientX = e.clientX
    const sourceDragData = dndData.getDragData(e.dataTransfer, dragTypes.TAB)

    // This must be executed async because the state change that this causes
    // will cause the onDragEnd to never run
    setTimeout(() => {
      const key = sourceDragData.get('key')
      let droppedOnTab = dnd.closestFromXOffset(this.tabRefs.filter((tab) => tab && tab.props.frameProps.get('key') !== key), clientX).selectedRef
      if (droppedOnTab) {
        const isLeftSide = dnd.isLeftSide(ReactDOM.findDOMNode(droppedOnTab), clientX)
        const droppedOnFrameProps = this.props.frames.find((frame) => frame.get('key') === droppedOnTab.props.frameProps.get('key'))
        windowActions.moveTab(sourceDragData, droppedOnFrameProps, isLeftSide)
        if (!sourceDragData.get('pinnedLocation')) {
          const location = sourceDragData.get('location')
          if (!(location === 'about:blank' || location === 'about:newtab' || isIntermediateAboutPage(location))) {
            windowActions.setPinned(sourceDragData, true)
          }
        } else {
          appActions.moveSite(siteUtil.getDetailFromFrame(sourceDragData, siteTags.PINNED),
            siteUtil.getDetailFromFrame(droppedOnFrameProps, siteTags.PINNED),
            isLeftSide)
        }
      }
    }, 0)
  }

  onDragOver (e) {
    e.dataTransfer.dropEffect = 'move'
    e.preventDefault()
  }

  render () {
    this.tabRefs = []
    return

       {
          this.props.frames
            .filter((frameProps) => frameProps.get('pinnedLocation'))
            .map((frameProps) =>
              <Tab activeDraggedTab={this.props.tabs.get('activeDraggedTab')}
                ref={(node) => this.tabRefs.push(node)}
                draggingOverData={this.props.draggingOverData}
                frameProps={frameProps}
                frames={this.props.frames}
                key={'tab-' + frameProps.get('key')}
                paintTabs={this.props.paintTabs}
                previewTabs={this.props.previewTabs}
                isActive={this.props.activeFrame === frameProps}
                isPrivate={frameProps.get('isPrivate')}
                partOfFullPageSet={this.props.partOfFullPageSet} />)
      }

  }
}

module.exports = PinnedTabs
<|endoftext|>