<commit_before>#!/usr/bin/env node

'use strict';

async function doAdd()
{
    function * generateQueue(indicator, solutionBookMap)
    {
        const queue = new Set();
        for (const char of charSet)
        {
            const promise =
            (
                async noSave =>
                {
                    const formattedCharacter = formatCharacter(char);
                    const bar = indicator.newBar(`Indexing ${formattedCharacter.padEnd(6)}`);
                    const serializedSolutionBook = await runWorker(solutionBookMap, bar, char);
                    bar.hide();
                    const solutionBook = solutionBookMap.deserialize(serializedSolutionBook);
                    solutionBookMap.set(char, solutionBook);
                    console.log('Character %s indexed', formattedCharacter);
                    if (!noSave)
                        solutionBookMap.save();
                    queue.delete(promise);
                }
            )
            (noSave);
            queue.add(promise);
            if (queue.size >= concurrency)
                yield queue;
        }
        while (queue.size)
            yield queue;
    }

    async function indexCharacters()
    {
        const progress = require('./internal/progress');

        const solutionBookMap = getSolutionBookMap(!noLoad);
        await progress
        (
            async indicator =>
            {
                const generator = generateQueue(indicator, solutionBookMap);
                for (const queue of generator)
                    await Promise.race(queue);
            },
        );
    }

    function runWorker(solutionBookMap, bar, char)
    {
        const executor =
        (resolve, reject) =>
        {
            const { join }      = require('path');
            const { Worker }    = require('worker_threads');

            const workerFileName = join(__dirname, 'internal/char-index-worker.js');
            const serializedSolutionBookMap = solutionBookMap.serialize(solutionBookMap);
            const worker =
            new Worker(workerFileName, { workerData: { char, serializedSolutionBookMap } });
            worker.on
            (
                'message',
                ({ progress, missingChar, serializedSolutionBook }) =>
                {
                    if (progress != null)
                        bar.update(progress);
                    if (missingChar != null)
                    {
                        console.warn
                        (
                            'Character %s required by %s is not indexed',
                            formatCharacter(missingChar),
                            formatCharacter(char),
                        );
                    }
                    if (serializedSolutionBook != null)
                        resolve(serializedSolutionBook);
                },
            );
            worker.on('error', reject);
            worker.on
            (
                'exit',
                code => reject(new Error(`Worker stopped unexpectedly with exit code ${code}`)),
            );
        };
        const promise = new Promise(executor);
        return promise;
    }

    let noLoad = false;
    let noSave = false;
    let concurrency;
    const charSet =
    parseArguments
    (
        sequence =>
        {
            const match = /concurrency(?:=(?<concurrency>.*))?/.exec(sequence);
            if (match)
            {
                concurrency = Number(match.groups.concurrency);
                if (concurrency !== Math.floor(concurrency) || concurrency < 1 || concurrency > 10)
                {
                    console.error('Concurrency must specify an integer between 1 and 10', sequence);
                    throw ARG_ERROR;
                }
            }
            else
            {
                switch (sequence)
                {
                case 'new':
                    noLoad = true;
                    break;
                case 'test':
                    noSave = true;
                    break;
                default:
                    return false;
                }
            }
            return true;
        },
    );
    if (!concurrency)
    {
        const { cpus } = require('os');
        const cpuCount = cpus().length;
        if (cpuCount < 3)
            concurrency = cpuCount;
        else
            concurrency = Math.min(Math.ceil(cpuCount / 2), 10);
    }

    {
        const timeUtils = require('../tools/time-utils');

        const duration = await timeUtils.timeThisAsync(indexCharacters);
        const durationStr = timeUtils.formatDuration(duration);
        console.log('%s elapsed.', durationStr);
    }
}

function doLevel()
{
    const fs = require('fs');
    const path = require('path');

    let output = '';
    for (const solutionBookMap = getSolutionBookMap(); solutionBookMap.size;)
    {
        const independentChars = [];
        for (const [char, solutionBook] of solutionBookMap.entries())
        {
            const { usedChars } = solutionBook;
            if (usedChars.every(usedChar => usedChar === char || !solutionBookMap.has(usedChar)))
                independentChars.push(char);
        }
        independentChars.forEach(char => solutionBookMap.delete(char));
        output += `${formatCharacters(independentChars)}\n`;
    }
    process.stdout.write(output);
    {
        const outputFileName = path.join(__dirname, '..', '.char-index-level');
        fs.writeFileSync(outputFileName, output);
    }
}

function doSort()
{
    function parseCounter()
    {
        let counter;
        const [,,, arg] = argv;
        switch (arg)
        {
        case 'jscrewit-timestamp':
            counter = ({ jscrewitTimestamp }) => jscrewitTimestamp;
            break;
        case 'max-length':
            counter = ({ solutions }) => Math.max(...solutions.map(({ length }) => length));
            break;
        case 'min-length':
            counter = ({ solutions }) => Math.min(...solutions.map(({ length }) => length));
            break;
        case 'solutions':
            counter = ({ solutions: { length } }) => length;
            break;
        default:
            console.error('Unexpected argument "%s"', arg);
            throw ARG_ERROR;
        }
        return counter;
    }

    const entries = [];
    {
        const counter = parseCounter();
        const solutionBookMap = getSolutionBookMap();
        for (const [char, solutionBook] of solutionBookMap.entries())
        {
            const count = counter(solutionBook);
            const entry = { char, count };
            entries.push(entry);
        }
    }
    entries.sort(({ count: count1 }, { count: count2 }) => count1 - count2);
    const maxCountLength = String(entries[entries.length - 1].count).length;
    for (const { char, count } of entries)
    {
        const formattedChar = formatCharacter(char).padEnd(6);
        const formattedCount = String(count).padStart(maxCountLength);
        console.log('%s %s', formattedChar, formattedCount);
    }
}

function doUses()
{
    const charSet = parseArguments(() => false);
    const solutionBookMap = getSolutionBookMap();
    const dependentChars = [];
    for (const [char, solutionBook] of solutionBookMap)
    {
        if (solutionBook.usedChars.some(char => charSet.has(char)))
            dependentChars.push(char);
    }
    console.log(formatCharacters(dependentChars));
}

function doWanted()
{
    const wantedChars = getWantedCharacters();
    console.log(formatCharacters(wantedChars));
}

function formatCharacter(char)
{
    if (' #&\'(),;<=>?[]{|}~'.includes(char))
        return `"${char}"`;
    if (char === '\\' || char === '`')
        return `"\\${char}"`;
    const charCode = char.charCodeAt();
    if (charCode >= 0x20 && charCode <= 0x7e && charCode !== 0x22 || charCode >= 0xa0)
        return char;
    return `U+${charCode.toString(16).toUpperCase().padStart(4, '0')}`;
}

function formatCharacters(chars)
{
    let str = '';
    let prevCharLong;
    for (const char of chars)
    {
        const formattedChar = formatCharacter(char);
        const charLong = formattedChar.length > 1;
        if (str && (prevCharLong || charLong))
            str += ' ';
        str += formattedChar;
        prevCharLong = charLong;
    }
    return str;
}

function getSolutionBookMap(load = true)
{
    const solutionBookMap = require('./internal/solution-book-map');

    if (load)
        solutionBookMap.load();
    return solutionBookMap;
}

function getWantedCharacters()
{
    const { getCharacters } = require('..').debug;

    const solutionBookMap = getSolutionBookMap();
    const wantedChars = getCharacters().filter(char => !solutionBookMap.has(char));
    return wantedChars;
}

function isCharacterDefined(char)
{
    const { getCharacterEntries } = require('..').debug;

    const charDefined = !!getCharacterEntries(char);
    return charDefined;
}

function parseArguments(parseSequence)
{
    const charSet = new Set();
    {
        const LOGICAL_SETS =
        {
            __proto__:  null,
            static:     () => '+-.0123456789INadefilnrstuy',
            wanted:     getWantedCharacters,
        };
        for (let index = 3; index < argCount; ++index)
        {
            const arg = argv[index];
            const matches =
            /^\s*(?:--(?<sequence>.*)|\*(?<logicalSet>.*)\*|U\+(?<hexCode>[\dA-F]{4}))\s*$/i
            .exec(arg);
            if (matches)
            {
                const { sequence, logicalSet, hexCode } = matches.groups;
                if (sequence != null)
                {
                    if (!parseSequence(sequence))
                    {
                        console.error('Unknown sequence "%s"', sequence);
                        throw ARG_ERROR;
                    }
                }
                else if (logicalSet != null)
                {
                    const charsProvider = LOGICAL_SETS[logicalSet];
                    if (!charsProvider)
                    {
                        console.error('Unknown logical set "%s"', logicalSet);
                        throw ARG_ERROR;
                    }
                    {
                        const chars = charsProvider();
                        for (const char of chars)
                            charSet.add(char);
                    }
                }
                else
                {
                    const charCode = parseInt(hexCode, 16);
                    const char = String.fromCharCode(charCode);
                    charSet.add(char);
                }
            }
            else
            {
                for (const char of arg)
                    charSet.add(char);
            }
        }
    }
    {
        const unindexableChars = [...charSet].filter(char => !isCharacterDefined(char));
        if (unindexableChars.length)
        {
            console.error
            ('Unindexable characters specified: %s', formatCharacters(unindexableChars));
            throw ARG_ERROR;
        }
    }
    return charSet;
}

function printHelp()
{
    const help =
    'char-index add [--new] [--test] <chars>\n' +
    'char-index level\n' +
    'char-index sort [jscrewit-timestamp|max-length|min-length|solutions]\n' +
    'char-index uses <chars>\n' +
    'char-index wanted\n' +
    'char-index help\n' +
    '\n' +
    'Characters can be specified in different ways:\n' +
    '• ABC       Characters "A", "B" and "C"\n' +
    '• U+0123    Character with hexadecimal code 123\n' +
    '• *static*  Characters in the static set\n' +
    '• *wanted*  Characters defined by JScrewIt but not indexed yet';
    console.log(help);
}

const ARG_ERROR = { };

const { argv } = process;
const argCount = argv.length;
if (argCount < 3)
    printHelp();
else
{
    const COMMANDS =
    {
        __proto__:  null,
        add:        doAdd,
        help:       printHelp,
        level:      doLevel,
        sort:       doSort,
        uses:       doUses,
        wanted:     doWanted,
    };

    const [,, command] = argv;
    const commandCall = COMMANDS[command];
    (async () =>
    {
        try
        {
            if (!commandCall)
            {
                console.error
                ('char-index: \'%s\' is not a valid command. See \'char-index help\'.', command);
                throw ARG_ERROR;
            }
            await commandCall();
        }
        catch (error)
        {
            if (error !== ARG_ERROR)
                throw error;
            process.exitCode = 1;
        }
    }
    )();
}
<commit_msg>Improved usability of the char-index utility in zsh<commit_after>#!/usr/bin/env node

'use strict';

async function doAdd()
{
    function * generateQueue(indicator, solutionBookMap)
    {
        const queue = new Set();
        for (const char of charSet)
        {
            const promise =
            (
                async noSave =>
                {
                    const formattedCharacter = formatCharacter(char);
                    const bar = indicator.newBar(`Indexing ${formattedCharacter.padEnd(6)}`);
                    const serializedSolutionBook = await runWorker(solutionBookMap, bar, char);
                    bar.hide();
                    const solutionBook = solutionBookMap.deserialize(serializedSolutionBook);
                    solutionBookMap.set(char, solutionBook);
                    console.log('Character %s indexed', formattedCharacter);
                    if (!noSave)
                        solutionBookMap.save();
                    queue.delete(promise);
                }
            )
            (noSave);
            queue.add(promise);
            if (queue.size >= concurrency)
                yield queue;
        }
        while (queue.size)
            yield queue;
    }

    async function indexCharacters()
    {
        const progress = require('./internal/progress');

        const solutionBookMap = getSolutionBookMap(!noLoad);
        await progress
        (
            async indicator =>
            {
                const generator = generateQueue(indicator, solutionBookMap);
                for (const queue of generator)
                    await Promise.race(queue);
            },
        );
    }

    function runWorker(solutionBookMap, bar, char)
    {
        const executor =
        (resolve, reject) =>
        {
            const { join }      = require('path');
            const { Worker }    = require('worker_threads');

            const workerFileName = join(__dirname, 'internal/char-index-worker.js');
            const serializedSolutionBookMap = solutionBookMap.serialize(solutionBookMap);
            const worker =
            new Worker(workerFileName, { workerData: { char, serializedSolutionBookMap } });
            worker.on
            (
                'message',
                ({ progress, missingChar, serializedSolutionBook }) =>
                {
                    if (progress != null)
                        bar.update(progress);
                    if (missingChar != null)
                    {
                        console.warn
                        (
                            'Character %s required by %s is not indexed',
                            formatCharacter(missingChar),
                            formatCharacter(char),
                        );
                    }
                    if (serializedSolutionBook != null)
                        resolve(serializedSolutionBook);
                },
            );
            worker.on('error', reject);
            worker.on
            (
                'exit',
                code => reject(new Error(`Worker stopped unexpectedly with exit code ${code}`)),
            );
        };
        const promise = new Promise(executor);
        return promise;
    }

    let noLoad = false;
    let noSave = false;
    let concurrency;
    const charSet =
    parseArguments
    (
        sequence =>
        {
            const match = /concurrency(?:=(?<concurrency>.*))?/.exec(sequence);
            if (match)
            {
                concurrency = Number(match.groups.concurrency);
                if (concurrency !== Math.floor(concurrency) || concurrency < 1 || concurrency > 10)
                {
                    console.error('Concurrency must specify an integer between 1 and 10', sequence);
                    throw ARG_ERROR;
                }
            }
            else
            {
                switch (sequence)
                {
                case 'new':
                    noLoad = true;
                    break;
                case 'test':
                    noSave = true;
                    break;
                default:
                    return false;
                }
            }
            return true;
        },
    );
    if (!concurrency)
    {
        const { cpus } = require('os');
        const cpuCount = cpus().length;
        if (cpuCount < 3)
            concurrency = cpuCount;
        else
            concurrency = Math.min(Math.ceil(cpuCount / 2), 10);
    }

    {
        const timeUtils = require('../tools/time-utils');

        const duration = await timeUtils.timeThisAsync(indexCharacters);
        const durationStr = timeUtils.formatDuration(duration);
        console.log('%s elapsed.', durationStr);
    }
}

function doLevel()
{
    const fs = require('fs');
    const path = require('path');

    let output = '';
    for (const solutionBookMap = getSolutionBookMap(); solutionBookMap.size;)
    {
        const independentChars = [];
        for (const [char, solutionBook] of solutionBookMap.entries())
        {
            const { usedChars } = solutionBook;
            if (usedChars.every(usedChar => usedChar === char || !solutionBookMap.has(usedChar)))
                independentChars.push(char);
        }
        independentChars.forEach(char => solutionBookMap.delete(char));
        output += `${formatCharacters(independentChars)}\n`;
    }
    process.stdout.write(output);
    {
        const outputFileName = path.join(__dirname, '..', '.char-index-level');
        fs.writeFileSync(outputFileName, output);
    }
}

function doSort()
{
    function parseCounter()
    {
        let counter;
        const [,,, arg] = argv;
        switch (arg)
        {
        case 'jscrewit-timestamp':
            counter = ({ jscrewitTimestamp }) => jscrewitTimestamp;
            break;
        case 'max-length':
            counter = ({ solutions }) => Math.max(...solutions.map(({ length }) => length));
            break;
        case 'min-length':
            counter = ({ solutions }) => Math.min(...solutions.map(({ length }) => length));
            break;
        case 'solutions':
            counter = ({ solutions: { length } }) => length;
            break;
        default:
            console.error('Unexpected argument "%s"', arg);
            throw ARG_ERROR;
        }
        return counter;
    }

    const entries = [];
    {
        const counter = parseCounter();
        const solutionBookMap = getSolutionBookMap();
        for (const [char, solutionBook] of solutionBookMap.entries())
        {
            const count = counter(solutionBook);
            const entry = { char, count };
            entries.push(entry);
        }
    }
    entries.sort(({ count: count1 }, { count: count2 }) => count1 - count2);
    const maxCountLength = String(entries[entries.length - 1].count).length;
    for (const { char, count } of entries)
    {
        const formattedChar = formatCharacter(char).padEnd(6);
        const formattedCount = String(count).padStart(maxCountLength);
        console.log('%s %s', formattedChar, formattedCount);
    }
}

function doUses()
{
    const charSet = parseArguments(() => false);
    const solutionBookMap = getSolutionBookMap();
    const dependentChars = [];
    for (const [char, solutionBook] of solutionBookMap)
    {
        if (solutionBook.usedChars.some(char => charSet.has(char)))
            dependentChars.push(char);
    }
    console.log(formatCharacters(dependentChars));
}

function doWanted()
{
    const wantedChars = getWantedCharacters();
    console.log(formatCharacters(wantedChars));
}

function formatCharacter(char)
{
    if (' #&\'(),;<=>?[]{|}~'.includes(char))
        return `"${char}"`;
    if (char === '\\' || char === '`')
        return `"\\${char}"`;
    const charCode = char.charCodeAt();
    if
    (
        charCode >= 0x20 && charCode <= 0x7e && charCode !== 0x22 ||
        charCode >= 0xa0 && !/(?=\p{L})(?=\p{sc=Arab})/u.test(char)
    )
        return char;
    return `U+${charCode.toString(16).toUpperCase().padStart(4, '0')}`;
}

function formatCharacters(chars)
{
    let str = '';
    let prevCharLong;
    for (const char of chars)
    {
        const formattedChar = formatCharacter(char);
        const charLong = formattedChar.length > 1;
        if (str && (prevCharLong || charLong))
            str += ' ';
        str += formattedChar;
        prevCharLong = charLong;
    }
    return str;
}

function getSolutionBookMap(load = true)
{
    const solutionBookMap = require('./internal/solution-book-map');

    if (load)
        solutionBookMap.load();
    return solutionBookMap;
}

function getWantedCharacters()
{
    const { getCharacters } = require('..').debug;

    const solutionBookMap = getSolutionBookMap();
    const wantedChars = getCharacters().filter(char => !solutionBookMap.has(char));
    return wantedChars;
}

function isCharacterDefined(char)
{
    const { getCharacterEntries } = require('..').debug;

    const charDefined = !!getCharacterEntries(char);
    return charDefined;
}

function parseArguments(parseSequence)
{
    const charSet = new Set();
    {
        const LOGICAL_SETS =
        {
            __proto__:  null,
            static:     () => '+-.0123456789INadefilnrstuy',
            wanted:     getWantedCharacters,
        };
        for (let index = 3; index < argCount; ++index)
        {
            const arg = argv[index];
            const matches =
            /^\s*(?:--(?<sequence>.*)|:(?<logicalSet>.*):|U\+(?<hexCode>[\dA-F]{4}))\s*$/i
            .exec(arg);
            if (matches)
            {
                const { sequence, logicalSet, hexCode } = matches.groups;
                if (sequence != null)
                {
                    if (!parseSequence(sequence))
                    {
                        console.error('Unknown sequence "%s"', sequence);
                        throw ARG_ERROR;
                    }
                }
                else if (logicalSet != null)
                {
                    const charsProvider = LOGICAL_SETS[logicalSet];
                    if (!charsProvider)
                    {
                        console.error('Unknown logical set "%s"', logicalSet);
                        throw ARG_ERROR;
                    }
                    {
                        const chars = charsProvider();
                        for (const char of chars)
                            charSet.add(char);
                    }
                }
                else
                {
                    const charCode = parseInt(hexCode, 16);
                    const char = String.fromCharCode(charCode);
                    charSet.add(char);
                }
            }
            else
            {
                for (const char of arg)
                    charSet.add(char);
            }
        }
    }
    {
        const unindexableChars = [...charSet].filter(char => !isCharacterDefined(char));
        if (unindexableChars.length)
        {
            console.error
            ('Unindexable characters specified: %s', formatCharacters(unindexableChars));
            throw ARG_ERROR;
        }
    }
    return charSet;
}

function printHelp()
{
    const help =
    'char-index add [--new] [--test] <chars>\n' +
    'char-index level\n' +
    'char-index sort [jscrewit-timestamp|max-length|min-length|solutions]\n' +
    'char-index uses <chars>\n' +
    'char-index wanted\n' +
    'char-index help\n' +
    '\n' +
    'Characters can be specified in different ways:\n' +
    '• ABC       Characters "A", "B" and "C"\n' +
    '• U+0123    Character with hexadecimal code 123\n' +
    '• :static:  Characters in the static set\n' +
    '• :wanted:  Characters defined by JScrewIt but not indexed yet';
    console.log(help);
}

const ARG_ERROR = { };

const { argv } = process;
const argCount = argv.length;
if (argCount < 3)
    printHelp();
else
{
    const COMMANDS =
    {
        __proto__:  null,
        add:        doAdd,
        help:       printHelp,
        level:      doLevel,
        sort:       doSort,
        uses:       doUses,
        wanted:     doWanted,
    };

    const [,, command] = argv;
    const commandCall = COMMANDS[command];
    (async () =>
    {
        try
        {
            if (!commandCall)
            {
                console.error
                ('char-index: \'%s\' is not a valid command. See \'char-index help\'.', command);
                throw ARG_ERROR;
            }
            await commandCall();
        }
        catch (error)
        {
            if (error !== ARG_ERROR)
                throw error;
            process.exitCode = 1;
        }
    }
    )();
}
<|endoftext|>


<commit_before>module.controller('SlotView', [
	'$scope', 'slot', 'pageService', function ($scope, slot, page) {
		$scope.slot = slot;

		page.display.title = slot.name;
		page.display.toolbarLinks = [];
	}
]);
<commit_msg>fix slotView title<commit_after>module.controller('SlotView', [
	'$scope', 'slot', 'pageService', function ($scope, slot, page) {
		$scope.slot = slot;

		page.display.title = page.types.slotName(slot);
		page.display.toolbarLinks = [];
	}
]);
<|endoftext|>


<commit_before>// Use jQuery for DOM manipulation

function getDestinationCordinates() {

    // Get div to display cordinates
    var div = document.getElementById('display');

    // Get all meta tags, check property and store lat/long into JS vars
    var metas = document.getElementsByTagName('meta');

    for (i=0; i<metas.length; i++) {
        if (metas[i].getAttribute("property") == "zomatocom:location:latitude") {
                    var lat = metas[i].getAttribute("content");
                    $("#display").append("Latitude: "+lat);
            }
            else if (metas[i].getAttribute("property") == "zomatocom:location:longitude") {
                    var long = metas[i].getAttribute("content");
                    $("#display").append("
Longitude: "+long);
            }
    }
}
<commit_msg>Forgot to add new JS file lol<commit_after>// Use jQuery for DOM manipulation

function getDestinationCordinates() {

    // Get div to display cordinates
    var div = document.getElementById('display');

    // Get all meta tags, check property and store lat/long into JS vars
    //var metas = document.getElementsByTagName('meta');

    var lat = $("meta[property='zomatocom:location:latitude']").attr("content");
    var long = $("meta[property='zomatocom:location:longitude']").attr("content");
    $("#display").append("Latitude: "+lat);
    $("#display").append("
Longitude: "+long);
}
<|endoftext|>


<commit_before>/* global describe, it, beforeEach, expect, module*/

import angular from 'angular';

import Tester from 'tester';
import '../';

import fixtures from './fixtures';

describe('avDropdown', () => {

  let $el;
  const tester = new Tester();

  beforeEach(() => {
    angular.mock.module('availity');
    angular.mock.module('availity.ui');
  });

  beforeEach(angular.mock.module(avDropdownConfigProvider => {

    avDropdownConfigProvider.set({
      width: 100,
      minimumInputLength: 5
    });

  }));

  tester.directive();

  it('should create DOM structure', () => {
    $el = tester.compileDirective(fixtures.standard);
    tester.flush();
    expect($el.siblings().is('div.select2-container')).toBe(true);
  });

  describe('AvDropdownController', () => {

    it('should default options when supplied', () => {

      $el = tester.compileDirective(fixtures.standard);

      expect($el.data('$avDropdownController').options.width).toBe(100);
      expect($el.data('$avDropdownController').options.minimumInputLength).toBe(5);
    });

    it('should use attribute values over default values', () => {

      $el = tester.compileDirective(fixtures.query);

      expect($el.data('$avDropdownController').options.minimumInputLength).toBe(0);
    });

  });

  describe('$ngModelController', () => {

    it('should be $pristine on load', () => {

      tester.$scope.demo = {};
      tester.$scope.demo.selections = ['first', 'second', 'third'];
      tester.$scope.demo.selected = 1;

      $el = tester.compileDirective(fixtures.standard);
      tester.flush();

      expect($el.data('$ngModelController').$pristine).toBe(true);

      // this should update the model and control state. this test is here
      // just to demonstrate the behavior and refresh our memory
      $el.trigger('change');

      expect($el.data('$ngModelController').$pristine).toBe(false);
      expect($el.data('$ngModelController').$dirty).toBe(true);

    });

  });

  describe('models', () => {

    it('should update when type is array', () => {

      tester.$scope.demo = {};
      tester.$scope.demo.selections = ['first', 'second', 'third'];
      tester.$scope.demo.selected = 'first';

      $el = tester.compileDirective(fixtures.standard);

      tester.flush();

      tester.$scope.demo.selected = 'second';
      tester.$scope.$apply();
      tester.flush();
      expect($el.select2('val')).toBe('string:second');

    });

    it('should update when types are objects', () => {

      tester.$scope.demo = {};
      tester.$scope.demo.selections = [
        {
          id: 1,
          value: 'first'
        },
        {
          id: 2,
          value: 'second'
        },
        {
          id: 3,
          value: 'third'
        }
      ];
      tester.$scope.demo.selected = tester.$scope.demo.selections[0];

      $el = tester.compileDirective(fixtures.objects);

      tester.flush();

      tester.$scope.demo.selected = tester.$scope.demo.selections[1];
      tester.$scope.$apply();
      tester.flush();

      expect($el.select2('val')).toBe('object:229');

    });

  });

});
<commit_msg>make the test for object collection in Select2 more precise<commit_after>/* global describe, it, beforeEach, expect, module*/

import angular from 'angular';

import Tester from 'tester';
import '../';

import fixtures from './fixtures';

describe('avDropdown', () => {

  let $el;
  const tester = new Tester();

  beforeEach(() => {
    angular.mock.module('availity');
    angular.mock.module('availity.ui');
  });

  beforeEach(angular.mock.module(avDropdownConfigProvider => {

    avDropdownConfigProvider.set({
      width: 100,
      minimumInputLength: 5
    });

  }));

  tester.directive();

  it('should create DOM structure', () => {
    $el = tester.compileDirective(fixtures.standard);
    tester.flush();
    expect($el.siblings().is('div.select2-container')).toBe(true);
  });

  describe('AvDropdownController', () => {

    it('should default options when supplied', () => {

      $el = tester.compileDirective(fixtures.standard);

      expect($el.data('$avDropdownController').options.width).toBe(100);
      expect($el.data('$avDropdownController').options.minimumInputLength).toBe(5);
    });

    it('should use attribute values over default values', () => {

      $el = tester.compileDirective(fixtures.query);

      expect($el.data('$avDropdownController').options.minimumInputLength).toBe(0);
    });

  });

  describe('$ngModelController', () => {

    it('should be $pristine on load', () => {

      tester.$scope.demo = {};
      tester.$scope.demo.selections = ['first', 'second', 'third'];
      tester.$scope.demo.selected = 1;

      $el = tester.compileDirective(fixtures.standard);
      tester.flush();

      expect($el.data('$ngModelController').$pristine).toBe(true);

      // this should update the model and control state. this test is here
      // just to demonstrate the behavior and refresh our memory
      $el.trigger('change');

      expect($el.data('$ngModelController').$pristine).toBe(false);
      expect($el.data('$ngModelController').$dirty).toBe(true);

    });

  });

  describe('models', () => {

    it('should update when type is array', () => {

      tester.$scope.demo = {};
      tester.$scope.demo.selections = ['first', 'second', 'third'];
      tester.$scope.demo.selected = 'first';

      $el = tester.compileDirective(fixtures.standard);

      tester.flush();

      tester.$scope.demo.selected = 'second';
      tester.$scope.$apply();
      tester.flush();
      expect($el.select2('val')).toBe('string:second');

    });

    it('should update when types are objects', () => {

      tester.$scope.demo = {};
      tester.$scope.demo.selections = [
        {
          id: 1,
          value: 'first'
        },
        {
          id: 2,
          value: 'second'
        },
        {
          id: 3,
          value: 'third'
        }
      ];
      tester.$scope.demo.selected = tester.$scope.demo.selections[0];

      $el = tester.compileDirective(fixtures.objects);

      tester.flush();

      tester.$scope.demo.selected = tester.$scope.demo.selections[0];
      tester.$scope.$apply();
      tester.flush();

      // Angular adds a property called $$hashkey to objects in order to track them in a collection.
      //
      //  @see https://github.com/angular/angular.js/blob/ddb4ef13a9793b93280e6b5ab2e0593af1c04743/src/ng/directive/ngOptions.js#L282.
      //  @see https://github.com/angular/angular.js/blob/07849779ba365f371a8caa3b58e23f677cfdc5ad/src/apis.js#L28
      //
      // We use the same method here to get the key and compare it so the value in Select2.
      expect($el.select2('val')).toBe(tester.$scope.demo.selections[0].$$hashKey);

    });

  });

});
<|endoftext|>


<commit_before>function get_node_size(type) {
  if (type == "switch")
    return 15;
  else if (type == "interface")
    return 5;
  else if (type == "host")
    return 10;
}

var svg = d3.select("#topology-chart svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height");

// Adds Pan and Zoom
// svg.call(d3.zoom().on("zoom", function () {
//             svg.attr("transform", d3.event.transform)
//     }))

var color = d3.scaleOrdinal(d3.schemeCategory20);

var simulation = d3.forceSimulation()
    .force("link", d3.forceLink().id(function(d) { return d.name; }))
    .force("charge", d3.forceManyBody())
    .force("center", d3.forceCenter(width / 2, height / 2));

d3.json("/static/data/topology.json", function(error, graph) {
  if (error) throw error;

  var link = svg.append("g")
      .attr("class", "links")
    .selectAll("line")
    .data(graph.links)
    .enter().append("line")
      .attr("stroke-width", function(d) { return Math.sqrt(d.value); });

  var node = svg.append("g")
      .attr("class", "nodes")
    .selectAll("circle")
    .data(graph.nodes)
    .enter().append("circle")
      .attr("r", function(d) { return get_node_size(d.type); })
      .attr("fill", function(d) { return color(d.group); })
      .call(d3.drag()
          .on("start", dragstarted)
          .on("drag", dragged)
          .on("end", dragended))
          .on("dblclick", releaseNode);

  node.append("title")
      .text(function(d) { return d.name; });

  simulation
      .nodes(graph.nodes)
      .on("tick", ticked);

  simulation.force("link")
      .links(graph.links);

  function ticked() {
    link
        .attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });

    node
        .attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
  }
});

function dragstarted(d) {
  if (!d3.event.active) simulation.alphaTarget(0.3).restart();
  d.fx = d.x;
  d.fy = d.y;
}

function dragged(d) {
  d.fx = d3.event.x;
  d.fy = d3.event.y;
}

function dragended(d) {
  if (!d3.event.active) simulation.alphaTarget(0);
  // uncomment the lines bellow to disable de fixed drag behavior
  //d.fx = null;
  //d.fy = null;
}

function releaseNode(d) {
    d.fx = null;
    d.fy = null;
}

<commit_msg>Improving strength/distance between elements (nodes and links)<commit_after>function get_node_size(type) {
  return size[type];
}

var charge = {'switch': 400,
              'host': 20,
              'interface': -20};

var size = {'switch': 20,
            'host': 10,
            'interface': 5};

// Links vars
var strength = {'link': 0.0001,
                'interface': 2,
                'host': 0.05};

var distance = {'link': 6 * size['switch'],
                'interface': size['switch'],
                'host': 5 * size['interface']};

var svg = d3.select("#topology-chart svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height");

// Adds Pan and Zoom
// svg.call(d3.zoom().on("zoom", function () {
//             svg.attr("transform", d3.event.transform)
//     }))

var color = d3.scaleOrdinal(d3.schemeCategory20);

var simulation = d3.forceSimulation()
    .force("link", d3.forceLink().id(function(d) { return d.name; })
                                 .strength(function(d) { return strength[d.type]; })
                                 .distance(function(d) { return distance[d.type]; })
          )
    .force("charge", d3.forceManyBody())
    .force("center", d3.forceCenter(width / 2, height / 2));

d3.json("/static/data/topology.json", function(error, graph) {
  if (error) throw error;

  var link = svg.append("g")
      .attr("class", "links")
    .selectAll("line")
    .data(graph.links)
    .enter().append("line")
      .attr("stroke-width", function(d) { return Math.sqrt(d.value); });

  var node = svg.append("g")
      .attr("class", "nodes")
    .selectAll("circle")
    .data(graph.nodes)
    .enter().append("circle")
      .attr("r", function(d) { return get_node_size(d.type); })
      .attr("fill", function(d) { return color(d.group); })
      .call(d3.drag()
          .on("start", dragstarted)
          .on("drag", dragged)
          .on("end", dragended))
          .on("dblclick", releaseNode);

  node.append("title")
      .text(function(d) { return d.name; });

  simulation
      .nodes(graph.nodes)
      .on("tick", ticked);

  simulation.force("link")
      .links(graph.links);

  function ticked() {
    link
        .attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });

    node
        .attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
  }
});

function dragstarted(d) {
  if (!d3.event.active) simulation.alphaTarget(0.3).restart();
  d.fx = d.x;
  d.fy = d.y;
}

function dragged(d) {
  d.fx = d3.event.x;
  d.fy = d3.event.y;
}

function dragended(d) {
  if (!d3.event.active) simulation.alphaTarget(0);
  // uncomment the lines bellow to disable de fixed drag behavior
  //d.fx = null;
  //d.fy = null;
}

function releaseNode(d) {
    d.fx = null;
    d.fy = null;
}

<|endoftext|>


<commit_before>/*

Metaball rendering demo. Many ideas and code taken from here

 */

const regl = require('../regl')()
const surfaceNets = require('surface-nets')
const ndarray = require('ndarray')
const normals = require('angle-normals')
const mat3 = require('gl-mat3')
const camera = require('./util/camera')(regl, {
  distance: 1.5,
  maxDistance: 3,
  minDistance: 0.5,
  center: [1, 1, 1],
  theta: 1.0
})

const maxCount = 4096

const positionBuffer = regl.buffer({
  length: maxCount * 3 * 4,
  type: 'float',
  usage: 'dynamic'
})

const normalBuffer = regl.buffer({
  length: maxCount * 3 * 4,
  type: 'float',
  usage: 'dynamic'
})

const cellsBuffer = regl.elements({
  length: (maxCount*3* 3) * 3 * 2,
  count: (maxCount*3* 3),
  type: 'uint16',
  usage: 'dynamic',
  primitive: 'triangles',
})

const drawBackground = regl({
  vert: `
    precision mediump float;
    attribute vec2 position;
    void main() {
      gl_Position = vec4(position, 0., 1.);
    }`,
  frag: `
    precision mediump float;
    uniform vec3 color;
    uniform float noise, width, height;

    #define VIG_REDUCTION_POWER 1.
    #define VIG_BOOST 1.

    float random(vec3 scale,float seed) {
      return fract(sin(dot(gl_FragCoord.xyz+seed,scale))*43758.5453+seed);
    }

    void main () {
      vec2 resolution = vec2(width, height);
      vec2 center = resolution * 0.5;
      float vignette = distance( center, gl_FragCoord.xy ) / resolution.x;
      vignette = VIG_BOOST - vignette * VIG_REDUCTION_POWER;

      float n = noise * (.5 - random(vec3(1.), length(gl_FragCoord)));

      float v = .5 * length(vec2(gl_FragCoord.y / resolution.y, (1. - abs(.5 - gl_FragCoord.x / resolution.x))));
      vec3 base = color;
      base += vec3(pow(v, 2.));

      gl_FragColor = vec4(base * vec3(vignette) + vec3(n), 1.);
    }`,
  uniforms: {
    color: [36 / 255.0, 70 / 255.0, 106 / 255.0],
    width: regl.context('viewportWidth'),
    height: regl.context('viewportHeight'),
    noise: 0.05
  },
  attributes: {
    position: [-4, -4, 4, -4, 0, 4]
  },
  count: 3
})

const drawMetaballs = regl({
  vert: `
    precision mediump float;
    uniform mat4 projection, view;
    uniform mat3 normalMatrix;

    attribute vec3 position, normal;

    varying vec3 vNormal, vONormal, vU;
    varying vec4 vPosition, vOPosition;

    void main () {
      vNormal = normalMatrix * normal;
      vONormal = normal;
      vPosition = vec4(position, 1.0);
      vOPosition = view * vPosition;
      vU = normalize(vec3(vOPosition));
      gl_Position = projection * vOPosition;
    }`,
  frag: `
    precision mediump float;
    uniform sampler2D textureMap, normalMap;
    uniform float normalScale, texScale;
    uniform vec3 color, eye;

    varying vec3 vNormal, vONormal, vU;
    varying vec4 vPosition, vOPosition;

    float random(vec3 scale, float seed) {
      return fract(sin(dot(gl_FragCoord.xyz + seed,scale)) * 43758.5453 + seed);
    }

    vec3 spherical_environment_map(vec3 ray, vec3 normal) {
      vec3 r = reflect(normalize(ray), normalize(normal));
      float m = 2.0 * sqrt(r.x * r.x + r.y * r.y + (r.z + 1.0) * (r.z + 1.0));
      vec2 calculatedNormal = vec2(r.x / m + 0.5, r.y / m + 0.5);
      return texture2D(textureMap, calculatedNormal).rgb;
    }

    mat3 tangent_space_basis(vec3 blend_weights) {
      vec3 tanX = vec3(vNormal.x, -vNormal.z, vNormal.y);
      vec3 tanY = vec3(vNormal.z, vNormal.y, -vNormal.x);
      vec3 tanZ = vec3(-vNormal.y, vNormal.x, vNormal.z);
      vec3 blended_tangent = tanX * blend_weights.xxx +
                             tanY * blend_weights.yyy +
                             tanZ * blend_weights.zzz;

      return mat3(
        normalize(blended_tangent),
        normalize(cross(vNormal, blended_tangent)),
        normalize(vNormal)
      );
    }

    vec3 blended_bump(vec3 blend_weights) {
      vec2 coord1 = vPosition.yz * texScale;
      vec2 coord2 = vPosition.zx * texScale;
      vec2 coord3 = vPosition.xy * texScale;

      vec3 bump1 = texture2D(normalMap, coord1).rgb;
      vec3 bump2 = texture2D(normalMap, coord2).rgb;
      vec3 bump3 = texture2D(normalMap, coord3).rgb;

      return bump1 * blend_weights.xxx +
             bump2 * blend_weights.yyy +
             bump3 * blend_weights.zzz;
    }

    void main() {
      vec3 blend_weights = abs(normalize(vONormal.xyz));
      blend_weights = (blend_weights - 0.2) * 7.;
      blend_weights = max(blend_weights, 0.);
      blend_weights /= (blend_weights.x + blend_weights.y + blend_weights.z);

      mat3 tsb = tangent_space_basis(blend_weights);
      vec3 bump = blended_bump(blend_weights);

      vec3 normalTex = bump * 2.0 - 1.0;
      normalTex.xy *= normalScale;
      normalTex.y *= -1.;
      normalTex = normalize(normalTex);
      vec3 finalNormal = tsb * normalTex;
      vec3 base = spherical_environment_map(vU, finalNormal);

      float rim = 1.75 * max(0., abs(dot(normalize(vNormal), normalize(-vOPosition.xyz))));
      base += 10. * base * color * clamp(1. - rim, 0., .15);

      base = vec3(1.) - (vec3(1.) - base) * (vec3(1.) - base);

      float dither = .05 * random(vec3(1.), length(gl_FragCoord));
      base += vec3(dither);

      gl_FragColor = vec4(base.rgb, 1.);
    }`,
  attributes: {
    position: {
      buffer: positionBuffer,
    },
    normal: {
      buffer: normalBuffer,
    }
  },
  uniforms: {
    color: [36 / 255.0, 70 / 255.0, 106 / 255.0],
    sphereColor: [36 / 255.0, 70 / 255.0, 106 / 255.0],
    normalScale: 1,
    texScale: 10,
    normalMatrix: (context) => {
      let a = mat3.create()
      mat3.normalFromMat4(a, context.view)
      return a
    },
    textureMap: regl.prop('textureMap'),
    normalMap: regl.prop('normalMap')
  },
  elements: cellsBuffer
})

const numblobs = 20
const strength = 1.2 / ((Math.sqrt(numblobs) - 1) / 4 + 1)
const subtract = 12
const size = 50
const bounds = [[0.5, 0.5, 0.5], [1.5, 1.5, 1.5]]
const position = (time, i) => {
  return [
    Math.sin(i + 1.26 * time * (1.03 + 0.5 * Math.cos(0.21 * i))) * 0.27 + 0.5,
    Math.cos(i + 1.12 * time * 0.21 * Math.sin((0.72 + 0.83 * i))) * 0.27 + 0.5,
    Math.cos(i + 1.32 * time * 0.1 * Math.sin((0.92 + 0.53 * i))) * 0.27 + 0.5
  ]
}
let start_bounds, end_bounds
[start_bounds, end_bounds] = bounds
const step_sizes = [0, 1, 2].map((i) => (end_bounds[i] - start_bounds[i]) / size)
const r = size * Math.sqrt(strength / subtract)

const render = (tick) => {
  let time = 0.5 * tick
  let fieldArray = new Float32Array(size * size * size)

  for (let n = 0; n < numblobs; n++) {
    let ballx, bally, ballz
    [ballx, bally, ballz] = position(time, n)
    let zs = ballz * size
    let ys = bally * size
    let xs = ballx * size

    let min_z = Math.floor(zs - r)
    if (min_z < 1) min_z = 1
    let max_z = Math.floor(zs + r)
    if (max_z > size - 1) max_z = size - 1
    let min_y = Math.floor(ys - r)
    if (min_y < 1) min_y = 1
    let max_y = Math.floor(ys + r)
    if (max_y > size - 1) max_y = size - 1
    let min_x = Math.floor(xs - r)
    if (min_x < 1) min_x = 1
    let max_x = Math.floor(xs + r)
    if (max_x > size - 1) max_x = size - 1

    for (let z = min_z; z < max_z; z++) {
      let z_offset = size * size * z

      for (let y = min_y; y < max_y; y++) {
        let y_offset = size * y

        for (let x = min_x; x < max_x; x++) {
          let fx = x / size - ballx
          let fy = y / size - bally
          let fz = z / size - ballz
          let val = strength / (0.000001 + (fx * fx) + (fy * fy) + (fz * fz)) - subtract
          if (val > 0.0) fieldArray[z_offset + y_offset + x] += val
        }
      }
    }
  }

  let mesh = surfaceNets(ndarray(fieldArray, [size, size, size]), 80.0)
  let coordinate_positions = mesh.positions.map((p) => {
    return p.map((index, i) => start_bounds[i] + (index * step_sizes[i]))
  })
  return {positions: coordinate_positions, cells: mesh.cells}
}

require('resl')({
  manifest: {
    sphereTexture: {
      type: 'image',
      src: 'spheretexture.jpg',
      parser: (data) => regl.texture({
        data: data,
        wrapT: 'clamp',
        wrapS: 'clamp',
        mag: 'linear',
        min: 'linear'
      })
    },
    normalTexture: {
      type: 'image',
      src: 'normaltexture.jpg',
      parser: (data) => regl.texture({
        data: data,
        wrapT: 'repeat',
        wrapS: 'repeat',
        min: 'linear mipmap linear',
        mag: 'linear'
      })
    }
  },
  onDone: ({sphereTexture, normalTexture}) => {
    regl.frame(({time}) => {
      let mesh = render(time)
      positionBuffer({data: mesh.positions})
      cellsBuffer({data: mesh.cells})
      normalBuffer({data: normals(mesh.cells, mesh.positions)})
      camera(() => {
        drawBackground({depth: {enable: false, mask: false}})
        regl.clear({depth: 1})
        drawMetaballs({
          textureMap: sphereTexture,
          normalMap: normalTexture
        })
      })
    })
  }
})
<commit_msg>Make bounds logic more readable.<commit_after>/*

Metaball rendering demo. Many ideas and code taken from here

 */

const regl = require('../regl')()
const surfaceNets = require('surface-nets')
const ndarray = require('ndarray')
const normals = require('angle-normals')
const mat3 = require('gl-mat3')
const camera = require('./util/camera')(regl, {
  distance: 1.5,
  maxDistance: 3,
  minDistance: 0.5,
  center: [1, 1, 1],
  theta: 1.0
})

const maxCount = 4096

const positionBuffer = regl.buffer({
  length: maxCount * 3 * 4,
  type: 'float',
  usage: 'dynamic'
})

const normalBuffer = regl.buffer({
  length: maxCount * 3 * 4,
  type: 'float',
  usage: 'dynamic'
})

const cellsBuffer = regl.elements({
  length: (maxCount*3* 3) * 3 * 2,
  count: (maxCount*3* 3),
  type: 'uint16',
  usage: 'dynamic',
  primitive: 'triangles',
})

const drawBackground = regl({
  vert: `
    precision mediump float;
    attribute vec2 position;
    void main() {
      gl_Position = vec4(position, 0., 1.);
    }`,
  frag: `
    precision mediump float;
    uniform vec3 color;
    uniform float noise, width, height;

    #define VIG_REDUCTION_POWER 1.
    #define VIG_BOOST 1.

    float random(vec3 scale,float seed) {
      return fract(sin(dot(gl_FragCoord.xyz+seed,scale))*43758.5453+seed);
    }

    void main () {
      vec2 resolution = vec2(width, height);
      vec2 center = resolution * 0.5;
      float vignette = distance( center, gl_FragCoord.xy ) / resolution.x;
      vignette = VIG_BOOST - vignette * VIG_REDUCTION_POWER;

      float n = noise * (.5 - random(vec3(1.), length(gl_FragCoord)));

      float v = .5 * length(vec2(gl_FragCoord.y / resolution.y, (1. - abs(.5 - gl_FragCoord.x / resolution.x))));
      vec3 base = color;
      base += vec3(pow(v, 2.));

      gl_FragColor = vec4(base * vec3(vignette) + vec3(n), 1.);
    }`,
  uniforms: {
    color: [36 / 255.0, 70 / 255.0, 106 / 255.0],
    width: regl.context('viewportWidth'),
    height: regl.context('viewportHeight'),
    noise: 0.05
  },
  attributes: {
    position: [-4, -4, 4, -4, 0, 4]
  },
  count: 3
})

const drawMetaballs = regl({
  vert: `
    precision mediump float;
    uniform mat4 projection, view;
    uniform mat3 normalMatrix;

    attribute vec3 position, normal;

    varying vec3 vNormal, vONormal, vU;
    varying vec4 vPosition, vOPosition;

    void main () {
      vNormal = normalMatrix * normal;
      vONormal = normal;
      vPosition = vec4(position, 1.0);
      vOPosition = view * vPosition;
      vU = normalize(vec3(vOPosition));
      gl_Position = projection * vOPosition;
    }`,
  frag: `
    precision mediump float;
    uniform sampler2D textureMap, normalMap;
    uniform float normalScale, texScale;
    uniform vec3 color, eye;

    varying vec3 vNormal, vONormal, vU;
    varying vec4 vPosition, vOPosition;

    float random(vec3 scale, float seed) {
      return fract(sin(dot(gl_FragCoord.xyz + seed,scale)) * 43758.5453 + seed);
    }

    vec3 spherical_environment_map(vec3 ray, vec3 normal) {
      vec3 r = reflect(normalize(ray), normalize(normal));
      float m = 2.0 * sqrt(r.x * r.x + r.y * r.y + (r.z + 1.0) * (r.z + 1.0));
      vec2 calculatedNormal = vec2(r.x / m + 0.5, r.y / m + 0.5);
      return texture2D(textureMap, calculatedNormal).rgb;
    }

    mat3 tangent_space_basis(vec3 blend_weights) {
      vec3 tanX = vec3(vNormal.x, -vNormal.z, vNormal.y);
      vec3 tanY = vec3(vNormal.z, vNormal.y, -vNormal.x);
      vec3 tanZ = vec3(-vNormal.y, vNormal.x, vNormal.z);
      vec3 blended_tangent = tanX * blend_weights.xxx +
                             tanY * blend_weights.yyy +
                             tanZ * blend_weights.zzz;

      return mat3(
        normalize(blended_tangent),
        normalize(cross(vNormal, blended_tangent)),
        normalize(vNormal)
      );
    }

    vec3 blended_bump(vec3 blend_weights) {
      vec2 coord1 = vPosition.yz * texScale;
      vec2 coord2 = vPosition.zx * texScale;
      vec2 coord3 = vPosition.xy * texScale;

      vec3 bump1 = texture2D(normalMap, coord1).rgb;
      vec3 bump2 = texture2D(normalMap, coord2).rgb;
      vec3 bump3 = texture2D(normalMap, coord3).rgb;

      return bump1 * blend_weights.xxx +
             bump2 * blend_weights.yyy +
             bump3 * blend_weights.zzz;
    }

    void main() {
      vec3 blend_weights = abs(normalize(vONormal.xyz));
      blend_weights = (blend_weights - 0.2) * 7.;
      blend_weights = max(blend_weights, 0.);
      blend_weights /= (blend_weights.x + blend_weights.y + blend_weights.z);

      mat3 tsb = tangent_space_basis(blend_weights);
      vec3 bump = blended_bump(blend_weights);

      vec3 normalTex = bump * 2.0 - 1.0;
      normalTex.xy *= normalScale;
      normalTex.y *= -1.;
      normalTex = normalize(normalTex);
      vec3 finalNormal = tsb * normalTex;
      vec3 base = spherical_environment_map(vU, finalNormal);

      float rim = 1.75 * max(0., abs(dot(normalize(vNormal), normalize(-vOPosition.xyz))));
      base += 10. * base * color * clamp(1. - rim, 0., .15);

      base = vec3(1.) - (vec3(1.) - base) * (vec3(1.) - base);

      float dither = .05 * random(vec3(1.), length(gl_FragCoord));
      base += vec3(dither);

      gl_FragColor = vec4(base.rgb, 1.);
    }`,
  attributes: {
    position: {
      buffer: positionBuffer,
    },
    normal: {
      buffer: normalBuffer,
    }
  },
  uniforms: {
    color: [36 / 255.0, 70 / 255.0, 106 / 255.0],
    sphereColor: [36 / 255.0, 70 / 255.0, 106 / 255.0],
    normalScale: 1,
    texScale: 10,
    normalMatrix: (context) => {
      let a = mat3.create()
      mat3.normalFromMat4(a, context.view)
      return a
    },
    textureMap: regl.prop('textureMap'),
    normalMap: regl.prop('normalMap')
  },
  elements: cellsBuffer
})

const numblobs = 20
const strength = 1.2 / ((Math.sqrt(numblobs) - 1) / 4 + 1)
const subtract = 12
const size = 50
const position = (time, i) => {
  return [
    Math.sin(i + 1.26 * time * (1.03 + 0.5 * Math.cos(0.21 * i))) * 0.27 + 0.5,
    Math.cos(i + 1.12 * time * 0.21 * Math.sin((0.72 + 0.83 * i))) * 0.27 + 0.5,
    Math.cos(i + 1.32 * time * 0.1 * Math.sin((0.92 + 0.53 * i))) * 0.27 + 0.5
  ]
}
const start_bounds = [0.5, 0.5, 0.5]
const end_bounds = [1.5, 1.5, 1.5]
const step_sizes = [0, 1, 2].map((i) => (end_bounds[i] - start_bounds[i]) / size)

// Outside the radius of influence, we assume field contribution of zero
const radius = size * Math.sqrt(strength / subtract)

const render = (tick) => {
  let time = 0.5 * tick
  let fieldArray = new Float32Array(size * size * size)

  for (let n = 0; n < numblobs; n++) {
    let ballx, bally, ballz, x_bounds, y_bounds, z_bounds, bounds
    [ballx, bally, ballz] = position(time, n)
    bounds = [ballx, bally, ballz].map((c) => {
      let coordCenter = c * size
      return [
        Math.max(Math.floor(coordCenter - radius), 1),
        Math.min(Math.floor(coordCenter + radius), size - 1)
      ]
    })
    x_bounds = bounds[0]
    y_bounds = bounds[1]
    z_bounds = bounds[2]

    for (let z = z_bounds[0]; z < z_bounds[1]; z++) {
      let z_offset = size * size * z

      for (let y = y_bounds[0]; y < y_bounds[1]; y++) {
        let y_offset = size * y

        for (let x = x_bounds[0]; x < x_bounds[1]; x++) {
          let fx = x / size - ballx
          let fy = y / size - bally
          let fz = z / size - ballz
          let val = strength / (0.000001 + (fx * fx) + (fy * fy) + (fz * fz)) - subtract
          if (val > 0.0) fieldArray[z_offset + y_offset + x] += val
        }
      }
    }
  }

  let mesh = surfaceNets(ndarray(fieldArray, [size, size, size]), 80.0)

  // Transform index coordinates to space coordinates
  let coordinate_positions = new Array(mesh.positions.length)
  for (let i = 0; i < mesh.positions.length; i++) {
    let position = mesh.positions[i]
    let transformed_position = new Array(3)
    for (let j = 0; j < 3; j++) {
      transformed_position[j] = start_bounds[j] + (position[j] * step_sizes[j])
    }
    coordinate_positions[i] = transformed_position
  }

  return {positions: coordinate_positions, cells: mesh.cells}
}

require('resl')({
  manifest: {
    sphereTexture: {
      type: 'image',
      src: 'spheretexture.jpg',
      parser: (data) => regl.texture({
        data: data,
        wrapT: 'clamp',
        wrapS: 'clamp',
        mag: 'linear',
        min: 'linear'
      })
    },
    normalTexture: {
      type: 'image',
      src: 'normaltexture.jpg',
      parser: (data) => regl.texture({
        data: data,
        wrapT: 'repeat',
        wrapS: 'repeat',
        min: 'linear mipmap linear',
        mag: 'linear'
      })
    }
  },
  onDone: ({sphereTexture, normalTexture}) => {
    regl.frame(({time}) => {
      let mesh = render(time)
      positionBuffer({data: mesh.positions})
      cellsBuffer({data: mesh.cells})
      normalBuffer({data: normals(mesh.cells, mesh.positions)})
      camera(() => {
        drawBackground({depth: {enable: false, mask: false}})
        regl.clear({depth: 1})
        drawMetaballs({
          textureMap: sphereTexture,
          normalMap: normalTexture
        })
      })
    })
  }
})
<|endoftext|>


<commit_before>export default {
  name: 'tabs',

  data () {
    return {
      activators: [],
      isActive: null,
      reverse: false,
      target: null,
      resizeDebounce: {},
      targetEl: null
    }
  },

  props: {
    centered: Boolean,
    grow: Boolean,
    icons: Boolean,
    scrollBars: Boolean,
    value: String
  },

  computed: {
    classes () {
      return {
        'tabs': true,
        'tabs--centered': this.centered,
        'tabs--grow': this.grow,
        'tabs--icons': this.icons,
        'tabs--scroll-bars': this.scrollBars
      }
    }
  },

  watch: {
    value () {
      this.tabClick(this.value)
    },
    isActive () {
      this.activators.forEach(i => {
        i.toggle(this.target)

        if (i.isActive) {
          this.slider(i.$el)
        }
      })

      this.$refs.content.$children.forEach(i => i.toggle(this.target, this.reverse))
      this.$emit('input', this.target)
    }
  },

  mounted () {
    this.$vuetify.load(() => {
      this.init()
      window.addEventListener('resize', this.resize, false)
    })
  },

  beforeDestroy () {
    window.removeEventListener('resize', this.resize, false)
  },

  methods: {
    init () {
      this.activators = this.$refs.activators.$children.filter(i => i.$options._componentTag === 'v-tab-item')
      setTimeout(() => {
        this.tabClick(this.value || this.activators[0].target)
      }, 200)
    },
    resize () {
      clearTimeout(this.resizeDebounce)

      this.resizeDebounce = setTimeout(() => {
        this.slider()
      }, 250)
    },
    slider (el) {
      this.targetEl = el || this.targetEl
      this.$refs.slider.style.width = `${this.targetEl.clientWidth}px`
      this.$refs.slider.style.left = `${this.targetEl.offsetLeft}px`
    },
    tabClick (target) {
      this.target = target

      if (!this.$refs.content) return
      this.$nextTick(() => {
        const nextIndex = this.$refs.content.$children.findIndex(i => i.id === this.target)
        this.reverse = nextIndex < this.isActive
        this.isActive = nextIndex
      })
    }
  },

  render (h) {
    const tabs = h('v-tabs-tabs', {
      ref: 'activators'
    }, [
      h('v-tabs-slider', { ref: 'slider' }),
      this.$slots.activators
    ])

    const items = h('v-tabs-items', {
      'class': 'tabs__items',
      ref: 'content'
    }, [this.$slots.content])

    return h('div', {
      'class': this.classes,
      domProps: { id: this.id }
    }, [this.$slots.default, tabs, items])
  }
}
<commit_msg>fix for #273<commit_after>export default {
  name: 'tabs',

  data () {
    return {
      activators: [],
      isActive: null,
      reverse: false,
      target: null,
      resizeDebounce: {},
      targetEl: null
    }
  },

  props: {
    centered: Boolean,
    grow: Boolean,
    icons: Boolean,
    scrollBars: Boolean,
    value: String
  },

  computed: {
    classes () {
      return {
        'tabs': true,
        'tabs--centered': this.centered,
        'tabs--grow': this.grow,
        'tabs--icons': this.icons,
        'tabs--scroll-bars': this.scrollBars
      }
    }
  },

  watch: {
    value () {
      this.tabClick(this.value)
    },
    isActive () {
      this.activators.forEach(i => {
        i.toggle(this.target)

        if (i.isActive) {
          this.slider(i.$el)
        }
      })

      this.$refs.content.$children.forEach(i => i.toggle(this.target, this.reverse))
      this.$emit('input', this.target)
    }
  },

  mounted () {
    this.$vuetify.load(() => {
      this.init()
      window.addEventListener('resize', this.resize, false)
    })
  },

  beforeDestroy () {
    window.removeEventListener('resize', this.resize, false)
  },

  methods: {
    init () {
      this.activators = this.$refs.activators.$children.filter(i => i.$options._componentTag === 'v-tab-item')
      setTimeout(() => {
        this.tabClick(this.value || this.activators[0].target)
      }, 200)
    },
    resize () {
      clearTimeout(this.resizeDebounce)

      this.resizeDebounce = setTimeout(() => {
        this.slider()
      }, 250)
    },
    slider (el) {
      this.targetEl = el || this.targetEl
      this.$refs.slider.style.width = `${this.targetEl.clientWidth}px`
      this.$refs.slider.style.left = `${this.targetEl.offsetLeft}px`
    },
    tabClick (target) {
      this.target = target

      if (!this.$refs.content) return
      this.$nextTick(() => {
        const nextIndex = this.$refs.content.$children.findIndex(i => i.id === this.target)
        this.reverse = nextIndex < this.isActive
        this.isActive = nextIndex
      })
    }
  },

  render (h) {
    const tabs = h('v-tabs-tabs', {
      ref: 'activators'
    }, [
      h('v-tabs-slider', { ref: 'slider' }),
      this.$slots.activators
    ])

    const items = h('v-tabs-items', {
      'class': 'tabs__items',
      ref: 'content'
    }, [this.$slots.content])

    return h('div', {
      'class': this.classes
    }, [this.$slots.default, tabs, items])
  }
}
<|endoftext|>


<commit_before>require.config({
  paths: {
    jquery: 'lib/jquery/jquery',
    text: 'lib/requirejs-text/text',
    base64: 'lib/base64/base64.min',
    hogan: 'lib/hogan/web/builds/2.0.0/hogan-2.0.0.amd',
    hgn: 'lib/requirejs-hogan-plugin/hgn',
    json: 'lib/requirejs-plugins/src/json',
    jasmine: 'lib/jasmine/lib/jasmine-core/jasmine',
    'jasmine-html': 'lib/jasmine/lib/jasmine-core/jasmine-html',
    'jasmine-jquery': 'lib/jasmine-jquery/lib/jasmine-jquery',
    'event-emitter': 'lib/event-emitter/src/event-emitter',
    inherits: 'lib/inherits/inherits',
    blanket: 'lib/blanket/dist/qunit/blanket',
    'blanket-jasmine': 'lib/blanket/dist/jasmine/blanket_jasmine',
    debug: 'lib/debug/debug'
  },
  packages: [{
    name: "auth",
    location: "lib/auth/src",
    main: "auth"
  },{
    name: "livefyre-bootstrap",
    location: "lib/livefyre-bootstrap/src"
  },{
    name: "streamhub-ui",
    location: "src"
  },{
    name: "view",
    location: "lib/view/src",
    main: "view"
  }],
  shim: {
    jquery: {
        exports: '$'
    },
    jasmine: {
        exports: 'jasmine'
    },
    'jasmine-html': {
        deps: ['jasmine'],
        exports: 'jasmine'
    },
    'blanket-jasmine': {
        exports: 'blanket',
        deps: ['jasmine']
    },
    'jasmine-jquery': {
        deps: ['jquery']
    }
  }
});
<commit_msg>Remove unused paths from requirejs.conf<commit_after>require.config({
  paths: {
    jquery: 'lib/jquery/jquery',
    hogan: 'lib/hogan/web/builds/2.0.0/hogan-2.0.0.amd',
    hgn: 'lib/requirejs-hogan-plugin/hgn',
    jasmine: 'lib/jasmine/lib/jasmine-core/jasmine',
    'jasmine-html': 'lib/jasmine/lib/jasmine-core/jasmine-html',
    'jasmine-jquery': 'lib/jasmine-jquery/lib/jasmine-jquery',
    'event-emitter': 'lib/event-emitter/src/event-emitter',
    inherits: 'lib/inherits/inherits',
    blanket: 'lib/blanket/dist/qunit/blanket',
    'blanket-jasmine': 'lib/blanket/dist/jasmine/blanket_jasmine',
    debug: 'lib/debug/debug'
  },
  packages: [{
    name: "auth",
    location: "lib/auth/src",
    main: "auth"
  },{
    name: "livefyre-bootstrap",
    location: "lib/livefyre-bootstrap/src"
  },{
    name: "streamhub-ui",
    location: "src"
  },{
    name: "view",
    location: "lib/view/src",
    main: "view"
  }],
  shim: {
    jquery: {
        exports: '$'
    },
    jasmine: {
        exports: 'jasmine'
    },
    'jasmine-html': {
        deps: ['jasmine'],
        exports: 'jasmine'
    },
    'blanket-jasmine': {
        exports: 'blanket',
        deps: ['jasmine']
    },
    'jasmine-jquery': {
        deps: ['jquery']
    }
  }
});
<|endoftext|>


<commit_before>(function(){
	var B={};

	var setAttribute='setAttribute';
	var getAttribute='getAttribute';

	var ex=function(v){return v!=null && v!=undefined;};
	B.exists=ex;

	var $id=function(id){
		if(typeof id=="string" && id!='')
			return document.getElementById(id);
		else if(id==='' || !ex(id))
			return null;
		else
			return id;
	};
	B.$id=$id;

	var cattr=document.all?'className':'class';
	function classRegex(c){return new RegExp('(?:\\s|^)'+c+'(?:\\s|$)');}

	B.hasClass=function(i,c){
		i=$id(i);
		if(!ex(i) || !i[getAttribute](cattr))
			return false;
		return i[getAttribute](cattr).match(classRegex(c));
	};
	B.addClass=function(i,c){
		i=$id(i);
		if(!B.hasClass(i,c)){
			var cn=i[getAttribute](cattr)||'';
			i[setAttribute](cattr,cn+' '+c);
		}
	};
	B.removeClass=function(i,c){
		i=$id(i);
		if(ex(i) && B.hasClass(i,c)){
			var cn=i[getAttribute](cattr).replace(classRegex(c),' ');
			i[setAttribute](cattr,cn);
		}
	};
	B.replaceClass=function(i,cO,cN,app){
		i=$id(i);
		if(ex(i)){
			var cn=i[getAttribute](cattr);
			if(B.hasClass(i,cO)) {
				cn=cn.replace(classRegex(cO),' '+cN+' ');
				i[setAttribute](cattr,cn);
			}else if(app)
				B.addClass(i, cN);
		}
	};
	B.setClass = function(i,c){
		i=$id(i);
		ex(i) && i[setAttribute](cattr,c);
	};

	B.create=function(n,att,p){
		var e;
		var appendChild = 'appendChild';
		if(n=='text')
			e=document.createTextNode(att['value']);
		else{
			e=document.createElement(n);
			for(var k in att){
				switch(k){
				default:
					e[setAttribute](k, att[k]);
					break;
				case 'id':
					if($id(att[k])==null || $id(att[k])==undefined)
						e[setAttribute]('id',att[k]);
					break;
				case 'style':
				case 'cssText':
					// doesn't seem to work with IE
					e[setAttribute]('cssText',att[k]);
					e[setAttribute]('style',att[k]);
					break;
				case 'class':
				case 'className':
					B.setClass(e,att[k]);
					break;
				case 'text':
					e[appendChild](document.createTextNode(att[k]));
					break;
				}
			}
		}
		//if the parent is given, the created node will be put in it
		if(ex($id(p)) || p && ex($id(p.element))){
			if(!ex(p.element)) $id(p)[appendChild](e);
			else{
				//if the elem has to be inserted before an element
				if(ex($id(p.before))) $id(p.element).insertBefore(e, $id(p.before));
				//else if it has to be inserted after an element
				else if(ex($id(p.after)) && ex($id(p.after).nextSibling)) $id(p.element).insertBefore($id(p.after).nextSibling);
				//else append
				else $id(p.element)[appendChild](e);
			}
		}
		return e;
	};

	B.addEvent=function(item,event,action,opt,args){
		opt=opt||{};
		args=args||new Array();
		item=$id(item);
		item[event+action]=function(evt){
			var scope=$id('scope' in opt?opt['scope']:window);
			if(!opt['skipEvent']) action.apply(scope,args.concat([evt]));
			else action.apply(scope,args);
		};

		if(item.attachEvent) item.attachEvent('on'+event,item[event+action]);
		else if(item.addEventListener) item.addEventListener(event,item[event+action],opt['propagate'] == true);
	};

	B.removeEvent=function(item,event,action,opt,args){
		opt=opt||{};
		args=args||new Array();
		item=$id(item);
		if(item.detachEvent) item.detachEvent('on'+event,item[event+action]);
		else if(item.removeEventListener) item.removeEventListener(event,item[event+action],opt['propagate'] == true);
		delete item[event+action];
	};

	B.appendChildren=function(i,c){
		var lC=c.length;
		i=$id(i);
		for(var k=0;k<lC;k++)
			i[appendChild](c[i]);
	};

	B.getStyle=function(i,s){
		if(i.currentStyle){
			s=s.replace(/\-(\w)/g,function(m,p1){return p1.toUpperCase();});
			var y=i.currentStyle[s];
		}else if(window.getComputedStyle){
			s=s.replace(/([A-Z])/g,function(p1){return "-"+p1.toLowerCase();});
			var y=document.defaultView.getComputedStyle(i,null).getPropertyValue(s);
		}
		return y;
	};

	B.getStyleValue=function(i,s){
		return B.getStyle(i, s).replace(new RegExp('(px|pt|em)$'),'');
	};

	function indexOf(v){
		for(var k in this)
			if(this[k]==v) return k;
		return -1;
	}

	Object.prototype.indexOf = Object.prototype.indexOf || indexOf;
	Array.prototype.indexOf = Array.prototype.indexOf || indexOf;

	function bind(obj){
		var s=Array.prototype.slice;
		args=s.call(arguments, 1);
		var self=this;
		var n=function(){};
		bound=function(){
			return self.apply(
				this instanceof n ? this : ( obj || {} ),
				args.concat(s.call(arguments))
			);
		};
		n.prototype=self.prototype;
		bound.prototype=new n();
		return bound;
	}
	Function.prototype.bind = Function.prototype.bind || bind;

	window['B']=B;
})();
<commit_msg>B.getStyleValue simplified and generalized<commit_after>(function(){
	var B={};

	var setAttribute='setAttribute';
	var getAttribute='getAttribute';

	var ex=function(v){return v!=null && v!=undefined;};
	B.exists=ex;

	var $id=function(id){
		if(typeof id=="string" && id!='')
			return document.getElementById(id);
		else if(id==='' || !ex(id))
			return null;
		else
			return id;
	};
	B.$id=$id;

	var cattr=document.all?'className':'class';
	function classRegex(c){return new RegExp('(?:\\s|^)'+c+'(?:\\s|$)');}

	B.hasClass=function(i,c){
		i=$id(i);
		if(!ex(i) || !i[getAttribute](cattr))
			return false;
		return i[getAttribute](cattr).match(classRegex(c));
	};
	B.addClass=function(i,c){
		i=$id(i);
		if(!B.hasClass(i,c)){
			var cn=i[getAttribute](cattr)||'';
			i[setAttribute](cattr,cn+' '+c);
		}
	};
	B.removeClass=function(i,c){
		i=$id(i);
		if(ex(i) && B.hasClass(i,c)){
			var cn=i[getAttribute](cattr).replace(classRegex(c),' ');
			i[setAttribute](cattr,cn);
		}
	};
	B.replaceClass=function(i,cO,cN,app){
		i=$id(i);
		if(ex(i)){
			var cn=i[getAttribute](cattr);
			if(B.hasClass(i,cO)) {
				cn=cn.replace(classRegex(cO),' '+cN+' ');
				i[setAttribute](cattr,cn);
			}else if(app)
				B.addClass(i, cN);
		}
	};
	B.setClass = function(i,c){
		i=$id(i);
		ex(i) && i[setAttribute](cattr,c);
	};

	B.create=function(n,att,p){
		var e;
		var appendChild = 'appendChild';
		if(n=='text')
			e=document.createTextNode(att['value']);
		else{
			e=document.createElement(n);
			for(var k in att){
				switch(k){
				default:
					e[setAttribute](k, att[k]);
					break;
				case 'id':
					if($id(att[k])==null || $id(att[k])==undefined)
						e[setAttribute]('id',att[k]);
					break;
				case 'style':
				case 'cssText':
					// doesn't seem to work with IE
					e[setAttribute]('cssText',att[k]);
					e[setAttribute]('style',att[k]);
					break;
				case 'class':
				case 'className':
					B.setClass(e,att[k]);
					break;
				case 'text':
					e[appendChild](document.createTextNode(att[k]));
					break;
				}
			}
		}
		//if the parent is given, the created node will be put in it
		if(ex($id(p)) || p && ex($id(p.element))){
			if(!ex(p.element)) $id(p)[appendChild](e);
			else{
				//if the elem has to be inserted before an element
				if(ex($id(p.before))) $id(p.element).insertBefore(e, $id(p.before));
				//else if it has to be inserted after an element
				else if(ex($id(p.after)) && ex($id(p.after).nextSibling)) $id(p.element).insertBefore($id(p.after).nextSibling);
				//else append
				else $id(p.element)[appendChild](e);
			}
		}
		return e;
	};

	B.addEvent=function(item,event,action,opt,args){
		opt=opt||{};
		args=args||new Array();
		item=$id(item);
		item[event+action]=function(evt){
			var scope=$id('scope' in opt?opt['scope']:window);
			if(!opt['skipEvent']) action.apply(scope,args.concat([evt]));
			else action.apply(scope,args);
		};

		if(item.attachEvent) item.attachEvent('on'+event,item[event+action]);
		else if(item.addEventListener) item.addEventListener(event,item[event+action],opt['propagate'] == true);
	};

	B.removeEvent=function(item,event,action,opt,args){
		opt=opt||{};
		args=args||new Array();
		item=$id(item);
		if(item.detachEvent) item.detachEvent('on'+event,item[event+action]);
		else if(item.removeEventListener) item.removeEventListener(event,item[event+action],opt['propagate'] == true);
		delete item[event+action];
	};

	B.appendChildren=function(i,c){
		var lC=c.length;
		i=$id(i);
		for(var k=0;k<lC;k++)
			i[appendChild](c[i]);
	};

	B.getStyle=function(i,s){
		if(i.currentStyle){
			s=s.replace(/\-(\w)/g,function(m,p1){return p1.toUpperCase();});
			var y=i.currentStyle[s];
		}else if(window.getComputedStyle){
			s=s.replace(/([A-Z])/g,function(p1){return "-"+p1.toLowerCase();});
			var y=document.defaultView.getComputedStyle(i,null).getPropertyValue(s);
		}
		return y;
	};

	B.getStyleValue=function(i,s){
		var v=B.getStyle(i, s);
		return isNaN(parseFloat(v))?0:v;
	};

	function indexOf(v){
		for(var k in this)
			if(this[k]==v) return k;
		return -1;
	}

	Object.prototype.indexOf = Object.prototype.indexOf || indexOf;
	Array.prototype.indexOf = Array.prototype.indexOf || indexOf;

	function bind(obj){
		var s=Array.prototype.slice;
		args=s.call(arguments, 1);
		var self=this;
		var n=function(){};
		bound=function(){
			return self.apply(
				this instanceof n ? this : ( obj || {} ),
				args.concat(s.call(arguments))
			);
		};
		n.prototype=self.prototype;
		bound.prototype=new n();
		return bound;
	}
	Function.prototype.bind = Function.prototype.bind || bind;

	window['B']=B;
})();
<|endoftext|>