<commit_before>/*
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @constructor
 */
WebInspector.AllocationProfile = function(profile, liveObjectStats)
{
    this._strings = profile.strings;
    this._liveObjectStats = liveObjectStats;

    this._nextNodeId = 1;
    this._functionInfos = []
    this._idToNode = {};
    this._idToTopDownNode = {};
    this._collapsedTopNodeIdToFunctionInfo = {};

    this._traceTops = null;

    this._buildFunctionAllocationInfos(profile);
    this._traceTree = this._buildAllocationTree(profile, liveObjectStats);
}

WebInspector.AllocationProfile.prototype = {
    _buildFunctionAllocationInfos: function(profile)
    {
        var strings = this._strings;

        var functionInfoFields = profile.snapshot.meta.trace_function_info_fields;
        var functionIdOffset = functionInfoFields.indexOf("function_id");
        var functionNameOffset = functionInfoFields.indexOf("name");
        var scriptNameOffset = functionInfoFields.indexOf("script_name");
        var scriptIdOffset = functionInfoFields.indexOf("script_id");
        var lineOffset = functionInfoFields.indexOf("line");
        var columnOffset = functionInfoFields.indexOf("column");
        var functionInfoFieldCount = functionInfoFields.length;

        var rawInfos = profile.trace_function_infos;
        var infoLength = rawInfos.length;
        var functionInfos = this._functionInfos = new Array(infoLength / functionInfoFieldCount);
        var index = 0;
        for (var i = 0; i < infoLength; i += functionInfoFieldCount) {
            functionInfos[index++] = new WebInspector.FunctionAllocationInfo(
                strings[rawInfos[i + functionNameOffset]],
                strings[rawInfos[i + scriptNameOffset]],
                rawInfos[i + scriptIdOffset],
                rawInfos[i + lineOffset],
                rawInfos[i + columnOffset]);
        }
    },

    _buildAllocationTree: function(profile, liveObjectStats)
    {
        var traceTreeRaw = profile.trace_tree;
        var functionInfos = this._functionInfos;
        var idToTopDownNode = this._idToTopDownNode;

        var traceNodeFields = profile.snapshot.meta.trace_node_fields;
        var nodeIdOffset = traceNodeFields.indexOf("id");
        var functionInfoIndexOffset = traceNodeFields.indexOf("function_info_index");
        var allocationCountOffset = traceNodeFields.indexOf("count");
        var allocationSizeOffset = traceNodeFields.indexOf("size");
        var childrenOffset = traceNodeFields.indexOf("children");
        var nodeFieldCount = traceNodeFields.length;

        function traverseNode(rawNodeArray, nodeOffset, parent)
        {
            var functionInfo = functionInfos[rawNodeArray[nodeOffset + functionInfoIndexOffset]];
            var id = rawNodeArray[nodeOffset + nodeIdOffset];
            var stats = liveObjectStats[id];
            var liveCount = stats ? stats.count : 0;
            var liveSize = stats ? stats.size : 0;
            var result = new WebInspector.TopDownAllocationNode(
                id,
                functionInfo,
                rawNodeArray[nodeOffset + allocationCountOffset],
                rawNodeArray[nodeOffset + allocationSizeOffset],
                liveCount,
                liveSize,
                parent);
            idToTopDownNode[id] = result;
            functionInfo.addTraceTopNode(result);

            var rawChildren = rawNodeArray[nodeOffset + childrenOffset];
            for (var i = 0; i < rawChildren.length; i += nodeFieldCount) {
                result.children.push(traverseNode(rawChildren, i, result));
            }
            return result;
        }

        return traverseNode(traceTreeRaw, 0, null);
    },

    /**
     * @return {!Array.<!WebInspector.HeapSnapshotCommon.SerializedAllocationNode>}
     */
    serializeTraceTops: function()
    {
        if (this._traceTops)
            return this._traceTops;
        var result = this._traceTops = [];
        var functionInfos = this._functionInfos;
        for (var i = 0; i < functionInfos.length; i++) {
            var info = functionInfos[i];
            if (info.totalCount === 0)
                continue;
            var nodeId = this._nextNodeId++;
            result.push(this._serializeNode(
                nodeId,
                info,
                info.totalCount,
                info.totalSize,
                info.totalLiveCount,
                info.totalLiveSize,
                true));
            this._collapsedTopNodeIdToFunctionInfo[nodeId] = info;
        }
        result.sort(function(a, b) {
            return b.size - a.size;
        });
        return result;
    },

    /**
     * @param {number} nodeId
     * @return {!WebInspector.HeapSnapshotCommon.AllocationNodeCallers}
     */
    serializeCallers: function(nodeId)
    {
        var node = this._ensureBottomUpNode(nodeId);
        var nodesWithSingleCaller = [];
        while (node.callers().length === 1) {
            node = node.callers()[0];
            nodesWithSingleCaller.push(this._serializeCaller(node));
        }

        var branchingCallers = [];
        var callers = node.callers();
        for (var i = 0; i < callers.length; i++) {
            branchingCallers.push(this._serializeCaller(callers[i]));
        }
        return new WebInspector.HeapSnapshotCommon.AllocationNodeCallers(nodesWithSingleCaller, branchingCallers);
    },

    /**
     * @param {number} traceNodeId
     * @return {!Array.<!WebInspector.HeapSnapshotCommon.AllocationStackFrame>}
     */
    serializeAllocationStack: function(traceNodeId)
    {
        var node = this._idToTopDownNode[traceNodeId];
        var result = [];
        while (node) {
            var functionInfo = node.functionInfo;
            result.push(new WebInspector.HeapSnapshotCommon.AllocationStackFrame(
                functionInfo.functionName,
                functionInfo.scriptName,
                functionInfo.scriptId,
                functionInfo.line,
                functionInfo.column
            ));
            node = node.parent;
        }
        return result;
    },

    /**
     * @param {number} allocationNodeId
     * @return {!Array.<number>}
     */
    traceIds: function(allocationNodeId)
    {
        return this._ensureBottomUpNode(allocationNodeId).traceTopIds;
    },

    /**
     * @param {number} nodeId
     * @return {!WebInspector.BottomUpAllocationNode}
     */
    _ensureBottomUpNode: function(nodeId)
    {
        var node = this._idToNode[nodeId];
        if (!node) {
            var functionInfo = this._collapsedTopNodeIdToFunctionInfo[nodeId];
            node = functionInfo.bottomUpRoot();
            delete this._collapsedTopNodeIdToFunctionInfo[nodeId];
            this._idToNode[nodeId] = node;
        }
        return node;
    },

    /**
     * @param {!WebInspector.BottomUpAllocationNode} node
     * @return {!WebInspector.HeapSnapshotCommon.SerializedAllocationNode}
     */
    _serializeCaller: function(node)
    {
        var callerId = this._nextNodeId++;
        this._idToNode[callerId] = node;
        return this._serializeNode(
            callerId,
            node.functionInfo,
            node.allocationCount,
            node.allocationSize,
            node.liveCount,
            node.liveSize,
            node.hasCallers());
    },

    /**
     * @param {number} nodeId
     * @param {!WebInspector.FunctionAllocationInfo} functionInfo
     * @param {number} count
     * @param {number} size
     * @param {number} liveCount
     * @param {number} liveSize
     * @param {boolean} hasChildren
     * @return {!WebInspector.HeapSnapshotCommon.SerializedAllocationNode}
     */
    _serializeNode: function(nodeId, functionInfo, count, size, liveCount, liveSize, hasChildren)
    {
        return new WebInspector.HeapSnapshotCommon.SerializedAllocationNode(
            nodeId,
            functionInfo.functionName,
            functionInfo.scriptName,
            functionInfo.scriptId,
            functionInfo.line,
            functionInfo.column,
            count,
            size,
            liveCount,
            liveSize,
            hasChildren
        );
    }
}

/**
 * @constructor
 * @param {number} id
 * @param {!WebInspector.FunctionAllocationInfo} functionInfo
 * @param {number} count
 * @param {number} size
 * @param {number} liveCount
 * @param {number} liveSize
 * @param {?WebInspector.TopDownAllocationNode} parent
 */
WebInspector.TopDownAllocationNode = function(id, functionInfo, count, size, liveCount, liveSize, parent)
{
    this.id = id;
    this.functionInfo = functionInfo;
    this.allocationCount = count;
    this.allocationSize = size;
    this.liveCount = liveCount;
    this.liveSize = liveSize;
    this.parent = parent;
    this.children = [];
}

/**
 * @constructor
 * @param {!WebInspector.FunctionAllocationInfo} functionInfo
 */
WebInspector.BottomUpAllocationNode = function(functionInfo)
{
    this.functionInfo = functionInfo;
    this.allocationCount = 0;
    this.allocationSize = 0;
    this.liveCount = 0;
    this.liveSize = 0;
    this.traceTopIds = [];
    this._callers = [];
}

WebInspector.BottomUpAllocationNode.prototype = {
    /**
     * @param {!WebInspector.TopDownAllocationNode} traceNode
     * @return {!WebInspector.BottomUpAllocationNode}
     */
    addCaller: function(traceNode)
    {
        var functionInfo = traceNode.functionInfo;
        var result;
        for (var i = 0; i < this._callers.length; i++) {
            var caller = this._callers[i];
            if (caller.functionInfo === functionInfo) {
                result = caller;
                break;
            }
        }
        if (!result) {
            result = new WebInspector.BottomUpAllocationNode(functionInfo);
            this._callers.push(result);
        }
        return result;
    },

    /**
     * @return {!Array.<!WebInspector.BottomUpAllocationNode>}
     */
    callers: function()
    {
        return this._callers;
    },

    /**
     * @return {boolean}
     */
    hasCallers: function()
    {
        return this._callers.length > 0;
    }
}

/**
 * @constructor
 * @param {string} functionName
 * @param {string} scriptName
 * @param {number} scriptId
 * @param {number} line
 * @param {number} column
 */
WebInspector.FunctionAllocationInfo = function(functionName, scriptName, scriptId, line, column)
{
    this.functionName = functionName;
    this.scriptName = scriptName;
    this.scriptId = scriptId;
    this.line = line;
    this.column = column;
    this.totalCount = 0;
    this.totalSize = 0;
    this.totalLiveCount = 0;
    this.totalLiveSize = 0;
    this._traceTops = [];
}

WebInspector.FunctionAllocationInfo.prototype = {
    /**
     * @param {!WebInspector.TopDownAllocationNode} node
     */
    addTraceTopNode: function(node)
    {
        if (node.allocationCount === 0)
            return;
        this._traceTops.push(node);
        this.totalCount += node.allocationCount;
        this.totalSize += node.allocationSize;
        this.totalLiveCount += node.liveCount;
        this.totalLiveSize += node.liveSize;
    },

    /**
     * @return {?WebInspector.BottomUpAllocationNode}
     */
    bottomUpRoot: function()
    {
        if (!this._traceTops.length)
            return null;
        if (!this._bottomUpTree)
            this._buildAllocationTraceTree();
        return this._bottomUpTree;
    },

    _buildAllocationTraceTree: function()
    {
        this._bottomUpTree = new WebInspector.BottomUpAllocationNode(this);

        for (var i = 0; i < this._traceTops.length; i++) {
            var node = this._traceTops[i];
            var bottomUpNode = this._bottomUpTree;
            var count = node.allocationCount;
            var size = node.allocationSize;
            var liveCount = node.liveCount;
            var liveSize = node.liveSize;
            var traceId = node.id;
            while (true) {
                bottomUpNode.allocationCount += count;
                bottomUpNode.allocationSize += size;
                bottomUpNode.liveCount += liveCount;
                bottomUpNode.liveSize += liveSize;
                bottomUpNode.traceTopIds.push(traceId);
                node = node.parent;
                if (node === null) {
                    break;
                }
                bottomUpNode = bottomUpNode.addCaller(node);
            }
        }
    }
}
<commit_msg>Make root node in allocation trace view non-expandable<commit_after>/*
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @constructor
 */
WebInspector.AllocationProfile = function(profile, liveObjectStats)
{
    this._strings = profile.strings;
    this._liveObjectStats = liveObjectStats;

    this._nextNodeId = 1;
    this._functionInfos = []
    this._idToNode = {};
    this._idToTopDownNode = {};
    this._collapsedTopNodeIdToFunctionInfo = {};

    this._traceTops = null;

    this._buildFunctionAllocationInfos(profile);
    this._traceTree = this._buildAllocationTree(profile, liveObjectStats);
}

WebInspector.AllocationProfile.prototype = {
    _buildFunctionAllocationInfos: function(profile)
    {
        var strings = this._strings;

        var functionInfoFields = profile.snapshot.meta.trace_function_info_fields;
        var functionIdOffset = functionInfoFields.indexOf("function_id");
        var functionNameOffset = functionInfoFields.indexOf("name");
        var scriptNameOffset = functionInfoFields.indexOf("script_name");
        var scriptIdOffset = functionInfoFields.indexOf("script_id");
        var lineOffset = functionInfoFields.indexOf("line");
        var columnOffset = functionInfoFields.indexOf("column");
        var functionInfoFieldCount = functionInfoFields.length;

        var rawInfos = profile.trace_function_infos;
        var infoLength = rawInfos.length;
        var functionInfos = this._functionInfos = new Array(infoLength / functionInfoFieldCount);
        var index = 0;
        for (var i = 0; i < infoLength; i += functionInfoFieldCount) {
            functionInfos[index++] = new WebInspector.FunctionAllocationInfo(
                strings[rawInfos[i + functionNameOffset]],
                strings[rawInfos[i + scriptNameOffset]],
                rawInfos[i + scriptIdOffset],
                rawInfos[i + lineOffset],
                rawInfos[i + columnOffset]);
        }
    },

    _buildAllocationTree: function(profile, liveObjectStats)
    {
        var traceTreeRaw = profile.trace_tree;
        var functionInfos = this._functionInfos;
        var idToTopDownNode = this._idToTopDownNode;

        var traceNodeFields = profile.snapshot.meta.trace_node_fields;
        var nodeIdOffset = traceNodeFields.indexOf("id");
        var functionInfoIndexOffset = traceNodeFields.indexOf("function_info_index");
        var allocationCountOffset = traceNodeFields.indexOf("count");
        var allocationSizeOffset = traceNodeFields.indexOf("size");
        var childrenOffset = traceNodeFields.indexOf("children");
        var nodeFieldCount = traceNodeFields.length;

        function traverseNode(rawNodeArray, nodeOffset, parent)
        {
            var functionInfo = functionInfos[rawNodeArray[nodeOffset + functionInfoIndexOffset]];
            var id = rawNodeArray[nodeOffset + nodeIdOffset];
            var stats = liveObjectStats[id];
            var liveCount = stats ? stats.count : 0;
            var liveSize = stats ? stats.size : 0;
            var result = new WebInspector.TopDownAllocationNode(
                id,
                functionInfo,
                rawNodeArray[nodeOffset + allocationCountOffset],
                rawNodeArray[nodeOffset + allocationSizeOffset],
                liveCount,
                liveSize,
                parent);
            idToTopDownNode[id] = result;
            functionInfo.addTraceTopNode(result);

            var rawChildren = rawNodeArray[nodeOffset + childrenOffset];
            for (var i = 0; i < rawChildren.length; i += nodeFieldCount) {
                result.children.push(traverseNode(rawChildren, i, result));
            }
            return result;
        }

        return traverseNode(traceTreeRaw, 0, null);
    },

    /**
     * @return {!Array.<!WebInspector.HeapSnapshotCommon.SerializedAllocationNode>}
     */
    serializeTraceTops: function()
    {
        if (this._traceTops)
            return this._traceTops;
        var result = this._traceTops = [];
        var functionInfos = this._functionInfos;
        for (var i = 0; i < functionInfos.length; i++) {
            var info = functionInfos[i];
            if (info.totalCount === 0)
                continue;
            var nodeId = this._nextNodeId++;
            var isRoot = i == 0;
            result.push(this._serializeNode(
                nodeId,
                info,
                info.totalCount,
                info.totalSize,
                info.totalLiveCount,
                info.totalLiveSize,
                !isRoot));
            this._collapsedTopNodeIdToFunctionInfo[nodeId] = info;
        }
        result.sort(function(a, b) {
            return b.size - a.size;
        });
        return result;
    },

    /**
     * @param {number} nodeId
     * @return {!WebInspector.HeapSnapshotCommon.AllocationNodeCallers}
     */
    serializeCallers: function(nodeId)
    {
        var node = this._ensureBottomUpNode(nodeId);
        var nodesWithSingleCaller = [];
        while (node.callers().length === 1) {
            node = node.callers()[0];
            nodesWithSingleCaller.push(this._serializeCaller(node));
        }

        var branchingCallers = [];
        var callers = node.callers();
        for (var i = 0; i < callers.length; i++) {
            branchingCallers.push(this._serializeCaller(callers[i]));
        }
        return new WebInspector.HeapSnapshotCommon.AllocationNodeCallers(nodesWithSingleCaller, branchingCallers);
    },

    /**
     * @param {number} traceNodeId
     * @return {!Array.<!WebInspector.HeapSnapshotCommon.AllocationStackFrame>}
     */
    serializeAllocationStack: function(traceNodeId)
    {
        var node = this._idToTopDownNode[traceNodeId];
        var result = [];
        while (node) {
            var functionInfo = node.functionInfo;
            result.push(new WebInspector.HeapSnapshotCommon.AllocationStackFrame(
                functionInfo.functionName,
                functionInfo.scriptName,
                functionInfo.scriptId,
                functionInfo.line,
                functionInfo.column
            ));
            node = node.parent;
        }
        return result;
    },

    /**
     * @param {number} allocationNodeId
     * @return {!Array.<number>}
     */
    traceIds: function(allocationNodeId)
    {
        return this._ensureBottomUpNode(allocationNodeId).traceTopIds;
    },

    /**
     * @param {number} nodeId
     * @return {!WebInspector.BottomUpAllocationNode}
     */
    _ensureBottomUpNode: function(nodeId)
    {
        var node = this._idToNode[nodeId];
        if (!node) {
            var functionInfo = this._collapsedTopNodeIdToFunctionInfo[nodeId];
            node = functionInfo.bottomUpRoot();
            delete this._collapsedTopNodeIdToFunctionInfo[nodeId];
            this._idToNode[nodeId] = node;
        }
        return node;
    },

    /**
     * @param {!WebInspector.BottomUpAllocationNode} node
     * @return {!WebInspector.HeapSnapshotCommon.SerializedAllocationNode}
     */
    _serializeCaller: function(node)
    {
        var callerId = this._nextNodeId++;
        this._idToNode[callerId] = node;
        return this._serializeNode(
            callerId,
            node.functionInfo,
            node.allocationCount,
            node.allocationSize,
            node.liveCount,
            node.liveSize,
            node.hasCallers());
    },

    /**
     * @param {number} nodeId
     * @param {!WebInspector.FunctionAllocationInfo} functionInfo
     * @param {number} count
     * @param {number} size
     * @param {number} liveCount
     * @param {number} liveSize
     * @param {boolean} hasChildren
     * @return {!WebInspector.HeapSnapshotCommon.SerializedAllocationNode}
     */
    _serializeNode: function(nodeId, functionInfo, count, size, liveCount, liveSize, hasChildren)
    {
        return new WebInspector.HeapSnapshotCommon.SerializedAllocationNode(
            nodeId,
            functionInfo.functionName,
            functionInfo.scriptName,
            functionInfo.scriptId,
            functionInfo.line,
            functionInfo.column,
            count,
            size,
            liveCount,
            liveSize,
            hasChildren
        );
    }
}

/**
 * @constructor
 * @param {number} id
 * @param {!WebInspector.FunctionAllocationInfo} functionInfo
 * @param {number} count
 * @param {number} size
 * @param {number} liveCount
 * @param {number} liveSize
 * @param {?WebInspector.TopDownAllocationNode} parent
 */
WebInspector.TopDownAllocationNode = function(id, functionInfo, count, size, liveCount, liveSize, parent)
{
    this.id = id;
    this.functionInfo = functionInfo;
    this.allocationCount = count;
    this.allocationSize = size;
    this.liveCount = liveCount;
    this.liveSize = liveSize;
    this.parent = parent;
    this.children = [];
}

/**
 * @constructor
 * @param {!WebInspector.FunctionAllocationInfo} functionInfo
 */
WebInspector.BottomUpAllocationNode = function(functionInfo)
{
    this.functionInfo = functionInfo;
    this.allocationCount = 0;
    this.allocationSize = 0;
    this.liveCount = 0;
    this.liveSize = 0;
    this.traceTopIds = [];
    this._callers = [];
}

WebInspector.BottomUpAllocationNode.prototype = {
    /**
     * @param {!WebInspector.TopDownAllocationNode} traceNode
     * @return {!WebInspector.BottomUpAllocationNode}
     */
    addCaller: function(traceNode)
    {
        var functionInfo = traceNode.functionInfo;
        var result;
        for (var i = 0; i < this._callers.length; i++) {
            var caller = this._callers[i];
            if (caller.functionInfo === functionInfo) {
                result = caller;
                break;
            }
        }
        if (!result) {
            result = new WebInspector.BottomUpAllocationNode(functionInfo);
            this._callers.push(result);
        }
        return result;
    },

    /**
     * @return {!Array.<!WebInspector.BottomUpAllocationNode>}
     */
    callers: function()
    {
        return this._callers;
    },

    /**
     * @return {boolean}
     */
    hasCallers: function()
    {
        return this._callers.length > 0;
    }
}

/**
 * @constructor
 * @param {string} functionName
 * @param {string} scriptName
 * @param {number} scriptId
 * @param {number} line
 * @param {number} column
 */
WebInspector.FunctionAllocationInfo = function(functionName, scriptName, scriptId, line, column)
{
    this.functionName = functionName;
    this.scriptName = scriptName;
    this.scriptId = scriptId;
    this.line = line;
    this.column = column;
    this.totalCount = 0;
    this.totalSize = 0;
    this.totalLiveCount = 0;
    this.totalLiveSize = 0;
    this._traceTops = [];
}

WebInspector.FunctionAllocationInfo.prototype = {
    /**
     * @param {!WebInspector.TopDownAllocationNode} node
     */
    addTraceTopNode: function(node)
    {
        if (node.allocationCount === 0)
            return;
        this._traceTops.push(node);
        this.totalCount += node.allocationCount;
        this.totalSize += node.allocationSize;
        this.totalLiveCount += node.liveCount;
        this.totalLiveSize += node.liveSize;
    },

    /**
     * @return {?WebInspector.BottomUpAllocationNode}
     */
    bottomUpRoot: function()
    {
        if (!this._traceTops.length)
            return null;
        if (!this._bottomUpTree)
            this._buildAllocationTraceTree();
        return this._bottomUpTree;
    },

    _buildAllocationTraceTree: function()
    {
        this._bottomUpTree = new WebInspector.BottomUpAllocationNode(this);

        for (var i = 0; i < this._traceTops.length; i++) {
            var node = this._traceTops[i];
            var bottomUpNode = this._bottomUpTree;
            var count = node.allocationCount;
            var size = node.allocationSize;
            var liveCount = node.liveCount;
            var liveSize = node.liveSize;
            var traceId = node.id;
            while (true) {
                bottomUpNode.allocationCount += count;
                bottomUpNode.allocationSize += size;
                bottomUpNode.liveCount += liveCount;
                bottomUpNode.liveSize += liveSize;
                bottomUpNode.traceTopIds.push(traceId);
                node = node.parent;
                if (node === null) {
                    break;
                }
                bottomUpNode = bottomUpNode.addCaller(node);
            }
        }
    }
}
<|endoftext|>


<commit_before>import PropTypes from 'prop-types';
import React, { Component } from 'react';
import classNames from 'classnames';

import PopupButton from '../popup/PopupButton';
import VolumeBar from '../volume-control/VolumeBar';

const propTypes = {
  player: PropTypes.object,
  actions: PropTypes.object,
  vertical: PropTypes.bool,
  className: PropTypes.string,
};

const defaultProps = {
  vertical: false,
};

class VolumeMenuButton extends Component {

  constructor(props, context) {
    super(props, context);

    this.state = {
      active: false,
    };

    this.handleClick = this.handleClick.bind(this);
    this.handleFocus = this.handleFocus.bind(this);
    this.handleBlur = this.handleBlur.bind(this);
  }

  handleClick() {
    const { player, actions } = this.props;
    actions.mute(!player.muted);
  }

  handleFocus() {
    this.setState({
      active: true,
    });
  }

  handleBlur() {
    this.setState({
      active: false,
    });
  }

  get volumeLevel() {
    const { player: { volume, muted } } = this.props;
    let level = 3;
    if (volume === 0 || muted) {
      level = 0;
    } else if (volume < 0.33) {
      level = 1;
    } else if (volume < 0.67) {
      level = 2;
    }
    return level;
  }

  render() {
    const { vertical, player, className } = this.props;
    const inline = !vertical;
    const level = this.volumeLevel;
    return (
      <PopupButton
        className={classNames(className, {
          'video-react-volume-menu-button-vertical': vertical,
          'video-react-volume-menu-button-horizontal': !vertical,
          'video-react-vol-muted': player.muted,
          'video-react-vol-0': level === 0 && !player.muted,
          'video-react-vol-1': level === 1,
          'video-react-vol-2': level === 2,
          'video-react-vol-3': level === 3,
          'video-react-slider-active': this.state.active,
          'video-react-lock-showing': this.state.active,
        }, 'video-react-volume-menu-button')}
        onClick={this.handleClick}
        inline={inline}
      >
        <VolumeBar
          onFocus={this.handleFocus}
          onBlur={this.handleBlur}
          {...this.props}
        />
      </PopupButton>
    );
  }
}

VolumeMenuButton.propTypes = propTypes;
VolumeMenuButton.defaultProps = defaultProps;
export default VolumeMenuButton;
<commit_msg>Add option to always show volume control<commit_after>import PropTypes from 'prop-types';
import React, { Component } from 'react';
import classNames from 'classnames';

import PopupButton from '../popup/PopupButton';
import VolumeBar from '../volume-control/VolumeBar';

const propTypes = {
  player: PropTypes.object,
  actions: PropTypes.object,
  vertical: PropTypes.bool,
  className: PropTypes.string,
  alwaysShowVolume: PropTypes.bool,
};

const defaultProps = {
  vertical: false,
};

class VolumeMenuButton extends Component {

  constructor(props, context) {
    super(props, context);

    this.state = {
      active: false,
    };

    this.handleClick = this.handleClick.bind(this);
    this.handleFocus = this.handleFocus.bind(this);
    this.handleBlur = this.handleBlur.bind(this);
  }

  handleClick() {
    const { player, actions } = this.props;
    actions.mute(!player.muted);
  }

  handleFocus() {
    this.setState({
      active: true,
    });
  }

  handleBlur() {
    this.setState({
      active: false,
    });
  }

  get volumeLevel() {
    const { player: { volume, muted } } = this.props;
    let level = 3;
    if (volume === 0 || muted) {
      level = 0;
    } else if (volume < 0.33) {
      level = 1;
    } else if (volume < 0.67) {
      level = 2;
    }
    return level;
  }

  render() {
    const { vertical, player, className } = this.props;
    const inline = !vertical;
    const level = this.volumeLevel;
    return (
      <PopupButton
        className={classNames(className, {
          'video-react-volume-menu-button-vertical': vertical,
          'video-react-volume-menu-button-horizontal': !vertical,
          'video-react-vol-muted': player.muted,
          'video-react-vol-0': level === 0 && !player.muted,
          'video-react-vol-1': level === 1,
          'video-react-vol-2': level === 2,
          'video-react-vol-3': level === 3,
          'video-react-slider-active': this.props.alwaysShowVolume || this.state.active,
          'video-react-lock-showing': this.props.alwaysShowVolume || this.state.active,
        }, 'video-react-volume-menu-button')}
        onClick={this.handleClick}
        inline={inline}
      >
        <VolumeBar
          onFocus={this.handleFocus}
          onBlur={this.handleBlur}
          {...this.props}
        />
      </PopupButton>
    );
  }
}

VolumeMenuButton.propTypes = propTypes;
VolumeMenuButton.defaultProps = defaultProps;
export default VolumeMenuButton;
<|endoftext|>


<commit_before>var app = angular.module("ive");

/**
 * Main Controller
 */
app.controller("mainController", function($scope, $socket, $timeout) {

    $scope.submitAlertMessage = false;

    // Init
    $scope.feedback = {
        rating: null,
        comment: ""
    };

    $socket.on('/set/video', function(data){
        console.log( data.video_id);
    });

    $scope.reset = function(){
        // Send socket message comment
        $socket.emit('/reset/feedback', null);
    };

    /**
     * [send feedback]
     */
    $scope.send = function(){

        var localDate = new Date();
        var options = {
            weekday: "short", month: "short",
            day: "numeric", hour: "2-digit", minute: "2-digit"
        };

        if ($scope.feedback.comment !== "" && $scope.feedback.rating === null){

            // Send socket message comment
            $socket.emit('/post/feedback', {
                comment: "On " + localDate.toLocaleTimeString("en-DE", options) + ", citizen wrote: " + ' "' + $scope.feedback.comment + '"'
             });
            $("#feedbackSubmitBtn").slideUp("slow");
        }else { if ( $scope.feedback.rating === "Like" || $scope.feedback.rating === "Dislike" ) {

            // Send socket message rating
            $socket.emit('/post/feedback', {
                rating: $scope.feedback.rating
            });
            $("#feedbackSubmitBtn").slideUp("slow");
        } else {console.log("no socket message")}
        }

        //hide text area after send comment
        if ($scope.feedback.comment !== "" && $scope.feedback.rating === null){
            $scope.showMeFlipTextarea = true;

        }else { if ( $scope.feedback.rating === "Like" || $scope.feedback.rating === "Dislike" ) {

                    $scope.showMeFlipRating = true;
                } else {console.log("if error")}
        }

        if( $scope.showMeFlipTextarea === true && $scope.showMeFlipRating === true){
            $("#feedbackSubmitBtn").slideUp("slow");
        }

        // submit alert for 2sec
        $scope.submitAlertMessage = true;
        $timeout(function() {
            $scope.submitAlertMessage = false;
        }, 2000);

    };

        // show text area and hide ratingArea
        $("#flipTextarea").click(function() {
            $("#comment").slideDown("slow");
            $("#ratingArea").slideUp("slow");
            $("#feedbackSubmitBtn").slideDown("slow");
            //reset rating
            $scope.feedback = {rating : null};

        });

        // show rating area and hide text area
        $("#flipRating").click(function() {
            $("#ratingArea").slideDown("slow");
            $("#comment").slideUp("slow");
            $("#feedbackSubmitBtn").slideDown("slow");
            //reset comment
            $scope.feedback = {comment : ""};

        });

});
<commit_msg>#new add time function<commit_after>var app = angular.module("ive");

/**
 * Main Controller
 */
app.controller("mainController", function($scope, $socket, $timeout) {

    // save time when feedback page is loaded
    $scope.startDate = new Date();
    $scope.submitAlertMessage = false;

    // Init
    $scope.feedback = {
        rating: null,
        comment: ""
    };

    $scope.reset = function(){
        // Send socket message comment
        $socket.emit('/reset/feedback', null);
    };

    /**
     * [send feedback]
     */
    $scope.send = function(){

        $scope.data.disabled = false;

        var localDate = new Date();
        // time settings
        var options = {
            weekday: "short", month: "short",
            day: "numeric", hour: "2-digit", minute: "2-digit"
        };
        // how long does it take until submit the comment @return time in milliseconds
        var timeUntilSubmitComment = localDate - $scope.startDate;

        if ($scope.feedback.comment !== "" && $scope.feedback.rating === null){

            // Send socket message comment
            $socket.emit('/post/feedback', {
                comment: "participant rated: " + $scope.participantRating + " start: " + $scope.startDate + " end: " + localDate + " time difference: " + timeUntilSubmitComment + " milliseconds" + " #splitHere# " + "On " + localDate.toLocaleTimeString("en-DE", options) + ", citizen wrote: " + ' "' + $scope.feedback.comment + '"'
             });
            $("#feedbackSubmitBtn").slideUp("slow");
        }else { if ( $scope.feedback.rating === "Like" || $scope.feedback.rating === "Dislike" ) {

            $scope.participantRating = $scope.feedback.rating;

            // Send socket message rating
            $socket.emit('/post/feedback', {
                rating: $scope.feedback.rating
            });
            $("#feedbackSubmitBtn").slideUp("slow");
        } else {console.log("no socket message")}
        }

        //hide text area after send comment
        if ($scope.feedback.comment !== "" && $scope.feedback.rating === null){
            $scope.showMeFlipTextarea = true;

        }else { if ( $scope.feedback.rating === "Like" || $scope.feedback.rating === "Dislike" ) {

                    $scope.showMeFlipRating = true;
                } else {console.log("if error")}
        }

        if( $scope.showMeFlipTextarea === true && $scope.showMeFlipRating === true){
            $("#feedbackSubmitBtn").slideUp("slow");
        }

        // submit alert for 2sec
        $scope.submitAlertMessage = true;
        $timeout(function() {
            $scope.submitAlertMessage = false;
        }, 2000);

    };

        // show text area and hide ratingArea
        $("#flipTextarea").click(function() {
            $("#comment").slideDown("slow");
            $("#ratingArea").slideUp("slow");
            $("#feedbackSubmitBtn").slideDown("slow");
            //reset rating
            $scope.feedback = {rating : null};

        });

        // show rating area and hide text area
        $("#flipRating").click(function() {
            $("#ratingArea").slideDown("slow");
            $("#comment").slideUp("slow");
            $("#feedbackSubmitBtn").slideDown("slow");
            //reset comment
            $scope.feedback = {comment : ""};

        });

});
<|endoftext|>


<commit_before>import React from 'react'
import { Route, Router, Switch } from 'react-router-dom'
import { filter } from 'lodash/collection'
import { get } from 'lodash/object'
import { Helmet } from 'react-helmet'
import { browserHistory } from 'js/navigation/navigation'
import BaseContainer from 'js/components/General/BaseContainer'
import ErrorBoundary from 'js/components/General/ErrorBoundary'
import { initializeFirebase } from 'js/authentication/firebaseConfig'
import logger from 'js/utils/logger'

// This is a hack to generate separate apps for the new tab
// page and search. We do this because create-react-app does
// not currently support more than one entry point. See:
// https://github.com/facebook/create-react-app/issues/1084#issuecomment-365495580
// Our goal is to use load only the necessary assets for the
// root new tab and search pages without downloading any
// critical JS asynchronously, while not switching away from
// CRA, ejecting from CRA, or dealing with the overhead of
// managing distinct codebases. In the future, it would be
// better for us to have a monorepo structure of some kind
// (see: https://github.com/facebook/create-react-app/issues/1492),
// use the built-in multiple entry points (if CRA supports
// it down the line), or switching to another framework.
// See this pull request for details:
// https://github.com/gladly-team/tab/pull/466
var TheApp
var appPath
if (process.env.REACT_APP_WHICH_APP === 'newtab') {
  TheApp = require('js/components/App/App').default
  appPath = '/newtab/'
} else if (process.env.REACT_APP_WHICH_APP === 'search') {
  TheApp = require('js/components/Search/SearchApp').default
  appPath = '/search/'
} else {
  throw new Error(
    `Env var "REACT_APP_WHICH_APP" should be set to "newtab" or "search". Received: "${
      process.env.REACT_APP_WHICH_APP
    }"`
  )
}

class Root extends React.Component {
  constructor(props) {
    super(props)

    // Initialize Firebase.
    try {
      initializeFirebase()
    } catch (e) {
      logger.error(e)
    }
  }

  componentDidMount() {
    // Measure time to interactive (TTI):
    // https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#time_to_interactive
    // https://github.com/GoogleChromeLabs/tti-polyfill
    try {
      if (process.env.REACT_APP_MEASURE_TIME_TO_INTERACTIVE === 'true') {
        import('tti-polyfill').then(ttiPolyfill => {
          ttiPolyfill.getFirstConsistentlyInteractive().then(tti => {
            console.log(`Time to interactive: ${tti}`)
          })
        })
      }
    } catch (e) {
      console.error(e)
    }
  }

  render() {
    // TODO: Show 404 page
    return (
      <ErrorBoundary>
        <BaseContainer>
          <Helmet
            // Handle a react-helmet bug that doesn't replace or remove
            // existing favicon <link /> elements when a new favicon is set.
            // https://github.com/nfl/react-helmet/issues/430
            // If we adde a new favicon link element, remove all other favicon
            // link elements and re-add the new favicon link element.
            onChangeClientState={(newState, addedTags) => {
              // TODO: add tests
              try {
                // Check if we added any new link[rel="icon"] elements.
                const newFaviconElems = filter(get(addedTags, 'linkTags', []), {
                  rel: 'icon',
                })
                if (!newFaviconElems.length) {
                  return
                }

                // Get the href of the last link element we just added, which
                // we assume is the most recently-added favicon.
                const newFaviconHref =
                  newFaviconElems[newFaviconElems.length - 1].href

                // Remove all react-helmet link elements with rel="icon" that
                // do not have the href of our recently-added favicon.
                // If no other favicon elements exist, we don't have to do
                // anything.
                const existingFavicons = document.querySelectorAll(
                  `link[rel="icon"][data-react-helmet]:not([href="${newFaviconHref}"])`
                )
                if (!existingFavicons.length) {
                  return
                }
                existingFavicons.forEach(e => e.parentNode.removeChild(e))

                // Remove and re-add the latest link element to make sure
                // the browser uses it.
                const newFaviconElem = document.querySelector(
                  `link[rel="icon"][data-react-helmet][href="${newFaviconHref}"]`
                )
                if (newFaviconElem) {
                  const parentElem = newFaviconElem.parentNode
                  parentElem.removeChild(newFaviconElem)
                  parentElem.appendChild(newFaviconElem)
                }
              } catch (e) {
                console.error(e)
              }
            }}
          />
          <Router history={browserHistory}>
            <Switch>
              <Route path={appPath} component={TheApp} />
            </Switch>
          </Router>
        </BaseContainer>
      </ErrorBoundary>
    )
  }
}

export default Root
<commit_msg>Fix typo<commit_after>import React from 'react'
import { Route, Router, Switch } from 'react-router-dom'
import { filter } from 'lodash/collection'
import { get } from 'lodash/object'
import { Helmet } from 'react-helmet'
import { browserHistory } from 'js/navigation/navigation'
import BaseContainer from 'js/components/General/BaseContainer'
import ErrorBoundary from 'js/components/General/ErrorBoundary'
import { initializeFirebase } from 'js/authentication/firebaseConfig'
import logger from 'js/utils/logger'

// This is a hack to generate separate apps for the new tab
// page and search. We do this because create-react-app does
// not currently support more than one entry point. See:
// https://github.com/facebook/create-react-app/issues/1084#issuecomment-365495580
// Our goal is to use load only the necessary assets for the
// root new tab and search pages without downloading any
// critical JS asynchronously, while not switching away from
// CRA, ejecting from CRA, or dealing with the overhead of
// managing distinct codebases. In the future, it would be
// better for us to have a monorepo structure of some kind
// (see: https://github.com/facebook/create-react-app/issues/1492),
// use the built-in multiple entry points (if CRA supports
// it down the line), or switching to another framework.
// See this pull request for details:
// https://github.com/gladly-team/tab/pull/466
var TheApp
var appPath
if (process.env.REACT_APP_WHICH_APP === 'newtab') {
  TheApp = require('js/components/App/App').default
  appPath = '/newtab/'
} else if (process.env.REACT_APP_WHICH_APP === 'search') {
  TheApp = require('js/components/Search/SearchApp').default
  appPath = '/search/'
} else {
  throw new Error(
    `Env var "REACT_APP_WHICH_APP" should be set to "newtab" or "search". Received: "${
      process.env.REACT_APP_WHICH_APP
    }"`
  )
}

class Root extends React.Component {
  constructor(props) {
    super(props)

    // Initialize Firebase.
    try {
      initializeFirebase()
    } catch (e) {
      logger.error(e)
    }
  }

  componentDidMount() {
    // Measure time to interactive (TTI):
    // https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#time_to_interactive
    // https://github.com/GoogleChromeLabs/tti-polyfill
    try {
      if (process.env.REACT_APP_MEASURE_TIME_TO_INTERACTIVE === 'true') {
        import('tti-polyfill').then(ttiPolyfill => {
          ttiPolyfill.getFirstConsistentlyInteractive().then(tti => {
            console.log(`Time to interactive: ${tti}`)
          })
        })
      }
    } catch (e) {
      console.error(e)
    }
  }

  render() {
    // TODO: Show 404 page
    return (
      <ErrorBoundary>
        <BaseContainer>
          <Helmet
            // Handle a react-helmet bug that doesn't replace or remove
            // existing favicon <link /> elements when a new favicon is set.
            // https://github.com/nfl/react-helmet/issues/430
            // If we add a new favicon link element, remove all other favicon
            // link elements and re-add the new favicon link element.
            onChangeClientState={(newState, addedTags) => {
              // TODO: add tests
              try {
                // Check if we added any new link[rel="icon"] elements.
                const newFaviconElems = filter(get(addedTags, 'linkTags', []), {
                  rel: 'icon',
                })
                if (!newFaviconElems.length) {
                  return
                }

                // Get the href of the last link element we just added, which
                // we assume is the most recently-added favicon.
                const newFaviconHref =
                  newFaviconElems[newFaviconElems.length - 1].href

                // Remove all react-helmet link elements with rel="icon" that
                // do not have the href of our recently-added favicon.
                // If no other favicon elements exist, we don't have to do
                // anything.
                const existingFavicons = document.querySelectorAll(
                  `link[rel="icon"][data-react-helmet]:not([href="${newFaviconHref}"])`
                )
                if (!existingFavicons.length) {
                  return
                }
                existingFavicons.forEach(e => e.parentNode.removeChild(e))

                // Remove and re-add the latest link element to make sure
                // the browser uses it.
                const newFaviconElem = document.querySelector(
                  `link[rel="icon"][data-react-helmet][href="${newFaviconHref}"]`
                )
                if (newFaviconElem) {
                  const parentElem = newFaviconElem.parentNode
                  parentElem.removeChild(newFaviconElem)
                  parentElem.appendChild(newFaviconElem)
                }
              } catch (e) {
                console.error(e)
              }
            }}
          />
          <Router history={browserHistory}>
            <Switch>
              <Route path={appPath} component={TheApp} />
            </Switch>
          </Router>
        </BaseContainer>
      </ErrorBoundary>
    )
  }
}

export default Root
<|endoftext|>


<commit_before>function describePlural(value, unit) {
    return value + " " + unit + (value == 1 ? "" : "s")
}
function describetime(now, other) {
    var seconds = now - other
    if (isNaN(seconds)) return ""
    var timeString
    if (seconds < 0)
        return "now"
    else if (seconds < 10)
        return "a few seconds ago"
    else if (seconds < 60)
        return " " + describePlural(Math.floor(seconds), "second") + " ago"
    else if (seconds < 2 * 60)
        return "a minute ago"
    else if (seconds < 60 * 60)
        return " " + describePlural(Math.floor(seconds / 60), "minute") + " ago"
    else if (seconds < 2 * 60 * 60)
        return "an hour ago";
    else if (seconds < 60 * 60 * 24)
        return " " + describePlural(Math.floor(seconds / 60 / 60), "hour") + " ago"
    else if (seconds < 60 * 60 * 24 * 30)
        return " " + describePlural(Math.floor(seconds / 60 / 60 / 24), "day") + " ago"
    else if (seconds < 60 * 60 * 24 * 365)
        return " " + describePlural(Math.floor(seconds / 60 / 60 / 24 / 30), "month") + " ago"
    else
        return " " + describePlural(Math.floor(seconds / 60 / 60 / 24 / 365), "year") + " ago"
}

function isIE() {
    return /trident/i.test(navigator.userAgent);
}

function dirAuto($el) {
    if ($el) {
        if (!isIE())
            $el.attr('dir', 'auto');
        else {
            var dir = /^[\s\.;:(+0-9]*[\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]/i.test($el.text()) ? "rtl" : "ltr";
            $el.attr('dir', dir);
        }
    }
    return $el;
}

function searchSubmit(form) {
    if (pxt && pxt.tickEvent) pxt.tickEvent("docs.search", {'source': form.id})
}

function setupSidebar() {
    $('.ui.sidebar')
        .sidebar({ dimPage: false })
        .sidebar(
        'attach events', '#togglesidebar'
        );

    $('.ui.dropdown')
        .dropdown();

    $('.ui.accordion')
        .accordion({
            closeNested: true,
            selector: {
                trigger: '.title .icon'
            }
        });
}

function setupSemantic() {
    // don't show related videos
    $.fn.embed.settings.sources.youtube.url = '//www.youtube.com/embed/{id}?rel=0'

    //This is an adapted version of the original template code in Semantic UI
    $.fn.embed.settings.templates.placeholder = function (image, icon) {
        var html = '';
        if (icon) {
            html += '';
        }
        if (image) {
            //Remove the timestamp from the YouTube source URL
            image = image.replace(/\#t=([0-9]+m)?([0-9]+s)?/, "");
            html += '';
        }
        return html;
    };
    //Again, this is a slightly modified version of the original Semantic UI source to support timestamped YouTube videos
    $.fn.embed.settings.templates.iframe = function (url, parameters) {
        var src = url;
        //The following if statement is all that is different from the original implementation
        var matches = src.match(/\#t=(([0-9]+)m)?(([0-9]+)s)?/);
        if (matches) {
            var minutes = matches[2] != undefined ? parseInt(matches[2]) : 0;
            var seconds = matches[4] != undefined ? parseInt(matches[4]) : 0;
            var param = "start=" + (minutes * 60 + seconds).toString();
            if (parameters) {
                parameters = param + "&" + parameters;
            }
            else {
                parameters = param;
            }
            src = src.replace(/\#t=([0-9]+m)?([0-9]+s)?/, "");
        }
        if (parameters) {
            src += (/\?/.test(url) ? '&' : '?') + parameters;
        }
        return ''
            + ''
            ;
    };

    $('.ui.embed').embed();

    $('.md-video-link').on("click", function () {
        var name = $(this).data("playerurl") || $(this).data("videosrc");
        $(this).find("img").remove();
        $(this).find("svg").remove();
        var outer = $('
', {
            "class": 'embed-responsive embed-responsive-16by9'
        });
        outer.appendTo($(this));
        $('', {
            class: 'embed-responsive-item',
            src: name,
            frameborder: 0,
            scrolling: 'no'
        }).appendTo(outer);
    });
}

function renderSnippets() {
    var codeElems = $('code')
    for (var i = 0; i < codeElems.length; i++) {
        codeElems[i].className = codeElems[i].className.replace('-ignore', '')
    }

    var downloadScreenshots = /screenshots=1/i.test(window.location.href);
    var path = window.location.href.split('/').pop().split(/[?#]/)[0];
    ksRunnerReady(function () {
        setupSidebar();
        setupSemantic();
        pxt.runner.renderAsync({
            snippetClass: 'lang-blocks',
            signatureClass: 'lang-sig',
            blocksClass: 'lang-block',
            shuffleClass: 'lang-shuffle',
            simulatorClass: 'lang-sim',
            linksClass: 'lang-cards',
            namespacesClass: 'lang-namespaces',
            codeCardClass: 'lang-codecard',
            packageClass: 'lang-package',
            projectClass: 'lang-project',
            snippetReplaceParent: true,
            simulator: true,
            hex: true,
            hexName: path,
            downloadScreenshots: downloadScreenshots
        }).done();
    });
}

$(document).ready(function () {
    renderSnippets();
});
<commit_msg>display user agent in /browsers page<commit_after>function isIE() {
    return /trident/i.test(navigator.userAgent);
}

function dirAuto($el) {
    if ($el) {
        if (!isIE())
            $el.attr('dir', 'auto');
        else {
            var dir = /^[\s\.;:(+0-9]*[\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]/i.test($el.text()) ? "rtl" : "ltr";
            $el.attr('dir', dir);
        }
    }
    return $el;
}

function searchSubmit(form) {
    if (pxt && pxt.tickEvent) pxt.tickEvent("docs.search", {'source': form.id})
}

function setupSidebar() {
    $('.ui.sidebar')
        .sidebar({ dimPage: false })
        .sidebar(
        'attach events', '#togglesidebar'
        );

    $('.ui.dropdown')
        .dropdown();

    $('.ui.accordion')
        .accordion({
            closeNested: true,
            selector: {
                trigger: '.title .icon'
            }
        });
}

function setupSemantic() {
    // don't show related videos
    $.fn.embed.settings.sources.youtube.url = '//www.youtube.com/embed/{id}?rel=0'

    //This is an adapted version of the original template code in Semantic UI
    $.fn.embed.settings.templates.placeholder = function (image, icon) {
        var html = '';
        if (icon) {
            html += '';
        }
        if (image) {
            //Remove the timestamp from the YouTube source URL
            image = image.replace(/\#t=([0-9]+m)?([0-9]+s)?/, "");
            html += '';
        }
        return html;
    };
    //Again, this is a slightly modified version of the original Semantic UI source to support timestamped YouTube videos
    $.fn.embed.settings.templates.iframe = function (url, parameters) {
        var src = url;
        //The following if statement is all that is different from the original implementation
        var matches = src.match(/\#t=(([0-9]+)m)?(([0-9]+)s)?/);
        if (matches) {
            var minutes = matches[2] != undefined ? parseInt(matches[2]) : 0;
            var seconds = matches[4] != undefined ? parseInt(matches[4]) : 0;
            var param = "start=" + (minutes * 60 + seconds).toString();
            if (parameters) {
                parameters = param + "&" + parameters;
            }
            else {
                parameters = param;
            }
            src = src.replace(/\#t=([0-9]+m)?([0-9]+s)?/, "");
        }
        if (parameters) {
            src += (/\?/.test(url) ? '&' : '?') + parameters;
        }
        return ''
            + ''
            ;
    };

    $('.ui.embed').embed();

    $('.md-video-link').on("click", function () {
        var name = $(this).data("playerurl") || $(this).data("videosrc");
        $(this).find("img").remove();
        $(this).find("svg").remove();
        var outer = $('
', {
            "class": 'embed-responsive embed-responsive-16by9'
        });
        outer.appendTo($(this));
        $('', {
            class: 'embed-responsive-item',
            src: name,
            frameborder: 0,
            scrolling: 'no'
        }).appendTo(outer);
    });

    if (/browsers$/i.test(window.location.href))
        $('.ui.footer').append($('
').text('user agent: ' + navigator.userAgent))
}

function renderSnippets() {
    var codeElems = $('code')
    for (var i = 0; i < codeElems.length; i++) {
        codeElems[i].className = codeElems[i].className.replace('-ignore', '')
    }

    var downloadScreenshots = /screenshots=1/i.test(window.location.href);
    var path = window.location.href.split('/').pop().split(/[?#]/)[0];
    ksRunnerReady(function () {
        setupSidebar();
        setupSemantic();
        pxt.runner.renderAsync({
            snippetClass: 'lang-blocks',
            signatureClass: 'lang-sig',
            blocksClass: 'lang-block',
            shuffleClass: 'lang-shuffle',
            simulatorClass: 'lang-sim',
            linksClass: 'lang-cards',
            namespacesClass: 'lang-namespaces',
            codeCardClass: 'lang-codecard',
            packageClass: 'lang-package',
            projectClass: 'lang-project',
            snippetReplaceParent: true,
            simulator: true,
            hex: true,
            hexName: path,
            downloadScreenshots: downloadScreenshots
        }).done();
    });
}

$(document).ready(function () {
    renderSnippets();
});
<|endoftext|>


<commit_before>// ** I18N

// Calendar pt_BR language
// Author: Adalberto Machado, <betosm@terra.com.br>
// Encoding: any
// Distributed under the same terms as the calendar itself.

// For translators: please use UTF-8 if possible.  We strongly believe that
// Unicode is the answer to a real internationalized world.  Also please
// include your contact information in the header, as can be seen above.

// full day names
Calendar._DN = new Array
("Domingo",
 "Segunda",
 "Terca",
 "Quarta",
 "Quinta",
 "Sexta",
 "Sabado",
 "Domingo");

// Please note that the following array of short day names (and the same goes
// for short month names, _SMN) isn't absolutely necessary.  We give it here
// for exemplification on how one can customize the short day names, but if
// they are simply the first N letters of the full name you can simply say:
//
//   Calendar._SDN_len = N; // short day name length
//   Calendar._SMN_len = N; // short month name length
//
// If N = 3 then this is not needed either since we assume a value of 3 if not
// present, to be compatible with translation files that were written before
// this feature.

// short day names
Calendar._SDN = new Array
("Dom",
 "Seg",
 "Ter",
 "Qua",
 "Qui",
 "Sex",
 "Sab",
 "Dom");

// full month names
Calendar._MN = new Array
("Janeiro",
 "Fevereiro",
 "Marco",
 "Abril",
 "Maio",
 "Junho",
 "Julho",
 "Agosto",
 "Setembro",
 "Outubro",
 "Novembro",
 "Dezembro");

// short month names
Calendar._SMN = new Array
("Jan",
 "Fev",
 "Mar",
 "Abr",
 "Mai",
 "Jun",
 "Jul",
 "Ago",
 "Set",
 "Out",
 "Nov",
 "Dez");

// tooltips
Calendar._TT = {};
Calendar._TT["INFO"] = "Sobre o calendario";

Calendar._TT["ABOUT"] =
"DHTML Date/Time Selector\n" +
"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
"Ultima versao visite: http://www.dynarch.com/projects/calendar/\n" +
"Distribuido sobre GNU LGPL.  Veja http://gnu.org/licenses/lgpl.html para detalhes." +
"\n\n" +
"Selecao de data:\n" +
"- Use os botoes \xab, \xbb para selecionar o ano\n" +
"- Use os botoes " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " para selecionar o mes\n" +
"- Segure o botao do mouse em qualquer um desses botoes para selecao rapida.";
Calendar._TT["ABOUT_TIME"] = "\n\n" +
"Selecao de hora:\n" +
"- Clique em qualquer parte da hora para incrementar\n" +
"- ou Shift-click para decrementar\n" +
"- ou clique e segure para selecao rapida.";

Calendar._TT["PREV_YEAR"] = "Ant. ano (segure para menu)";
Calendar._TT["PREV_MONTH"] = "Ant. mes (segure para menu)";
Calendar._TT["GO_TODAY"] = "Hoje";
Calendar._TT["NEXT_MONTH"] = "Prox. mes (segure para menu)";
Calendar._TT["NEXT_YEAR"] = "Prox. ano (segure para menu)";
Calendar._TT["SEL_DATE"] = "Selecione a data";
Calendar._TT["DRAG_TO_MOVE"] = "Arraste para mover";
Calendar._TT["PART_TODAY"] = " (hoje)";

// the following is to inform that "%s" is to be the first day of week
// %s will be replaced with the day name.
Calendar._TT["DAY_FIRST"] = "Mostre %s primeiro";

// This may be locale-dependent.  It specifies the week-end days, as an array
// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1
// means Monday, etc.
Calendar._TT["WEEKEND"] = "0,6";

Calendar._TT["CLOSE"] = "Fechar";
Calendar._TT["TODAY"] = "Hoje";
Calendar._TT["TIME_PART"] = "(Shift-)Click ou arraste para mudar valor";

// date formats
Calendar._TT["DEF_DATE_FORMAT"] = "%d/%m/%Y";
Calendar._TT["TT_DATE_FORMAT"] = "%a, %e %b";

Calendar._TT["WK"] = "sm";
Calendar._TT["TIME"] = "Hora:";
<commit_msg>Delete calendar-pt.js<commit_after><|endoftext|>


<commit_before>'use strict';

module.exports = {
  client: {
    lib: {
      css: [
        'public/lib/bootstrap/dist/css/bootstrap.css',
        'public/lib/bootstrap/dist/css/bootstrap-theme.css',
        'public/lib/bootstrap-additions/dist/bootstrap-additions.css',
        'public/lib/components-font-awesome/css/font-awesome.css',
        'public/lib/angular-ui-switch/angular-ui-switch.css',
        'public/lib/ng-tags-input/ng-tags-input.css',
        'public/lib/angular-moment-picker/dist/angular-moment-picker.css'
      ],
      js: [
        'public/lib/angular/angular.js',
        'public/lib/angular-resource/angular-resource.js',
        'public/lib/angular-animate/angular-animate.js',
        'public/lib/angular-messages/angular-messages.js',
        'public/lib/angular-ui-router/release/angular-ui-router.js',
        'public/lib/angular-ui-utils/ui-utils.js',
        'public/lib/angular-bootstrap/ui-bootstrap-tpls.js',
        'public/lib/angular-file-upload/angular-file-upload.js',
        'public/lib/angular-strap/dist/angular-strap.js',
        'public/lib/angular-strap/dist/angular-strap.tpl.js',
        'public/lib/owasp-password-strength-test/owasp-password-strength-test.js',
        'public/lib/angular-ui-switch/angular-ui-switch.js',
        'public/lib/ng-tags-input/ng-tags-input.js',
        'public/lib/underscore/underscore.js',
        'public/lib/moment/moment.js',
        'public/lib/angular-moment-picker/dist/angular-moment-picker.js'
      ],
      tests: ['public/lib/angular-mocks/angular-mocks.js']
    },
    css: [
      'modules/*/client/css/*.css'
    ],
    less: [
      'modules/*/client/less/*.less'
    ],
    sass: [
      'modules/*/client/scss/*.scss'
    ],
    js: [
      'modules/core/client/app/config.js',
      'modules/core/client/app/init.js',
      'modules/*/client/*.js',
      'modules/*/client/**/*.js',
      'modules/*/client/**/**/*.js',
    ],
    views: ['modules/*/client/views/**/*.html'],
    templates: ['build/templates.js']
  },
  server: {
    gruntConfig: 'gruntfile.js',
    gulpConfig: 'gulpfile.js',
    allJS: ['server.js', 'config/**/*.js', 'modules/*/server/**/*.js'],
    models: 'modules/*/server/models/**/*.js',
    routes: ['modules/!(core)/server/routes/**/*.js', 'modules/core/server/routes/**/*.js'],
    sockets: 'modules/*/server/sockets/**/*.js',
    config: 'modules/*/server/config/*.js',
    policies: 'modules/*/server/policies/*.js',
    views: 'modules/*/server/views/*.html'
  }
};
<commit_msg>Commited from lenh at 2017年 6月 19日 月曜日 16:45:53<commit_after>'use strict';

module.exports = {
  client: {
    lib: {
      css: [
        'public/lib/bootstrap/dist/css/bootstrap.css',
        'public/lib/bootstrap/dist/css/bootstrap-theme.css',
        'public/lib/bootstrap-additions/dist/bootstrap-additions.css',
        'public/lib/components-font-awesome/css/font-awesome.css',
        'public/lib/angular-ui-switch/angular-ui-switch.css',
        'public/lib/ng-tags-input/ng-tags-input.css',
        'public/lib/angular-moment-picker/dist/angular-moment-picker.css'
      ],
      js: [
        'public/lib/angular/angular.js',
        'public/lib/angular-resource/angular-resource.js',
        'public/lib/angular-animate/angular-animate.js',
        'public/lib/angular-messages/angular-messages.js',
        'public/lib/angular-ui-router/release/angular-ui-router.js',
        'public/lib/angular-ui-utils/ui-utils.js',
        // 'public/lib/angular-bootstrap/ui-bootstrap-tpls.js',
        'public/lib/angular-file-upload/angular-file-upload.js',
        'public/lib/angular-strap/dist/angular-strap.js',
        'public/lib/angular-strap/dist/angular-strap.tpl.js',
        'public/lib/owasp-password-strength-test/owasp-password-strength-test.js',
        'public/lib/angular-ui-switch/angular-ui-switch.js',
        'public/lib/ng-tags-input/ng-tags-input.js',
        'public/lib/underscore/underscore.js',
        'public/lib/moment/moment.js',
        'public/lib/angular-moment-picker/dist/angular-moment-picker.js'
      ],
      tests: ['public/lib/angular-mocks/angular-mocks.js']
    },
    css: [
      'modules/*/client/css/*.css'
    ],
    less: [
      'modules/*/client/less/*.less'
    ],
    sass: [
      'modules/*/client/scss/*.scss'
    ],
    js: [
      'modules/core/client/app/config.js',
      'modules/core/client/app/init.js',
      'modules/*/client/*.js',
      'modules/*/client/**/*.js',
      'modules/*/client/**/**/*.js',
    ],
    views: ['modules/*/client/views/**/*.html'],
    templates: ['build/templates.js']
  },
  server: {
    gruntConfig: 'gruntfile.js',
    gulpConfig: 'gulpfile.js',
    allJS: ['server.js', 'config/**/*.js', 'modules/*/server/**/*.js'],
    models: 'modules/*/server/models/**/*.js',
    routes: ['modules/!(core)/server/routes/**/*.js', 'modules/core/server/routes/**/*.js'],
    sockets: 'modules/*/server/sockets/**/*.js',
    config: 'modules/*/server/config/*.js',
    policies: 'modules/*/server/policies/*.js',
    views: 'modules/*/server/views/*.html'
  }
};
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */

const mongoose = require('mongoose');
const GithubStrategy = require('passport-github').Strategy;
const config = require('../');
const User = mongoose.model('User');

/**
 * Expose
 */

module.exports = new GithubStrategy(
  {
    clientID: config.github.clientID,
    clientSecret: config.github.clientSecret,
    callbackURL: config.github.callbackURL
  },
  function(accessToken, refreshToken, profile, done) {
    const options = {
      criteria: { 'github.id': parseInt(profile.id) }
    };
    User.load(options, function(err, user) {
      if (err) return done(err);
      if (!user) {
        user = new User({
          name: profile.displayName,
          email: profile.emails[0].value,
          username: profile.username,
          provider: 'github',
          github: profile._json
        });
        user.save(function(err) {
          if (err) console.log(err);
          return done(err, user);
        });
      } else {
        return done(err, user);
      }
    });
  }
);
<commit_msg>closes #197<commit_after>'use strict';

/**
 * Module dependencies.
 */

const mongoose = require('mongoose');
const GithubStrategy = require('passport-github').Strategy;
const config = require('../');
const User = mongoose.model('User');

/**
 * Expose
 */

module.exports = new GithubStrategy(
  {
    clientID: config.github.clientID,
    clientSecret: config.github.clientSecret,
    callbackURL: config.github.callbackURL,
    scope: ['user:email']
  },
  function(accessToken, refreshToken, profile, done) {
    const options = {
      criteria: { 'github.id': parseInt(profile.id) }
    };
    User.load(options, function(err, user) {
      if (err) return done(err);
      if (!user) {
        user = new User({
          name: profile.displayName,
          email: profile.emails[0].value,
          username: profile.username,
          provider: 'github',
          github: profile._json
        });
        user.save(function(err) {
          if (err) console.log(err);
          return done(err, user);
        });
      } else {
        return done(err, user);
      }
    });
  }
);
<|endoftext|>


<commit_before>var fb = require('facebook');
var social = require('social_plus');

var win = Ti.UI.createWindow({
	title: 'Unified Status',
	backgroundColor: '#fff'
});

win.add(Ti.UI.createLabel({
	text : 'Post a message',
	top : 4,
	width: '90%',
	textAlign: Ti.UI.TEXT_ALIGNMENT_LEFT,
	font: {
	    fontSize: '22sp'
	}
}));

var txtStatus = Ti.UI.createTextArea({
	top: 15,
	maxLength: 140,
	height: 100,
	top: 37,
	width: '90%',
	borderWidth: 3,
	borderRadius: 4,
	borderColor: '#000',
	color: '#000',
	font: {
	    fontSize: '16sp'
	}
});

var lblCount = Ti.UI.createLabel({
	text: '0/140',
	top: 134,
	width: '90%',
	textAlign: Ti.UI.TEXT_ALIGNMENT_RIGHT
});

txtStatus.addEventListener('change', function(e) {
	lblCount.text = e.value.length + '/140';

	if (e.value.length > 120) {
		lblCount.color = '#ff0000';
	} else {
		lblCount.color = '#000'
	}

	btnPost.enabled = !(e.value.length === 0);
});

win.add(lblCount);
win.add(txtStatus);

var btnPost = Ti.UI.createButton({
	title: 'Post',
	top: 140,
	width: 150
});

win.add(btnPost);

win.addEventListener('click', function() {
	txtStatus.blur();
});

var bottomView = Ti.UI.createView({
	bottom: 4,
	width: '90%',
	height: Ti.UI.SIZE
});

var fbView = Ti.UI.createImageView({
	backgroundColor: '#3B5998',
	image: 'images/fb-logo-disabled.png',
	borderRadius: 4,
	width: 100,
	left: 10,
	height: 100
});

fbView.addEventListener('click', function() {
	toggleFacebook(!fb.loggedIn);
});

bottomView.add(fbView);

var twitView = Ti.UI.createImageView({
	backgroundColor: '#9AE4E8',
	image: 'images/twitter-logo-disabled.png',
	borderRadius: 4,
	width: 100,
	right: 10,
	height: 100
});

twitView.addEventListener('click', function() {
	toggleTwitter(!twitter.isAuthorized())
});

bottomView.add(twitView);

win.add(bottomView);

var activity = Ti.Android.currentActivity;
activity.onCreateOptionsMenu = function(e) {
    var menu = e.menu;
    var menuItem = menu.add({ title: "Settings" });

    menuItem.setIcon(Ti.Android.R.drawable.ic_menu_preferences);

    menuItem.addEventListener("click", function(e) {
        Ti.UI.Android.openPreferences();
    });
};

function toggleFacebook(isActive) {
	if (isActive) {
		if (!fb.loggedin) {
			fb.authorize();
		}
	} else {
		fb.logout();
	}

	Ti.App.Properties.setBool('facebook_preference', isActive);
}

function toggleTwitter(isActive) {
	if (isActive) {
		if (!twitter.isAuthorized()) {
			 twitter.authorize(function() {
			 	twitView.image = 'images/twitter-logo.png';
			 });
		} else {
			twitView.image = 'images/twitter-logo.png';
		}
	} else {
		 twitter.deauthorize();
		 twitView.image = 'images/twitter-logo-disabled.png';
	}

	Ti.App.Properties.setBool('twitter_preference', isActive);
}

function postFacebookStatus(status) {
	fb.requestWithGraphPath('me/feed', {
			message: status
		}, "POST", function(e) {
			if (e.success) {
				Ti.API.info("Success!  From FB: " + e.result);
			} else {
				if (e.error) {
					alert(e.error);
					Ti.API.error(e);
				} else {
					alert("Unkown result from Facebook");
				}
			}
		}
	);
}

function postTwitterStatus(status) {
	twitter.share({
		message: status,
		success: function() {
			alert('Tweeted!');
		},
		error: function() {
			alert('ERROR from Twitter Tweeter');
		}
	});
}

function loadSettings() {
	Ti.API.info('Facebook' + Ti.App.Properties.getBool('facebook_preference'));
	Ti.API.info('Twitter' + Ti.App.Properties.getBool('twitter_preference'));

	var enableFacebook = Ti.App.Properties.getBool('facebook_preference');
	var enableTwitter = Ti.App.Properties.getBool('twitter_preference');

	if (enableFacebook) {
		toggleFacebook(enableFacebook);
	}

	if (enableTwitter) {
		toggleTwitter(enableTwitter);
	}
}

/////////// FACEBOOK
fb.appid = Ti.App.Properties.getString('facebook.appid');
fb.permissions = ['publish_actions'];
fb.forceDialogAuth = false;

fb.addEventListener('login', function(e) {
    if (e.success) {
      	fbView.image = 'images/fb-logo.png';
        Ti.API.debug("http://graph.facebook.com/"+e.uid+"/picture");
      //  Ti.API.info(e);
    } else if (e.error) {
        alert(e.error);
    } else if (e.cancelled) {
        alert("Canceled");
    }
});

fb.addEventListener('logout', function(e) {
    fbView.image = 'images/fb-logo-disabled.png';
});

///////////////// TWITTER
var twitter = social.create({
	consumerSecret : Ti.App.Properties.getString('twitter.consumerSecret'),
	consumerKey : Ti.App.Properties.getString('twitter.consumerKey')
});

btnPost.addEventListener('click', function() {

	if (fb.loggedIn) {
		postFacebookStatus(txtStatus.value);
	}

	if (twitter.isAuthorized()) {
		postTwitterStatus(txtStatus.value);
	}

	txtStatus.blur();
	txtStatus.value = '';
	lblCount.text = '0/140';
});

loadSettings();

win.open();
<commit_msg>Made Android code conditional<commit_after>var fb = require('facebook');
var social = require('social_plus');

var win = Ti.UI.createWindow({
	title: 'Unified Status',
	backgroundColor: '#fff'
});

win.add(Ti.UI.createLabel({
	text : 'Post a message',
	top : 4,
	width: '90%',
	textAlign: Ti.UI.TEXT_ALIGNMENT_LEFT,
	font: {
	    fontSize: '22sp'
	}
}));

var txtStatus = Ti.UI.createTextArea({
	top: 15,
	maxLength: 140,
	height: 100,
	top: 37,
	width: '90%',
	borderWidth: 3,
	borderRadius: 4,
	borderColor: '#000',
	color: '#000',
	font: {
	    fontSize: '16sp'
	}
});

var lblCount = Ti.UI.createLabel({
	text: '0/140',
	top: 134,
	width: '90%',
	textAlign: Ti.UI.TEXT_ALIGNMENT_RIGHT
});

txtStatus.addEventListener('change', function(e) {
	lblCount.text = e.value.length + '/140';

	if (e.value.length > 120) {
		lblCount.color = '#ff0000';
	} else {
		lblCount.color = '#000'
	}

	btnPost.enabled = !(e.value.length === 0);
});

win.add(lblCount);
win.add(txtStatus);

var btnPost = Ti.UI.createButton({
	title: 'Post',
	top: 140,
	width: 150
});

win.add(btnPost);

win.addEventListener('click', function() {
	txtStatus.blur();
});

var bottomView = Ti.UI.createView({
	bottom: 4,
	width: '90%',
	height: Ti.UI.SIZE
});

var fbView = Ti.UI.createImageView({
	backgroundColor: '#3B5998',
	image: 'images/fb-logo-disabled.png',
	borderRadius: 4,
	width: 100,
	left: 10,
	height: 100
});

fbView.addEventListener('click', function() {
	toggleFacebook(!fb.loggedIn);
});

bottomView.add(fbView);

var twitView = Ti.UI.createImageView({
	backgroundColor: '#9AE4E8',
	image: 'images/twitter-logo-disabled.png',
	borderRadius: 4,
	width: 100,
	right: 10,
	height: 100
});

twitView.addEventListener('click', function() {
	toggleTwitter(!twitter.isAuthorized())
});

bottomView.add(twitView);

win.add(bottomView);

if (Ti.Platform.osname == "android") {
	var activity = Ti.Android.currentActivity;

	activity.onCreateOptionsMenu = function(e) {
		var menu = e.menu;
		var menuItem = menu.add({
			title : "Settings"
		});

		menuItem.setIcon(Ti.Android.R.drawable.ic_menu_preferences);

		menuItem.addEventListener("click", function(e) {
			Ti.UI.Android.openPreferences();
		});
	};
}

function toggleFacebook(isActive) {
	if (isActive) {
		if (!fb.loggedin) {
			fb.authorize();
		}
	} else {
		fb.logout();
	}

	Ti.App.Properties.setBool('facebook_preference', isActive);
}

function toggleTwitter(isActive) {
	if (isActive) {
		if (!twitter.isAuthorized()) {
			 twitter.authorize(function() {
			 	twitView.image = 'images/twitter-logo.png';
			 });
		} else {
			twitView.image = 'images/twitter-logo.png';
		}
	} else {
		 twitter.deauthorize();
		 twitView.image = 'images/twitter-logo-disabled.png';
	}

	Ti.App.Properties.setBool('twitter_preference', isActive);
}

function postFacebookStatus(status) {
	fb.requestWithGraphPath('me/feed', {
			message: status
		}, "POST", function(e) {
			if (e.success) {
				Ti.API.info("Success!  From FB: " + e.result);
			} else {
				if (e.error) {
					alert(e.error);
					Ti.API.error(e);
				} else {
					alert("Unkown result from Facebook");
				}
			}
		}
	);
}

function postTwitterStatus(status) {
	twitter.share({
		message: status,
		success: function() {
			alert('Tweeted!');
		},
		error: function() {
			alert('ERROR from Twitter Tweeter');
		}
	});
}

function loadSettings() {
	Ti.API.info('Facebook' + Ti.App.Properties.getBool('facebook_preference'));
	Ti.API.info('Twitter' + Ti.App.Properties.getBool('twitter_preference'));

	var enableFacebook = Ti.App.Properties.getBool('facebook_preference');
	var enableTwitter = Ti.App.Properties.getBool('twitter_preference');

	if (enableFacebook) {
		toggleFacebook(enableFacebook);
	}

	if (enableTwitter) {
		toggleTwitter(enableTwitter);
	}
}

/////////// FACEBOOK
fb.appid = Ti.App.Properties.getString('facebook.appid');
fb.permissions = ['publish_actions'];
fb.forceDialogAuth = false;

fb.addEventListener('login', function(e) {
    if (e.success) {
      	fbView.image = 'images/fb-logo.png';
        Ti.API.debug("http://graph.facebook.com/"+e.uid+"/picture");
      //  Ti.API.info(e);
    } else if (e.error) {
        alert(e.error);
    } else if (e.cancelled) {
        alert("Canceled");
    }
});

fb.addEventListener('logout', function(e) {
    fbView.image = 'images/fb-logo-disabled.png';
});

///////////////// TWITTER
var twitter = social.create({
	consumerSecret : Ti.App.Properties.getString('twitter.consumerSecret'),
	consumerKey : Ti.App.Properties.getString('twitter.consumerKey')
});

btnPost.addEventListener('click', function() {

	if (fb.loggedIn) {
		postFacebookStatus(txtStatus.value);
	}

	if (twitter.isAuthorized()) {
		postTwitterStatus(txtStatus.value);
	}

	txtStatus.blur();
	txtStatus.value = '';
	lblCount.text = '0/140';
});

loadSettings();

win.open();
<|endoftext|>


<commit_before>// @flow

import React, { Component } from 'react';
import { Location, Permissions } from 'expo';
import { getVenues, FOURSQUARE_CATEGORIES } from '../helpers/foursquare';
import type { VenueType } from '../helpers/foursquare';

type LocationData = {
  coords: {
    latitude: number,
    longitude: number,
    altitude: number,
    accuracy: number,
    heading: number,
    speed: number,
  },
  timestamp: number,
};

type State = {
  location?: LocationData,
  venues: VenueType[],
  errorMessage?: 'Permission to access location was denied',
  timestamp: number,
};

export default class LocationProvider extends Component {
  props: {
    render: State => React.Component,
  };
  state: State;
  state = {
    location: null,
    venues: [],
    errorMessage: null,
  };

  locator = null;

  componentWillMount() {
    this._getLocationAsync();
  }

  componentWillUnmount() {
    this._removeListener();
  }

  _removeListener() {
    if (this.locator) {
      this.locator.remove();
    }
  }

  _updateLocation = async location => {
    this.setState(s => ({ ...s, location }));
    const { latitude, longitude } = location.coords;

    const venues = await getVenues({
      latitude,
      longitude,
      radius: 500,
      categoryId: FOURSQUARE_CATEGORIES.join(','), // arts & entertainment
    });

    console.warn(JSON.stringify(venues[0]));

    this.setState(s => ({ ...s, venues }));
  };

  _getLocationAsync = async () => {
    const { status } = await Permissions.askAsync(Permissions.LOCATION);
    if (status !== 'granted') {
      this.setState({
        errorMessage: 'Permission to access location was denied',
      });
    }

    this.locator = await Location.watchPositionAsync(
      { enableHighAccuracy: true },
      this._updateLocation
    );
  };

  render() {
    const { render } = this.props;
    return render(this.state);
  }
}
<commit_msg>nearby venues<commit_after>// @flow

import React, { Component } from 'react';
import { Location, Permissions } from 'expo';
import { getVenues, FOURSQUARE_CATEGORIES } from '../helpers/foursquare';
import type { VenueType } from '../helpers/foursquare';

type LocationData = {
  coords: {
    latitude: number,
    longitude: number,
    altitude: number,
    accuracy: number,
    heading: number,
    speed: number,
  },
  timestamp: number,
};

type State = {
  location?: LocationData,
  venues: VenueType[],
  errorMessage?: 'Permission to access location was denied',
  timestamp: number,
};

export default class LocationProvider extends Component {
  props: {
    render: State => React.Component,
  };
  state: State;
  state = {
    location: null,
    venues: [],
    errorMessage: null,
  };

  locator = null;

  componentWillMount() {
    this._getLocationAsync();
  }

  componentWillUnmount() {
    this._removeListener();
  }

  _removeListener() {
    if (this.locator) {
      this.locator.remove();
    }
  }

  _updateLocation = async location => {
    this.setState(s => ({ ...s, location }));
    const { latitude, longitude } = location.coords;

    const nearby = await getVenues({
      latitude,
      longitude,
      radius: 500,
      categoryId: FOURSQUARE_CATEGORIES.join(','), // arts & entertainment
    });

    this.setState(s => ({ ...s, nearby }));
  };

  _getLocationAsync = async () => {
    const { status } = await Permissions.askAsync(Permissions.LOCATION);
    if (status !== 'granted') {
      this.setState({
        errorMessage: 'Permission to access location was denied',
      });
    }

    this.locator = await Location.watchPositionAsync(
      { enableHighAccuracy: true },
      this._updateLocation
    );
  };

  render() {
    const { render } = this.props;
    return render(this.state);
  }
}
<|endoftext|>


<commit_before>'use strict';
const express = require('express');

let app = express();

app.get('/', (req, res) => {
    res.send("qwe");
});

app.listen(8888);<commit_msg>Added message to see if server is running<commit_after>'use strict';

const express = require('express');
const PORT    = process.env.CUSTOMER_PORT || 8888;
let app       = express();

app.get('/', (req, res) => {
    res.send('Customer is king');
});

app.listen(PORT, () => {
  console.log(`Customer API service running on port: ${PORT}`);
});
<|endoftext|>


<commit_before>// TODO build an session store api
var env = process.env;
var EventEmitter = require('events').EventEmitter;
var cookie = require('cookie');
var clone = require(env.Z_PATH_UTILS + 'clone');
var Model = require(env.Z_PATH_MODELS + 'factory');

var randomStringBase = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
var publicSid = uid();
var sessionCookieKey = 'sid';
var roleKey = env.Z_SESSION_ROLE_KEY;
var userKey = env.Z_SESSION_USER_KEY;
var localeKey = env.Z_SESSION_LOCALE_KEY;
var sessionModel;

module.exports = setup;

// session class
var Session = {};

// create a new session
Session.create = function (role, locale, user, callback) {

    var session = clone(Session);
    session.sid = uid();
    session[roleKey] = role;
    session[userKey] = user;
    session[localeKey] = locale || 'en_US';
    session.store = sessionModel;

    // save session
    session.save(callback);
};

Session.regenerate = function () {
    // renew session with a new sid
};

Session.destroy = function (callback) {
    var self = this;

    // remove from store
    self.store.queries.remove({sid: self.sid}, function (err) {
        callback(err);
    });

    // remove sid
    delete self.sid;
    // set public role
    self[roleKey] = '';
};
Session.reload = function () {
    // reload session data
};

// save session in store
Session.save = function (callback) {
    var self = this;
    var doc = {sid: self.sid};
    doc[localeKey] = self[localeKey];
    doc[roleKey] = self[roleKey];
    doc[userKey] = self[userKey];

    // save session
    self.store.queries.renew({sid: self.sid, doc: doc}, function (err) {
        callback(err, self);
    });
};
Session.touch = function () {
    // update expire
};
Session.maxAge = function () {
    // expire info
};

// setup session middleware
function setup (callback) {

    Model.factory(env.Z_SESSION_MODEL, env.Z_SESSION_ROLE, function (err, model) {

        if (err) {
            return callback(err);
        }

        // save session model (mongodb-native collection)
        sessionModel = model;

        // return handler
        callback(null, factory);

    });
}

// get or create session
function factory (callback) {

    return function (connection, response) {

        // make it compatible with ws connections
        var con = connection.upgradeReq ? connection.upgradeReq : connection;

        // parse cookies, get session id
        if (con.headers.cookie) {
            var parsedCookie = cookie.parse(con.headers.cookie);

            if (parsedCookie && parsedCookie[sessionCookieKey]) {

                // pause connection
                connection.pause();

                var sessionId = parsedCookie[sessionCookieKey];

                // TODO update expire
                return sessionModel.queries.get({sid: sessionId/*, now: new Date().getTime() / 1000*/}, function (err, item) {

                    if (err) {
                        return callback(err);
                    }

                    // set public session if no session is found.. or error?
                    if (!item) {
                        connection.session = {
                            create: Session.create
                        };

                    // create session for current connection
                    } else {

                        var session = clone(Session);
                        session.sid = sessionId;
                        session[roleKey] = item[roleKey];
                        session[localeKey] = item[localeKey];
                        session[userKey] = item[userKey].toString();
                        session.store = sessionModel;

                        // append session to connection
                        connection.session = session;
                    }

                    callback(null, connection, response);
                    connection.resume();
                });
            } else {

                // set public session to connection
                connection.session = {
                    create: Session.create
                };
            }
        } else {

            // set public session to connection
            connection.session = {
                create: Session.create
            };
        }

        callback(null, connection, response);
    };
}

// random string generator
function uid (len, string) {
    len = len || 23;
    string = string || '';

    for (var i = 0; i < len; ++i) {
        string += randomStringBase[0 | Math.random() * 62];
    }
    return string;
}
<commit_msg>use internal "pojo" cache for sessions instead of mongodb<commit_after>// TODO make sessions expire
var env = process.env;
var EventEmitter = require('events').EventEmitter;
var cookie = require('cookie');
var clone = require(env.Z_PATH_UTILS + 'clone');
var cache = require(env.Z_PATH_CACHE + 'cache');

var sessionCache = cache.pojo('sessions');
var randomStringBase = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
var publicSid = uid();
var sessionCookieKey = 'sid';
var roleKey = env.Z_SESSION_ROLE_KEY;
var userKey = env.Z_SESSION_USER_KEY;
var localeKey = env.Z_SESSION_LOCALE_KEY;

module.exports = middleware;

// session class
var Session = {};

// create a new session
Session.create = function (role, locale, user, callback) {

    var session = clone(Session);
    session.sid = uid();
    session[roleKey] = role;
    session[userKey] = user;
    session[localeKey] = locale || 'en_US';
    session.store = sessionCache;

    // save session
    session.save(callback);
};

Session.regenerate = function () {
    // renew session with a new sid
};

Session.destroy = function (callback) {
    var self = this;

    // remove from store
    self.store.rm(self.sid);

    // remove sid
    delete self.sid;

    // set public role
    self[roleKey] = '';

    callback(err);
};
Session.reload = function () {
    // reload session data
};

// save session in store
Session.save = function (callback) {
    var self = this;
    var session = {sid: self.sid};
    session[localeKey] = self[localeKey];
    session[roleKey] = self[roleKey];
    session[userKey] = self[userKey];

    // save session
    self.store.set(self.sid, session);

    callback(null, self);
};
Session.touch = function () {
    // update expire
};
Session.maxAge = function () {
    // expire info
};

// get or create session
function middleware (callback) {

    return function (connection, response) {

        // make it compatible with ws connections
        var con = connection.upgradeReq ? connection.upgradeReq : connection;

        // parse cookies, get session id
        if (con.headers.cookie) {

            var parsedCookie = cookie.parse(con.headers.cookie);

            if (parsedCookie && parsedCookie[sessionCookieKey]) {

                var sessionId = parsedCookie[sessionCookieKey];

                // TODO update expire
                var item = sessionCache.get(sessionId/*, now: new Date().getTime() / 1000*/);

                // set public session if no session is found.. or error?
                if (!item) {
                    connection.session = {
                        create: Session.create
                    };

                // create session for current connection
                } else {

                    var session = clone(Session);
                    session.sid = sessionId;
                    session[roleKey] = item[roleKey];
                    session[localeKey] = item[localeKey];
                    session[userKey] = item[userKey].toString();
                    session.store = sessionCache;

                    // append session to connection
                    connection.session = session;
                }

            // set public session to connection
            } else {
                connection.session = {
                    create: Session.create
                };
            }

        // set public session to connection
        } else {
            connection.session = {
                create: Session.create
            };
        }

        callback(null, connection, response);
    };
}

// random string generator
function uid (len, string) {
    len = len || 23;
    string = string || '';

    for (var i = 0; i < len; ++i) {
        string += randomStringBase[0 | Math.random() * 62];
    }
    return string;
}
<|endoftext|>