<commit_before>import test from 'tape'
import FetchMock from 'fetch-mock'
import bigi from 'bigi'

import { network } from '../../../lib'

const mynet = new network.BlockstackNetwork(
  'https://core.blockstack.org',
  'https://broadcast.blockstack.org',
  new network.BlockchainInfoApi()
)

const testAddresses = [
  {
    skHex: '85b33fdfa5efeca980806c6ad3c8a55d67a850bd987237e7d49c967566346fbd01',
    address: '1br553PVnK6F5nyBtb4ju1owwBKdsep5c'
  },
  {
    skHex: '744196d67ed78fe39009c71fbfd53e6ecca98353fbfe81ccba21b0703a69be9c01',
    address: '16xVjkJ3nY62B9t9q3N9wY6hx1duAfwRZR'
  },
  {
    address: '1HEjCcUjZXtbiDnCYviHLVZvSQsSZoDRFa',
    skHex: '12f90d1b9e34d8df56f0dc6754a97ab4a2eb962918c281b1b552162438e313c001'
  },
  {
    address: '16TaQJi78o4A3nKDSzswqZiX3bhecNuNBQ',
    skHex: '58f7b29ee4a9a8b05855591b8a5405a0647c74c0a539515173adb9a32c964a9a01'
  },
  {
    address: '15eNSvgT3UFvHSonajxFswnmHFifJPE5LB',
    skHex: 'f5360140d18c6a34fbd2c45b98c1857c3fdad5454350249688a90efe936d475101'
  },
  {
    address: '1Lt8ajRt7i8ajkQsYQZbk3ULCVTsSn2TNV',
    skHex: '6eaed28d7f26f57fac925283aa0fe49c031028212863219f1c0141e4b0de2b2d01'
  },
  {
    address: '1GvM4xksXrQsq4xPRck11toRLXVq9UYj2B',
    skHex: '4c103c5c3de544c90f18a3ed29aaeebd33feedb1bb4f026df24aa3eddae826aa01'
  }
]

export function runNetworkTests() {
  test('prices-v1', (t) => {
    t.plan(2)
    FetchMock.restore()
    FetchMock.get('https://core.blockstack.org/v2/prices/names/test.id', 404)
    FetchMock.get('https://core.blockstack.org/v2/prices/namespaces/id', 404)
    FetchMock.get('https://core.blockstack.org/v1/prices/names/test.id',
                  { name_price: { btc: 0.0001, satoshis: 1000 } })
    FetchMock.get('https://core.blockstack.org/v1/prices/namespaces/id', { satoshis: 650000 })

    mynet.getNamePrice('test.id')
      .then(response => t.deepEqual(
        response, { units: 'BTC', amount: bigi.fromByteArrayUnsigned('5500') }))

    mynet.getNamespacePrice('id')
      .then(response => t.deepEqual(
        response, { units: 'BTC', amount: bigi.fromByteArrayUnsigned('650000') }))
  })

  test('prices-v2', (t) => {
    t.plan(3)
    FetchMock.restore()
    FetchMock.get('https://core.blockstack.org/v1/prices/names/test.id', 404)
    FetchMock.get('https://core.blockstack.org/v1/prices/names/test-tokens.id', 404)
    FetchMock.get('https://core.blockstack.org/v1/prices/namespaces/id', 404)
    FetchMock.get('https://core.blockstack.org/v2/prices/names/test.id',
                  { name_price: { units: 'BTC', amount: '1000' } })
    FetchMock.get('https://core.blockstack.org/v2/prices/names/test-tokens.id',
                  { name_price: { units: 'STACKS', amount: '1733000' } })
    FetchMock.get('https://core.blockstack.org/v2/prices/namespaces/id',
                  { units: 'BTC', amount: '650000' })

    mynet.getNamePrice('test.id')
      .then(response => t.deepEqual(
        response, { units: 'BTC', amount: bigi.fromByteArrayUnsigned('5500') }))

    mynet.getNamePrice('test-tokens.id')
      .then(response => t.deepEqual(
        response, { units: 'STACKS', amount: bigi.fromByteArrayUnsigned('1733000') }))

    mynet.getNamespacePrice('id')
      .then(response => t.deepEqual(
        response, { units: 'BTC', amount: bigi.fromByteArrayUnsigned('650000') }))
  })

  test('accounts', (t) => {
    t.plan(10)
    FetchMock.restore()
    const addr = testAddresses[0].address
    const addr2 = testAddresses[1].address
    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr}/tokens`, ['STACKS'])
    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr2}/tokens`, 404)

    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr}/STACKS/balance`,
                  { balance: '69129' })
    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr2}/NOPE/balance`, 404)

    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr}/STACKS/status`,
                  { address: addr, credit_value: '123450', debit_value: '54321' })
    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr2}/STACKS/status`, 404)

    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr}/history?page=0`,
                  [{ address: addr, credit_value: '123450', debit_value: '54321' }])
    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr2}/history?page=0`, 404)

    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr}/history/567890`,
                  [{ address: addr, credit_value: '123450', debit_value: '54321' }])
    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr2}/history/567890`, 404)

    mynet.getAccountTokens(addr)
      .then(response => t.deepEqual(response, ['STACKS']))
    mynet.getAccountTokens(addr2)
      .then(() => t.fail('did not get exception when querying tokens of unknown address'))
      .catch(e => t.equal(e.message, 'Account not found'))

    mynet.getAccountBalance(addr, 'STACKS')
      .then(response => t.deepEqual(response, bigi.fromByteArrayUnsigned('69129')))
    mynet.getAccountBalance(addr2, 'NOPE')
      .then(response => t.deepEqual(response, bigi.fromByteArrayUnsigned('0')))

    mynet.getAccountStatus(addr, 'STACKS')
      .then(response => t.deepEqual(response,
                                    {
                                      address: addr,
                                      credit_value: bigi.fromByteArrayUnsigned('123450'),
                                      debit_value: bigi.fromByteArrayUnsigned('54321')
                                    }))
    mynet.getAccountStatus(addr2, 'STACKS')
      .then(() => t.fail('did not get exception when querying status of unknown address'))
      .catch(e => t.equal(e.message, 'Account not found'))

    mynet.getAccountHistoryPage(addr, 0)
      .then(response => t.deepEqual(response,
                                    [{
                                      address: addr,
                                      credit_value: bigi.fromByteArrayUnsigned('123450'),
                                      debit_value: bigi.fromByteArrayUnsigned('54321')
                                    }]))
    mynet.getAccountHistoryPage(addr2, 0)
      .then(() => t.fail('did not get exception when querying history of unknown address'))
      .catch(e => t.equal(e.message, 'Account not found'))

    mynet.getAccountAt(addr, 567890)
      .then(response => t.deepEqual(response,
                                    [{
                                      address: addr,
                                      credit_value: bigi.fromByteArrayUnsigned('123450'),
                                      debit_value: bigi.fromByteArrayUnsigned('54321')
                                    }]))
    mynet.getAccountAt(addr2, 567890)
      .then(() => t.fail('did not get exception when querying block txs of unknown address'))
      .catch(e => t.equal(e.message, 'Account not found'))
  })
}
<commit_msg>test getzonefile<commit_after>import test from 'tape'
import FetchMock from 'fetch-mock'
import bigi from 'bigi'

import { network } from '../../../lib'

const mynet = new network.BlockstackNetwork(
  'https://core.blockstack.org',
  'https://broadcast.blockstack.org',
  new network.BlockchainInfoApi()
)

const testAddresses = [
  {
    skHex: '85b33fdfa5efeca980806c6ad3c8a55d67a850bd987237e7d49c967566346fbd01',
    address: '1br553PVnK6F5nyBtb4ju1owwBKdsep5c'
  },
  {
    skHex: '744196d67ed78fe39009c71fbfd53e6ecca98353fbfe81ccba21b0703a69be9c01',
    address: '16xVjkJ3nY62B9t9q3N9wY6hx1duAfwRZR'
  },
  {
    address: '1HEjCcUjZXtbiDnCYviHLVZvSQsSZoDRFa',
    skHex: '12f90d1b9e34d8df56f0dc6754a97ab4a2eb962918c281b1b552162438e313c001'
  },
  {
    address: '16TaQJi78o4A3nKDSzswqZiX3bhecNuNBQ',
    skHex: '58f7b29ee4a9a8b05855591b8a5405a0647c74c0a539515173adb9a32c964a9a01'
  },
  {
    address: '15eNSvgT3UFvHSonajxFswnmHFifJPE5LB',
    skHex: 'f5360140d18c6a34fbd2c45b98c1857c3fdad5454350249688a90efe936d475101'
  },
  {
    address: '1Lt8ajRt7i8ajkQsYQZbk3ULCVTsSn2TNV',
    skHex: '6eaed28d7f26f57fac925283aa0fe49c031028212863219f1c0141e4b0de2b2d01'
  },
  {
    address: '1GvM4xksXrQsq4xPRck11toRLXVq9UYj2B',
    skHex: '4c103c5c3de544c90f18a3ed29aaeebd33feedb1bb4f026df24aa3eddae826aa01'
  }
]

export function runNetworkTests() {
  test('prices-v1', (t) => {
    t.plan(2)
    FetchMock.restore()
    FetchMock.get('https://core.blockstack.org/v2/prices/names/test.id', 404)
    FetchMock.get('https://core.blockstack.org/v2/prices/namespaces/id', 404)
    FetchMock.get('https://core.blockstack.org/v1/prices/names/test.id',
                  { name_price: { btc: 0.0001, satoshis: 1000 } })
    FetchMock.get('https://core.blockstack.org/v1/prices/namespaces/id', { satoshis: 650000 })

    mynet.getNamePrice('test.id')
      .then(response => t.deepEqual(
        response, { units: 'BTC', amount: bigi.fromByteArrayUnsigned('5500') }))

    mynet.getNamespacePrice('id')
      .then(response => t.deepEqual(
        response, { units: 'BTC', amount: bigi.fromByteArrayUnsigned('650000') }))
  })

  test('prices-v2', (t) => {
    t.plan(3)
    FetchMock.restore()
    FetchMock.get('https://core.blockstack.org/v1/prices/names/test.id', 404)
    FetchMock.get('https://core.blockstack.org/v1/prices/names/test-tokens.id', 404)
    FetchMock.get('https://core.blockstack.org/v1/prices/namespaces/id', 404)
    FetchMock.get('https://core.blockstack.org/v2/prices/names/test.id',
                  { name_price: { units: 'BTC', amount: '1000' } })
    FetchMock.get('https://core.blockstack.org/v2/prices/names/test-tokens.id',
                  { name_price: { units: 'STACKS', amount: '1733000' } })
    FetchMock.get('https://core.blockstack.org/v2/prices/namespaces/id',
                  { units: 'BTC', amount: '650000' })

    mynet.getNamePrice('test.id')
      .then(response => t.deepEqual(
        response, { units: 'BTC', amount: bigi.fromByteArrayUnsigned('5500') }))

    mynet.getNamePrice('test-tokens.id')
      .then(response => t.deepEqual(
        response, { units: 'STACKS', amount: bigi.fromByteArrayUnsigned('1733000') }))

    mynet.getNamespacePrice('id')
      .then(response => t.deepEqual(
        response, { units: 'BTC', amount: bigi.fromByteArrayUnsigned('650000') }))
  })

  test('accounts', (t) => {
    t.plan(10)
    FetchMock.restore()
    const addr = testAddresses[0].address
    const addr2 = testAddresses[1].address
    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr}/tokens`, ['STACKS'])
    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr2}/tokens`, 404)

    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr}/STACKS/balance`,
                  { balance: '69129' })
    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr2}/NOPE/balance`, 404)

    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr}/STACKS/status`,
                  { address: addr, credit_value: '123450', debit_value: '54321' })
    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr2}/STACKS/status`, 404)

    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr}/history?page=0`,
                  [{ address: addr, credit_value: '123450', debit_value: '54321' }])
    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr2}/history?page=0`, 404)

    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr}/history/567890`,
                  [{ address: addr, credit_value: '123450', debit_value: '54321' }])
    FetchMock.get(`https://core.blockstack.org/v1/accounts/${addr2}/history/567890`, 404)

    mynet.getAccountTokens(addr)
      .then(response => t.deepEqual(response, ['STACKS']))
    mynet.getAccountTokens(addr2)
      .then(() => t.fail('did not get exception when querying tokens of unknown address'))
      .catch(e => t.equal(e.message, 'Account not found'))

    mynet.getAccountBalance(addr, 'STACKS')
      .then(response => t.deepEqual(response, bigi.fromByteArrayUnsigned('69129')))
    mynet.getAccountBalance(addr2, 'NOPE')
      .then(response => t.deepEqual(response, bigi.fromByteArrayUnsigned('0')))

    mynet.getAccountStatus(addr, 'STACKS')
      .then(response => t.deepEqual(response,
                                    {
                                      address: addr,
                                      credit_value: bigi.fromByteArrayUnsigned('123450'),
                                      debit_value: bigi.fromByteArrayUnsigned('54321')
                                    }))
    mynet.getAccountStatus(addr2, 'STACKS')
      .then(() => t.fail('did not get exception when querying status of unknown address'))
      .catch(e => t.equal(e.message, 'Account not found'))

    mynet.getAccountHistoryPage(addr, 0)
      .then(response => t.deepEqual(response,
                                    [{
                                      address: addr,
                                      credit_value: bigi.fromByteArrayUnsigned('123450'),
                                      debit_value: bigi.fromByteArrayUnsigned('54321')
                                    }]))
    mynet.getAccountHistoryPage(addr2, 0)
      .then(() => t.fail('did not get exception when querying history of unknown address'))
      .catch(e => t.equal(e.message, 'Account not found'))

    mynet.getAccountAt(addr, 567890)
      .then(response => t.deepEqual(response,
                                    [{
                                      address: addr,
                                      credit_value: bigi.fromByteArrayUnsigned('123450'),
                                      debit_value: bigi.fromByteArrayUnsigned('54321')
                                    }]))
    mynet.getAccountAt(addr2, 567890)
      .then(() => t.fail('did not get exception when querying block txs of unknown address'))
      .catch(e => t.equal(e.message, 'Account not found'))
  })

  test('zonefiles', (t) => {
    t.plan(2)
    FetchMock.restore()
    const zf = '$ORIGIN judecn.id\n$TTL 3600\n_https._tcp URI 10 1 '
      + '"https://raw.githubusercontent.com/jcnelson/profile/master/judecn.id"\n_https._tcp URI '
      + '10 1 "https://www.cs.princeton.edu/~jcnelson/judecn.id"\n'
    const zfh = '737c631c7c5d911c6617993c21fba731363f1cfe'
    const zfh2 = '737c631c7c5d911c6617993c21fba731363f1cff'

    FetchMock.get(`https://core.blockstack.org/v1/zonefiles/${zfh}`, zf)
    FetchMock.get(`https://core.blockstack.org/v1/zonefiles/${zfh2}`, zf)

    mynet.getZonefile(zfh)
      .then(response => t.equal(response, zf))

    mynet.getZonefile(zfh2)
      .catch(e => t.equal(e.message, `Zone file contents hash to ${zfh}, not ${zfh2}`))
  })
}
<|endoftext|>


<commit_before>/*global jQuery:true*/

'use strict';

require('angular');
require('angular-mocks');

describe('Directive: Code Descriptions', function () {

    beforeEach(angular.mock.module('hmdaPilotApp'));

    var element,
        scope,
        $el,
        HMDAEngine,
        ngDialog,
        mockFileSpec = {
            transmittalSheet: {
                recordID: {
                    label: 'Record Identifier',
                    validation: {
                        type: 'number',
                        canBeBlank: false,
                        canBeNA: false
                    }
                },
                respondentID: {
                    label: 'Respondent-ID',
                    validation: {
                        type: 'string',
                        canBeBlank: false,
                        canBeNA: false
                    }
                },
                agencyCode: {
                    label: 'Agency Code',
                    validation: {
                        type: 'number',
                        values: {
                            '1': 'OCC',
                            '2': 'FRS',
                            '3': 'FDIC',
                            '5': 'NCUA',
                            '7': 'HUD',
                            '9': 'CFPB'
                        }
                    }
                }
            },
            loanApplicationRegister: {
                loanType: {
                    label: 'Loan Type',
                    validation: {
                        type: 'number',
                        values: {
                            '1': 'Conventional (any loan other than FHA, VA, FSA, or RHS loans)',
                            '2': 'FHA-insured (Federal Housing Administration)',
                            '3': 'VA-guaranteed (Veterans Administration)',
                            '4': 'FSA/RHS (Farm Service Agency or Rural Housing Service)'
                         }
                     }
                }
            }
        };

    beforeEach(inject(function(_HMDAEngine_, _ngDialog_) {
        HMDAEngine = _HMDAEngine_;
        HMDAEngine.getFileSpec = function() { return mockFileSpec; };
        HMDAEngine.getRuleYear = function() { return '2013'; };
        ngDialog = _ngDialog_;
        spyOn(ngDialog, 'open');
    }));

    beforeEach(inject(function($templateCache) {
        var directiveTemplate = null;
        var templateId = 'partials/codeDescriptions.html';
        var req = new XMLHttpRequest();
        req.onload = function() {
            directiveTemplate = this.responseText;
        };
        req.open('get', '/base/app/'+templateId, false);
        req.send();
        $templateCache.put(templateId, directiveTemplate);
    }));

    beforeEach(inject(function ($rootScope, $compile) {
        scope = $rootScope.$new();
        element = angular.element('<code-descriptions></code-descriptions>');
        element = $compile(element)(scope);
        scope.$digest();
        $el = jQuery(element);
    }));

    describe('template', function() {
        it('should display a button to open the modal', function() {
            var $btn = $el.find('button');
            expect($btn).not.toBeNull();
            $btn.click();
            expect(ngDialog.open).toHaveBeenCalled();
        });
    });

    describe('open', function() {
        it('should display a definition list', function() {
            $el.find('button').click();
            expect($el.find('dl')).toBeDefined();
        });
    });
});
<commit_msg>punt on trying to get the modal element<commit_after>/*global jQuery:true*/

'use strict';

require('angular');
require('angular-mocks');

describe('Directive: Code Descriptions', function () {

    beforeEach(angular.mock.module('hmdaPilotApp'));

    var element,
        scope,
        $el,
        HMDAEngine,
        ngDialog,
        mockFileSpec = {
            transmittalSheet: {
                recordID: {
                    label: 'Record Identifier',
                    validation: {
                        type: 'number',
                        canBeBlank: false,
                        canBeNA: false
                    }
                },
                respondentID: {
                    label: 'Respondent-ID',
                    validation: {
                        type: 'string',
                        canBeBlank: false,
                        canBeNA: false
                    }
                },
                agencyCode: {
                    label: 'Agency Code',
                    validation: {
                        type: 'number',
                        values: {
                            '1': 'OCC',
                            '2': 'FRS',
                            '3': 'FDIC',
                            '5': 'NCUA',
                            '7': 'HUD',
                            '9': 'CFPB'
                        }
                    }
                }
            },
            loanApplicationRegister: {
                loanType: {
                    label: 'Loan Type',
                    validation: {
                        type: 'number',
                        values: {
                            '1': 'Conventional (any loan other than FHA, VA, FSA, or RHS loans)',
                            '2': 'FHA-insured (Federal Housing Administration)',
                            '3': 'VA-guaranteed (Veterans Administration)',
                            '4': 'FSA/RHS (Farm Service Agency or Rural Housing Service)'
                         }
                     }
                }
            }
        };

    beforeEach(inject(function(_HMDAEngine_, _ngDialog_) {
        HMDAEngine = _HMDAEngine_;
        HMDAEngine.getFileSpec = function() { return mockFileSpec; };
        HMDAEngine.getRuleYear = function() { return '2013'; };
        ngDialog = _ngDialog_;
        spyOn(ngDialog, 'open');
    }));

    beforeEach(inject(function($templateCache) {
        var directiveTemplate = null;
        var templateId = 'partials/codeDescriptions.html';
        var req = new XMLHttpRequest();
        req.onload = function() {
            directiveTemplate = this.responseText;
        };
        req.open('get', '/base/app/'+templateId, false);
        req.send();
        $templateCache.put(templateId, directiveTemplate);
    }));

    beforeEach(inject(function ($rootScope, $compile) {
        scope = $rootScope.$new();
        element = angular.element('<code-descriptions></code-descriptions>');
        element = $compile(element)(scope);
        scope.$digest();
        $el = jQuery(element);
    }));

    describe('template', function() {
        it('should display a button to open the modal', function() {
            var $btn = $el.find('button');
            expect($btn.length).toBeGreaterThan(0);
            $btn.click();
            expect(ngDialog.open).toHaveBeenCalled();
        });
    });
});
<|endoftext|>


<commit_before>/**
* main common functionalities will go in here
*/
var cc = {

    //debug value from Countly
    debug: false,
    debugBulk: false,
    debugBulkUser: false,
    /**
     *
     *log level Enums:
        *Error - this is a issues that needs attention right now.
        *Warning - this is something that is potentially a issue. Maybe a deprecated usage of something, maybe consent is enabled but consent is not given.
        *Info - All publicly exposed functions should log a call at this level to indicate that they were called. These calls should include the function name.
        *Debug - this should contain logs from the internal workings of the SDK and it's important calls. This should include things like the SDK configuration options, success or fail of the current network request, "request queue is full" and the oldest request get's dropped, etc.
        *Verbose - this should give a even deeper look into the SDK's inner working and should contain things that are more noisy and happen often.
        */
    logLevelEnums: {
        ERROR: '[ERROR] ',
        WARNING: '[WARNING] ',
        INFO: '[INFO] ',
        DEBUG: '[DEBUG] ',
        VERBOSE: '[VERBOSE] ',
    },
    /**
     *  Get current timestamp
     *  @returns {number} unix timestamp in seconds
     */
    getTimestamp: function getTimestamp() {
        return Math.floor(new Date().getTime() / 1000);
    },
    /**
         *  Retrieve only specific properties from object
         *  @param {Object} orig - object from which to get properties
         *  @param {Array} props - list of properties to get
         *  @returns {Object} Object with requested properties
         */
    getProperties: function getProperties(orig, props) {
        var ob = {};
        var prop;
        for (var i = 0; i < props.length; i++) {
            prop = props[i];
            if (typeof orig[prop] !== "undefined") {
                ob[prop] = orig[prop];
            }
        }
        return ob;
    },
    /**
         *  Removing trailing slashes
         *  @memberof Countly._internals
         *  @param {String} str - string from which to remove traling slash
         *  @returns {String} modified string
         */
    stripTrailingSlash: function stripTrailingSlash(str) {
        if (str.substring(str.length - 1) === "/") {
            return str.substring(0, str.length - 1);
        }
        return str;
    },
    /**
         *  Generate random UUID value
         *  @returns {String} random UUID value
         */
    generateUUID: function generateUUID() {
        var d = new Date().getTime();
        var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
            var r = (d + Math.random() * 16) % 16 | 0;
            d = Math.floor(d / 16);
            return (c === "x" ? r : (r & 0x3 | 0x8)).toString(16);
        });
        return uuid;
    },
    /**
     *  Log data if debug mode is enabled
     * @param {string} level - log level (error, warning, info, debug, verbose)
     * @param {string} message - any string message
     */
    log: function log(level, message, ...args) {
        if ((this.debug || this.debugBulk || this.debugBulkUser) && typeof console !== "undefined") {
            if (args[0] && typeof args[0] === "object") {
                args[0] = JSON.stringify(args[0]);
            }
            var color = '';
            //change colors for better readability
            if (level === this.logLevelEnums.ERROR) {
                //ERROR is red color through console.error
                // eslint-disable-next-line no-console
                console.error(color, level + message, Array.prototype.slice.call(args).join("\n"));
            }
            else if (level === this.logLevelEnums.WARNING) {
                // WARNING is yellow color through console.warn
                // eslint-disable-next-line no-console
                console.warn(color, level + message, Array.prototype.slice.call(args).join("\n"));
            }
            else if (level === this.logLevelEnums.VERBOSE) {
                // VERBOSE is set to blue color
                color = '\x1b[34m%s\x1b[0m';
                // eslint-disable-next-line no-console
                console.log(color, level + message, Array.prototype.slice.call(args).join("\n"));
            }
            else {
                //INFO has white color (no color setting)
                if (level !== this.logLevelEnums.INFO) {
                    //default log level is DEBUG
                    level = this.logLevelEnums.DEBUG;
                    //DEBUG is set to color cyan
                    color = '\x1b[36m%s\x1b[0m';
                }
                // eslint-disable-next-line no-console
                console.log(color, level + message, Array.prototype.slice.call(args).join("\n"));
            }
        }
    },
    /**
     * Check if the http response fits the bill of:
     * 1. The HTTP response code was successful (which is any 2xx code or code between 200 <= x < 300)
     * 2. The returned request is a JSON object
     * 3. That JSON object contains the field "result" (there can be other fields)
     * @param {Number} statusCode - http incoming statusCode
     * @param {String} str - response from server, ideally must be: {"result":"Success"} or should contain at least result field
     * @returns {Boolean} - returns true if response passes the tests
     */
    isResponseValid: function isResponseValid(statusCode, str) {
        // status code and response format check
        if (!(statusCode >= 200 && statusCode < 300)) {
            return false;
        }

        //Try to parse JSON
        try {
            return JSON.parse(str).result ? true : false;
        }
        catch (e) {
            this.log("Http response is in the wrong format.", e);
            return false;
        }
    }
};

module.exports = cc;
<commit_msg>coloring fix (#29)<commit_after>/**
* main common functionalities will go in here
*/
var cc = {

    //debug value from Countly
    debug: false,
    debugBulk: false,
    debugBulkUser: false,
    /**
     *
     *log level Enums:
        *Error - this is a issues that needs attention right now.
        *Warning - this is something that is potentially a issue. Maybe a deprecated usage of something, maybe consent is enabled but consent is not given.
        *Info - All publicly exposed functions should log a call at this level to indicate that they were called. These calls should include the function name.
        *Debug - this should contain logs from the internal workings of the SDK and it's important calls. This should include things like the SDK configuration options, success or fail of the current network request, "request queue is full" and the oldest request get's dropped, etc.
        *Verbose - this should give a even deeper look into the SDK's inner working and should contain things that are more noisy and happen often.
        */
    logLevelEnums: {
        ERROR: '[ERROR] ',
        WARNING: '[WARNING] ',
        INFO: '[INFO] ',
        DEBUG: '[DEBUG] ',
        VERBOSE: '[VERBOSE] ',
    },
    /**
     *  Get current timestamp
     *  @returns {number} unix timestamp in seconds
     */
    getTimestamp: function getTimestamp() {
        return Math.floor(new Date().getTime() / 1000);
    },
    /**
         *  Retrieve only specific properties from object
         *  @param {Object} orig - object from which to get properties
         *  @param {Array} props - list of properties to get
         *  @returns {Object} Object with requested properties
         */
    getProperties: function getProperties(orig, props) {
        var ob = {};
        var prop;
        for (var i = 0; i < props.length; i++) {
            prop = props[i];
            if (typeof orig[prop] !== "undefined") {
                ob[prop] = orig[prop];
            }
        }
        return ob;
    },
    /**
         *  Removing trailing slashes
         *  @memberof Countly._internals
         *  @param {String} str - string from which to remove traling slash
         *  @returns {String} modified string
         */
    stripTrailingSlash: function stripTrailingSlash(str) {
        if (str.substring(str.length - 1) === "/") {
            return str.substring(0, str.length - 1);
        }
        return str;
    },
    /**
         *  Generate random UUID value
         *  @returns {String} random UUID value
         */
    generateUUID: function generateUUID() {
        var d = new Date().getTime();
        var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
            var r = (d + Math.random() * 16) % 16 | 0;
            d = Math.floor(d / 16);
            return (c === "x" ? r : (r & 0x3 | 0x8)).toString(16);
        });
        return uuid;
    },
    /**
     *  Log data if debug mode is enabled
     * @param {string} level - log level (error, warning, info, debug, verbose)
     * @param {string} message - any string message
     */
    log: function log(level, message, ...args) {
        if ((this.debug || this.debugBulk || this.debugBulkUser) && typeof console !== "undefined") {
            if (args[0] && typeof args[0] === "object") {
                args[0] = JSON.stringify(args[0]);
            }
            if (level === this.logLevelEnums.ERROR) {
                // eslint-disable-next-line no-console
                console.error(level + message, Array.prototype.slice.call(args).join("\n"));
            }
            else if (level === this.logLevelEnums.WARNING) {
                // eslint-disable-next-line no-console
                console.warn(level + message, Array.prototype.slice.call(args).join("\n"));
            }
            else if (level === this.logLevelEnums.VERBOSE) {
                // eslint-disable-next-line no-console
                console.log(level + message, Array.prototype.slice.call(args).join("\n"));
            }
            else if (level === this.logLevelEnums.INFO) {
                // eslint-disable-next-line no-console
                console.info(level + message, Array.prototype.slice.call(args).join("\n"));
            }
            else {
                //default log level is DEBUG
                level = this.logLevelEnums.DEBUG;
                // eslint-disable-next-line no-console
                console.debug(level + message, Array.prototype.slice.call(args).join("\n"));
            }
        }
    },
    /**
     * Check if the http response fits the bill of:
     * 1. The HTTP response code was successful (which is any 2xx code or code between 200 <= x < 300)
     * 2. The returned request is a JSON object
     * 3. That JSON object contains the field "result" (there can be other fields)
     * @param {Number} statusCode - http incoming statusCode
     * @param {String} str - response from server, ideally must be: {"result":"Success"} or should contain at least result field
     * @returns {Boolean} - returns true if response passes the tests
     */
    isResponseValid: function isResponseValid(statusCode, str) {
        // status code and response format check
        if (!(statusCode >= 200 && statusCode < 300)) {
            return false;
        }

        //Try to parse JSON
        try {
            return JSON.parse(str).result ? true : false;
        }
        catch (e) {
            this.log("Http response is in the wrong format.", e);
            return false;
        }
    }
};

module.exports = cc;
<|endoftext|>


<commit_before>'use strict';

describe('filterByFilter', function() {

  var filter;

  beforeEach(module('a8m.filter-by'));

  beforeEach(inject(function($filter) {
    filter = $filter('filterBy');
  }));

  it('should filter by specific properties and avoid the rest', function() {

    var users = [
      { id: 1, user: { first_name: 'foo', last_name: 'bar',  mobile: 4444 } },
      { id: 2, user: { first_name: 'bar', last_name: 'foo',  mobile: 3333 } },
      { id: 3, user: { first_name: 'foo', last_name: 'baz',  mobile: 2222 } },
      { id: 4, user: { first_name: 'baz', last_name: 'foo',  mobile: 1111 } }
    ];

    expect(filter(users, ['user.first_name', 'user.last_name'], 'foo')).toEqual(users);
    expect(filter(users, ['user.first_name'], 'foo')).toEqual([users[0], users[2]]);
    expect(filter(users, ['user.last_name'], 'bar')).toEqual([users[0]]);

    expect(filter(users, ['id', 'user.mobile'], '1')).toEqual([users[0], users[3]]);
    expect(filter(users, ['id'], '1')).toEqual([users[0]]);
    expect(filter(users, ['id', 'user.mobile'], '11')).toEqual([users[3]]);

  });

  it('should support to get object as collection', function() {

    var users = {
      0: { id: 1, user: { first_name: 'foo', last_name: 'bar',  mobile: 4444 } },
      1: { id: 2, user: { first_name: 'bar', last_name: 'foo',  mobile: 3333 } },
      2: { id: 3, user: { first_name: 'foo', last_name: 'baz',  mobile: 2222 } },
      3: { id: 4, user: { first_name: 'baz', last_name: 'foo',  mobile: 1111 } }
    };

    expect(filter(users, ['user.first_name', 'user.last_name'], 'foo')).toEqual(users);
    expect(filter(users, ['user.first_name'], 'oo')).toEqual([users[0], users[2]]);
    expect(filter(users, ['user.last_name'], 'bar')).toEqual([users[0]]);

  });

  it('should parse concatenate properties, and search them by one field', function() {

    var users = [
      { id: 1, user: { first_name: 'foo', last_name: 'bar',  mobile: 4444 } },
      { id: 2, user: { first_name: 'bar', last_name: 'foo',  mobile: 3333 } },
      { id: 3, user: { first_name: 'foo', last_name: 'baz',  mobile: 2222 } },
      { id: 4, user: { first_name: 'baz', last_name: 'foo',  mobile: 1111 } }
    ];

    expect(filter(users, ['user.first_name + user.last_name'], 'foo bar')).toEqual([users[0]]);
    expect(filter(users, ['user.first_name+user.last_name'], 'foo bar')).toEqual([users[0]]);
    expect(filter(users, ['user.first_name + user.mobile'], 'foo 4444')).toEqual([users[0]]);

    expect(filter(users, ['user.first_name + user.undefined'], 'foo')).toEqual([users[0], users[2]]);

    expect(filter(users, ['user.first_name + user.last_name'], 'a')).toEqual(users);
    expect(filter(users, ['user.first_name + user.last_name'], 'ba')).toEqual(users);
    expect(filter(users, ['user.first_name + user.last_name'], 'foo')).toEqual(users);

  });

  it('should take care on extreme conditions', function() {

    var users = [
      { id: 1, user: { first_name: 'foo', last_name: 'bar',  mobile: 4444 } },
      { id: 2, user: { first_name: 'bar', last_name: 'foo',  mobile: 3333 } },
      { id: 3, user: { first_name: 'foo', last_name: 'baz',  mobile: 2222 } },
      { id: 4, user: { first_name: 'baz', last_name: 'foo',  mobile: 1111 } }
    ];

    expect(filter(users, ['id'], 1)).toEqual([users[0]]);
    expect(filter(users, ['id'])).toEqual(users);
    expect(filter(users, ['id', 'phone'], 4)).toEqual([users[3]]);
    expect(filter(users, ['id', 'phone'], null)).toEqual(users);
    expect(filter(users, null, null)).toEqual(users);
    expect(filter(users, [], [])).toEqual(users);

  });

  it('should get a !collection and return it as-is', function() {

    expect(filter(!1)).toBeFalsy();
    expect(filter(1)).toEqual(1);
    expect(filter('string')).toEqual('string');
    expect(filter(undefined)).toEqual(undefined);

  });

  it('should not coerce non-string/number properties', function() {
    var users = [
      { id: [1, 2], user: { first_name: 'foo', last_name: 'bar',  mobile: 4444 } }
    ];

    expect(filter(users, ['id'], 1)).toEqual([]);
  });

  describe('strict mode', function() {

    var users = [
      { id: 1, user: { first_name: 'foo', last_name: 'bar',  mobile: 4444 } }
    ];

    it('should only return exact matches', function() {

      expect(filter(users, ['user.first_name'], 'fo', true)).toEqual([]);
      expect(filter(users, ['user.first_name'], 'foo', true)).toEqual(users);

    });

    it('should handle multiple properties', function() {

      expect(filter(users, ['user.first_name', 'user.last_name'], 'ba', true)).toEqual([]);
      expect(filter(users, ['user.first_name', 'user.last_name'], 'bar', true)).toEqual(users);

    });

    it('should handle concatenation', function() {

      expect(filter(users, ['user.first_name + user.last_name'], 'foo ba', true)).toEqual([]);
      expect(filter(users, ['user.first_name + user.last_name'], 'foo bar', true)).toEqual(users);

    });

  });

});
<commit_msg>style(test/filter-by): rm unnecessary newlines<commit_after>'use strict';

describe('filterByFilter', function() {
  var filter;

  beforeEach(module('a8m.filter-by'));
  beforeEach(inject(function($filter) {
    filter = $filter('filterBy');
  }));

  it('should filter by specific properties and avoid the rest', function() {
    var users = [
      { id: 1, user: { first_name: 'foo', last_name: 'bar',  mobile: 4444 } },
      { id: 2, user: { first_name: 'bar', last_name: 'foo',  mobile: 3333 } },
      { id: 3, user: { first_name: 'foo', last_name: 'baz',  mobile: 2222 } },
      { id: 4, user: { first_name: 'baz', last_name: 'foo',  mobile: 1111 } }
    ];

    expect(filter(users, ['user.first_name', 'user.last_name'], 'foo')).toEqual(users);
    expect(filter(users, ['user.first_name'], 'foo')).toEqual([users[0], users[2]]);
    expect(filter(users, ['user.last_name'], 'bar')).toEqual([users[0]]);

    expect(filter(users, ['id', 'user.mobile'], '1')).toEqual([users[0], users[3]]);
    expect(filter(users, ['id'], '1')).toEqual([users[0]]);
    expect(filter(users, ['id', 'user.mobile'], '11')).toEqual([users[3]]);
  });

  it('should support to get object as collection', function() {
    var users = {
      0: { id: 1, user: { first_name: 'foo', last_name: 'bar',  mobile: 4444 } },
      1: { id: 2, user: { first_name: 'bar', last_name: 'foo',  mobile: 3333 } },
      2: { id: 3, user: { first_name: 'foo', last_name: 'baz',  mobile: 2222 } },
      3: { id: 4, user: { first_name: 'baz', last_name: 'foo',  mobile: 1111 } }
    };

    expect(filter(users, ['user.first_name', 'user.last_name'], 'foo')).toEqual(users);
    expect(filter(users, ['user.first_name'], 'oo')).toEqual([users[0], users[2]]);
    expect(filter(users, ['user.last_name'], 'bar')).toEqual([users[0]]);
  });

  it('should parse concatenate properties, and search them by one field', function() {
    var users = [
      { id: 1, user: { first_name: 'foo', last_name: 'bar',  mobile: 4444 } },
      { id: 2, user: { first_name: 'bar', last_name: 'foo',  mobile: 3333 } },
      { id: 3, user: { first_name: 'foo', last_name: 'baz',  mobile: 2222 } },
      { id: 4, user: { first_name: 'baz', last_name: 'foo',  mobile: 1111 } }
    ];

    expect(filter(users, ['user.first_name + user.last_name'], 'foo bar')).toEqual([users[0]]);
    expect(filter(users, ['user.first_name+user.last_name'], 'foo bar')).toEqual([users[0]]);
    expect(filter(users, ['user.first_name + user.mobile'], 'foo 4444')).toEqual([users[0]]);

    expect(filter(users, ['user.first_name + user.undefined'], 'foo')).toEqual([users[0], users[2]]);

    expect(filter(users, ['user.first_name + user.last_name'], 'a')).toEqual(users);
    expect(filter(users, ['user.first_name + user.last_name'], 'ba')).toEqual(users);
    expect(filter(users, ['user.first_name + user.last_name'], 'foo')).toEqual(users);
  });

  it('should take care on extreme conditions', function() {
    var users = [
      { id: 1, user: { first_name: 'foo', last_name: 'bar',  mobile: 4444 } },
      { id: 2, user: { first_name: 'bar', last_name: 'foo',  mobile: 3333 } },
      { id: 3, user: { first_name: 'foo', last_name: 'baz',  mobile: 2222 } },
      { id: 4, user: { first_name: 'baz', last_name: 'foo',  mobile: 1111 } }
    ];

    expect(filter(users, ['id'], 1)).toEqual([users[0]]);
    expect(filter(users, ['id'])).toEqual(users);
    expect(filter(users, ['id', 'phone'], 4)).toEqual([users[3]]);
    expect(filter(users, ['id', 'phone'], null)).toEqual(users);
    expect(filter(users, null, null)).toEqual(users);
    expect(filter(users, [], [])).toEqual(users);
  });

  it('should get a !collection and return it as-is', function() {
    expect(filter(!1)).toBeFalsy();
    expect(filter(1)).toEqual(1);
    expect(filter('string')).toEqual('string');
    expect(filter(undefined)).toEqual(undefined);
  });

  it('should not coerce non-string/number properties', function() {
    var users = [
      { id: [1, 2], user: { first_name: 'foo', last_name: 'bar',  mobile: 4444 } }
    ];

    expect(filter(users, ['id'], 1)).toEqual([]);
  });

  describe('strict mode', function() {
    var users = [
      { id: 1, user: { first_name: 'foo', last_name: 'bar',  mobile: 4444 } }
    ];

    it('should only return exact matches', function() {
      expect(filter(users, ['user.first_name'], 'fo', true)).toEqual([]);
      expect(filter(users, ['user.first_name'], 'foo', true)).toEqual(users);
    });

    it('should handle multiple properties', function() {
      expect(filter(users, ['user.first_name', 'user.last_name'], 'ba', true)).toEqual([]);
      expect(filter(users, ['user.first_name', 'user.last_name'], 'bar', true)).toEqual(users);
    });

    it('should handle concatenation', function() {
      expect(filter(users, ['user.first_name + user.last_name'], 'foo ba', true)).toEqual([]);
      expect(filter(users, ['user.first_name + user.last_name'], 'foo bar', true)).toEqual(users);
    });
  });
});
<|endoftext|>


<commit_before>/**
 * @name      ElkArte Forum
 * @copyright ElkArte Forum contributors
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause
 *
 * @version 1.0 Release Candidate 1
 *
 * This file contains javascript associated with the drafts auto function as it
 * relates to an sceditor invocation
 */

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

	function elk_Drafts(options) {
		// All the passed options and defaults are loaded to the opts object
		this.opts = $.extend({}, this.defaults, options);

		// Attach mousedown events to the forms submit buttons
		this.formCheck();
	}

	/**
	 * Make the call to save this draft in the background
	 * - returns if nothing has changed since the last save or there is nothing to save
	 * - updates the display to show we are saving
	 * - loads the form data and makes the ajax request
	 */
	elk_Drafts.prototype.draftSave = function() {
		// No change since the last save, or form submitted
		if (!this.opts._bCheckDraft || elk_formSubmitted || (typeof disableDrafts !== 'undefined' && disableDrafts))
			return false;

		// Still saving the last one or other?
		if (this.opts._bInDraftMode === true)
			this.draftCancel();

		// Get the editor text, either from sceditor or from the quicktext textarea
		var sPostdata = base.val();

		// Nothing to save?
		if (isEmptyText(sPostdata))
			return false;

		// Flag that we are saving a draft
		document.getElementById('throbber').style.display = '';
		this.opts._bInDraftMode = true;

		// Get all the form elements that we want to save
		var aSections = [
			'topic=' + parseInt(document.forms.postmodify.elements['topic'].value),
			'id_draft=' + (('id_draft' in document.forms.postmodify.elements) ? parseInt(document.forms.postmodify.elements['id_draft'].value) : 0),
			'subject=' + escape(document.forms.postmodify['subject'].value.replace(/&#/g, "&#").php_to8bit()).replace(/\+/g, "%2B"),
			'message=' + escape(sPostdata.replace(/&#/g, "&#").php_to8bit()).replace(/\+/g, "%2B"),
			'icon=' + escape(document.forms.postmodify['icon'].value.replace(/&#/g, "&#").php_to8bit()).replace(/\+/g, "%2B"),
			'save_draft=true',
			elk_session_var + '=' + elk_session_id
		];

		// Get the locked an/or sticky values if they have been selected or set that is
		if (this.opts.sType && this.opts.sType === 'post')
		{
			var oLock = document.getElementById('check_lock'),
				oSticky = document.getElementById('check_sticky'),
				oSmile = document.getElementById('check_smileys');

			if (oLock && oLock.checked)
				aSections[aSections.length] = 'lock=1';

			if (oSticky && oSticky.checked)
				aSections[aSections.length] = 'sticky=1';

			if (oSmile && oSmile.checked)
				aSections[aSections.length] = 'ns=1';
		}

		// Keep track of source or wysiwyg when using the full editor
		aSections[aSections.length] = 'message_mode=' + (base.inSourceMode() ? '1' : '0');

		// Send in the request to save the data
		this.draftAjax(aSections, "?action=post2;board=" + this.opts.iBoard + ";xml");
	};

	/**
	 * Make the call to save this PM draft in the background
	 * - returns if nothing has changed since the last save or there is nothing to save
	 * - updates the display to show we are saving
	 * - loads the form data and makes the ajax request
	 */
	elk_Drafts.prototype.draftPMSave = function ()
	{
		// No change since the last PM save, or elk is doing its thing
		if (!this.opts._bCheckDraft || elk_formSubmitted)
			return false;

		// Still saving the last one or some other?
		if (this.opts._bInDraftMode === true)
			this.draftCancel();

		// Nothing to save
		var sPostdata = base.val();
		if (isEmptyText(sPostdata))
			return false;

		// Flag that we are saving the PM
		document.getElementById('throbber').style.display = '';
		this.opts._bInDraftMode = true;

		// Get the to and bcc values
		var aTo = this.draftGetRecipient('recipient_to[]'),
			aBcc = this.draftGetRecipient('recipient_bcc[]');

		// Get the rest of the form elements that we want to save, and load them up
		var aSections = [
			'replied_to=' + parseInt(document.forms.pmFolder.elements['replied_to'].value),
			'id_pm_draft=' + (('id_pm_draft' in document.forms.pmFolder.elements) ? parseInt(document.forms.pmFolder.elements['id_pm_draft'].value) : 0),
			'subject=' + escape(document.forms.pmFolder['subject'].value.replace(/&#/g, "&#").php_to8bit()).replace(/\+/g, "%2B"),
			'message=' + escape(sPostdata.replace(/&#/g, "&#").php_to8bit()).replace(/\+/g, "%2B"),
			'recipient_to=' + aTo,
			'recipient_bcc=' + aBcc,
			'save_draft=true',
			elk_session_var + '=' + elk_session_id
		];

		// Account for wysiwyg
		if (this.opts.sType && this.opts.sType === 'post')
			aSections[aSections.length] = 'message_mode=' + (base.inSourceMode() ? '1' : '0');

		// Send in (post) the document for saving
		this.draftAjax(aSections, "?action=pm;sa=send2;xml");
	};

	/**
	 * Make and process the ajax response
	 *
	 * - updates the display to show last saved on
	 * - closes the draft last saved info box from a "manual" save draft click
	 * - hides the ajax saving icon
	 * - turns off _bInDraftMode so another save request can fire
	 *
	 * @param {xml object} XMLDoc
	 */
	elk_Drafts.prototype.draftAjax = function(post, action)
	{
		// Send in the request to save the data
		$.ajax({
			type: "POST",
			dataType: 'xml',
			url: elk_scripturl + action,
			data: post.join("&"),
			context: this
		})
		.done(function(data, textStatus, jqXHR) {
			// If it is not valid then move on
			if (textStatus === 'success' && $(data).find("draft").length !== 0)
			{
				// Grab the returned draft id and saved time from the response
				this.opts._sCurDraftId = $(data).find("draft").attr('id');
				this.opts._sLastSaved = $(data).find("draft").text();

				// Update the form to show we finished, if the id is not set, then set it
				document.getElementById(this.opts.sLastID).value = this.opts._sCurDraftId;
				document.getElementById(this.opts.sLastNote).innerHTML = this.opts._sLastSaved;

				// Hide the saved draft successbox in the event they pressed the save draft button at some point
				var draft_section = document.getElementById('draft_section');
				if (draft_section)
					draft_section.style.display = 'none';
			}
		})
		.always(function() {
			// No matter what, we clear the saving indicator
			this.opts._bInDraftMode = false;
			document.getElementById('throbber').style.display = 'none';

			// Set the flag off so we don't save again (until a keypress indicates they changed the text)
			this.opts._bCheckDraft = false;
		});
	};

	/**
	 * Function to retrieve the to and bcc values from the pseudo arrays
	 *  - Accounts for either a single or multiple to/bcc recipients
	 *
	 * @param {string} sField name of the form elements we are getting
	 */
	elk_Drafts.prototype.draftGetRecipient = function (sField)
	{
		var oRecipient = document.forms.pmFolder.elements[sField],
			aRecipient = [];

		if (typeof(oRecipient) !== 'undefined')
		{
			// Just one recipient
			if ('value' in oRecipient)
				aRecipient.push(parseInt(oRecipient.value));
			else
			{
				// Or many !
				for (var i = 0, n = oRecipient.length; i < n; i++)
					aRecipient.push(parseInt(oRecipient[i].value));
			}
		}

		return aRecipient;
	};

	/**
	 * If another auto save came in with one still pending we cancel out
	 */
	elk_Drafts.prototype.draftCancel = function () {
		this.opts._bInDraftMode = false;
		document.getElementById('throbber').style.display = 'none';
	};

	/**
	 * Starts the autosave timer for the current instance of the elk_draft object
	 */
	elk_Drafts.prototype.startSaver = function () {
		var oInstance = this;
		if (this.opts.bPM)
			this.opts._interval_id = setInterval(function(){oInstance.draftPMSave();}, this.opts.iFreq);
		else
			this.opts._interval_id = setInterval(function(){oInstance.draftSave();}, this.opts.iFreq);
	};

	/**
	 * Signals that one of the post/pm/qr form buttons was pressed
	 * Used to prevent saving an auto draft on input button (post, save, etc)
	 */
	elk_Drafts.prototype.formCheck = function() {
		var oInstance = this,
			formID = $('#id_draft').closest("form").attr('id');

		$('#' + formID + ' .button_submit').on('mousedown', oInstance, function () {
			oInstance.opts._bInDraftMode = true;
		});
	};

	/**
	 * Private draft vars to keep track of what/where/why
	 */
	elk_Drafts.prototype.defaults = {
		/**
		 * If we are currently in draft saving mode
		 * @type {Boolean}
		 */
		_bInDraftMode: false,

		/**
		 * The id of the draft so it save/appends
		 * @type {String}
		 */
		_sCurDraftId: null,

		/**
		 * How often we are going to save a draft in the background
		 * @type {Integer}
		 */
		_interval_id: null,

		/**
		 * The text to place in the last saved Div, comes from the xml response
		 * @type {String}
		 */
		_sLastSaved: null,

		/**
		 * If the user has pressed a key since the last save
		 * @type {Boolean}
		 */
		_bCheckDraft: false
	};

	/**
	 * Holds all  current draft options (defaults + passed options)
	 */
	elk_Drafts.prototype.opts = {};

	/**
	 * Draft plugin interface to SCEditor
	 *  - Called from the editor as a plugin
	 *  - Monitors events so we control the elk_draft autosaver (on/off/change)
	 */
	$.sceditor.plugins.draft = function() {
		var base = this,
			oDrafts;

		/**
		 * Initialize, called when sceditor starts and initializes plugins
		 */
		base.init = function() {
			// Init the draft instance, load in the options
			oDrafts = new elk_Drafts(this.opts.draftOptions);
			oDrafts.opts.bPM = oDrafts.opts.bPM ? true : false;

			// Start the autosave timer
			if (oDrafts.opts.iFreq > 0)
				oDrafts.startSaver();
		};

		/**
		 * Used to ensure the autosave timer is running when the editor window
		 * (wiz or source) re-gains focus
		 */
		base.signalFocusEvent = function() {
			if (oDrafts.opts._interval_id === "")
				oDrafts.startSaver();
		};

		/**
		 * Moved away from the editor, where did you go?
		 * - Turns off the autosave timer when the user moves the focus away
		 * - Saves the current content before turning off the autosaver
		 */
		base.signalBlurEvent = function(e) {
			// If we are not already in a save action, save the draft
			if (oDrafts.opts._bInDraftMode === true)
				oDrafts.draftCancel();
			else {
				// Lets save the draft then
				if (oDrafts.opts.bPM)
					oDrafts.draftPMSave();
				else
					oDrafts.draftSave();

				// Turn it off the autosave if we can, mark it as such
				if (oDrafts.opts._interval_id !== "")
					clearInterval(oDrafts.opts._interval_id);

				oDrafts.opts._interval_id = "";
			}
		};

		/**
		 * Informs the autosave function that some activity has occurred in the
		 * editor window since the last save ... activity being any keypress
		 * in the editor which we assume means they changed it
		 */
		base.signalKeypressEvent = function() {
			oDrafts.opts._bCheckDraft = true;
		};
	};

})(jQuery, window, document);<commit_msg>! small formatting cleanup<commit_after>/**
 * @name      ElkArte Forum
 * @copyright ElkArte Forum contributors
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause
 *
 * @version 1.0 Release Candidate 1
 *
 * This file contains javascript associated with the drafts auto function as it
 * relates to an sceditor invocation
 */

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

	function elk_Drafts(options) {
		// All the passed options and defaults are loaded to the opts object
		this.opts = $.extend({}, this.defaults, options);

		// Attach mousedown events to the forms submit buttons
		this.formCheck();
	}

	/**
	 * Make the call to save this draft in the background
	 * - returns if nothing has changed since the last save or there is nothing to save
	 * - updates the display to show we are saving
	 * - loads the form data and makes the ajax request
	 */
	elk_Drafts.prototype.draftSave = function() {
		// No change since the last save, or form submitted
		if (!this.opts._bCheckDraft || elk_formSubmitted || (typeof disableDrafts !== 'undefined' && disableDrafts))
			return false;

		// Still saving the last one or other?
		if (this.opts._bInDraftMode === true)
			this.draftCancel();

		// Get the editor text, either from sceditor or from the quicktext textarea
		var sPostdata = base.val();

		// Nothing to save?
		if (isEmptyText(sPostdata))
			return false;

		// Flag that we are saving a draft
		document.getElementById('throbber').style.display = '';
		this.opts._bInDraftMode = true;

		// Get all the form elements that we want to save
		var aSections = [
			'topic=' + parseInt(document.forms.postmodify.elements['topic'].value),
			'id_draft=' + (('id_draft' in document.forms.postmodify.elements) ? parseInt(document.forms.postmodify.elements['id_draft'].value) : 0),
			'subject=' + escape(document.forms.postmodify['subject'].value.replace(/&#/g, "&#").php_to8bit()).replace(/\+/g, "%2B"),
			'message=' + escape(sPostdata.replace(/&#/g, "&#").php_to8bit()).replace(/\+/g, "%2B"),
			'icon=' + escape(document.forms.postmodify['icon'].value.replace(/&#/g, "&#").php_to8bit()).replace(/\+/g, "%2B"),
			'save_draft=true',
			elk_session_var + '=' + elk_session_id
		];

		// Get the locked an/or sticky values if they have been selected or set that is
		if (this.opts.sType && this.opts.sType === 'post')
		{
			var oLock = document.getElementById('check_lock'),
				oSticky = document.getElementById('check_sticky'),
				oSmile = document.getElementById('check_smileys');

			if (oLock && oLock.checked)
				aSections[aSections.length] = 'lock=1';

			if (oSticky && oSticky.checked)
				aSections[aSections.length] = 'sticky=1';

			if (oSmile && oSmile.checked)
				aSections[aSections.length] = 'ns=1';
		}

		// Keep track of source or wysiwyg when using the full editor
		aSections[aSections.length] = 'message_mode=' + (base.inSourceMode() ? '1' : '0');

		// Send in the request to save the data
		this.draftAjax(aSections, "?action=post2;board=" + this.opts.iBoard + ";xml");
	};

	/**
	 * Make the call to save this PM draft in the background
	 * - returns if nothing has changed since the last save or there is nothing to save
	 * - updates the display to show we are saving
	 * - loads the form data and makes the ajax request
	 */
	elk_Drafts.prototype.draftPMSave = function()
	{
		// No change since the last PM save, or elk is doing its thing
		if (!this.opts._bCheckDraft || elk_formSubmitted)
			return false;

		// Still saving the last one or some other?
		if (this.opts._bInDraftMode === true)
			this.draftCancel();

		// Nothing to save
		var sPostdata = base.val();
		if (isEmptyText(sPostdata))
			return false;

		// Flag that we are saving the PM
		document.getElementById('throbber').style.display = '';
		this.opts._bInDraftMode = true;

		// Get the to and bcc values
		var aTo = this.draftGetRecipient('recipient_to[]'),
			aBcc = this.draftGetRecipient('recipient_bcc[]');

		// Get the rest of the form elements that we want to save, and load them up
		var aSections = [
			'replied_to=' + parseInt(document.forms.pmFolder.elements['replied_to'].value),
			'id_pm_draft=' + (('id_pm_draft' in document.forms.pmFolder.elements) ? parseInt(document.forms.pmFolder.elements['id_pm_draft'].value) : 0),
			'subject=' + escape(document.forms.pmFolder['subject'].value.replace(/&#/g, "&#").php_to8bit()).replace(/\+/g, "%2B"),
			'message=' + escape(sPostdata.replace(/&#/g, "&#").php_to8bit()).replace(/\+/g, "%2B"),
			'recipient_to=' + aTo,
			'recipient_bcc=' + aBcc,
			'save_draft=true',
			elk_session_var + '=' + elk_session_id
		];

		// Account for wysiwyg
		if (this.opts.sType && this.opts.sType === 'post')
			aSections[aSections.length] = 'message_mode=' + (base.inSourceMode() ? '1' : '0');

		// Send in (post) the document for saving
		this.draftAjax(aSections, "?action=pm;sa=send2;xml");
	};

	/**
	 * Make and process the ajax response
	 *
	 * - updates the display to show last saved on
	 * - closes the draft last saved info box from a "manual" save draft click
	 * - hides the ajax saving icon
	 * - turns off _bInDraftMode so another save request can fire
	 *
	 * @param {xml object} XMLDoc
	 */
	elk_Drafts.prototype.draftAjax = function(post, action)
	{
		// Send in the request to save the data
		$.ajax({
			type: "POST",
			dataType: 'xml',
			url: elk_scripturl + action,
			data: post.join("&"),
			context: this
		})
		.done(function(data, textStatus, jqXHR) {
			// If it is not valid then move on
			if (textStatus === 'success' && $(data).find("draft").length !== 0)
			{
				// Grab the returned draft id and saved time from the response
				this.opts._sCurDraftId = $(data).find("draft").attr('id');
				this.opts._sLastSaved = $(data).find("draft").text();

				// Update the form to show we finished, if the id is not set, then set it
				document.getElementById(this.opts.sLastID).value = this.opts._sCurDraftId;
				document.getElementById(this.opts.sLastNote).innerHTML = this.opts._sLastSaved;

				// Hide the saved draft successbox in the event they pressed the save draft button at some point
				var draft_section = document.getElementById('draft_section');
				if (draft_section)
					draft_section.style.display = 'none';
			}
		})
		.always(function() {
			// No matter what, we clear the saving indicator
			this.opts._bInDraftMode = false;
			document.getElementById('throbber').style.display = 'none';

			// Set the flag off so we don't save again (until a keypress indicates they changed the text)
			this.opts._bCheckDraft = false;
		});
	};

	/**
	 * Function to retrieve the to and bcc values from the pseudo arrays
	 *  - Accounts for either a single or multiple to/bcc recipients
	 *
	 * @param {string} sField name of the form elements we are getting
	 */
	elk_Drafts.prototype.draftGetRecipient = function(sField)
	{
		var oRecipient = document.forms.pmFolder.elements[sField],
			aRecipient = [];

		if (typeof (oRecipient) !== 'undefined')
		{
			// Just one recipient
			if ('value' in oRecipient)
				aRecipient.push(parseInt(oRecipient.value));
			else
			{
				// Or many !
				for (var i = 0, n = oRecipient.length; i < n; i++)
					aRecipient.push(parseInt(oRecipient[i].value));
			}
		}

		return aRecipient;
	};

	/**
	 * If another auto save came in with one still pending we cancel out
	 */
	elk_Drafts.prototype.draftCancel = function() {
		this.opts._bInDraftMode = false;
		document.getElementById('throbber').style.display = 'none';
	};

	/**
	 * Starts the autosave timer for the current instance of the elk_draft object
	 */
	elk_Drafts.prototype.startSaver = function() {
		var oInstance = this;
		if (this.opts.bPM)
			this.opts._interval_id = setInterval(function() {
				oInstance.draftPMSave();
			}, this.opts.iFreq);
		else
			this.opts._interval_id = setInterval(function() {
				oInstance.draftSave();
			}, this.opts.iFreq);
	};

	/**
	 * Signals that one of the post/pm/qr form buttons was pressed
	 * Used to prevent saving an auto draft on input button (post, save, etc)
	 */
	elk_Drafts.prototype.formCheck = function() {
		var oInstance = this,
			formID = $('#id_draft').closest("form").attr('id');

		$('#' + formID + ' .button_submit').on('mousedown', oInstance, function() {
			oInstance.opts._bInDraftMode = true;
		});
	};

	/**
	 * Private draft vars to keep track of what/where/why
	 */
	elk_Drafts.prototype.defaults = {
		/**
		 * If we are currently in draft saving mode
		 * @type {Boolean}
		 */
		_bInDraftMode: false,

		/**
		 * The id of the draft so it save/appends
		 * @type {String}
		 */
		_sCurDraftId: null,

		/**
		 * How often we are going to save a draft in the background
		 * @type {Integer}
		 */
		_interval_id: null,

		/**
		 * The text to place in the last saved Div, comes from the xml response
		 * @type {String}
		 */
		_sLastSaved: null,

		/**
		 * If the user has pressed a key since the last save
		 * @type {Boolean}
		 */
		_bCheckDraft: false
	};

	/**
	 * Holds all  current draft options (defaults + passed options)
	 */
	elk_Drafts.prototype.opts = {};

	/**
	 * Draft plugin interface to SCEditor
	 *  - Called from the editor as a plugin
	 *  - Monitors events so we control the elk_draft autosaver (on/off/change)
	 */
	$.sceditor.plugins.draft = function() {
		var base = this,
			oDrafts;

		/**
		 * Initialize, called when sceditor starts and initializes plugins
		 */
		base.init = function() {
			// Init the draft instance, load in the options
			oDrafts = new elk_Drafts(this.opts.draftOptions);
			oDrafts.opts.bPM = oDrafts.opts.bPM ? true : false;

			// Start the autosave timer
			if (oDrafts.opts.iFreq > 0)
				oDrafts.startSaver();
		};

		/**
		 * Used to ensure the autosave timer is running when the editor window
		 * (wiz or source) re-gains focus
		 */
		base.signalFocusEvent = function() {
			if (oDrafts.opts._interval_id === "")
				oDrafts.startSaver();
		};

		/**
		 * Moved away from the editor, where did you go?
		 * - Turns off the autosave timer when the user moves the focus away
		 * - Saves the current content before turning off the autosaver
		 */
		base.signalBlurEvent = function() {
			// If we are not already in a save action, save the draft
			if (oDrafts.opts._bInDraftMode === true)
				oDrafts.draftCancel();
			else {
				// Lets save the draft then
				if (oDrafts.opts.bPM)
					oDrafts.draftPMSave();
				else
					oDrafts.draftSave();

				// Turn it off the autosave if we can, mark it as such
				if (oDrafts.opts._interval_id !== "")
					clearInterval(oDrafts.opts._interval_id);

				oDrafts.opts._interval_id = "";
			}
		};

		/**
		 * Informs the autosave function that some activity has occurred in the
		 * editor window since the last save ... activity being any keypress
		 * in the editor which we assume means they changed it
		 */
		base.signalKeypressEvent = function() {
			oDrafts.opts._bCheckDraft = true;
		};
	};

})(jQuery, window, document);<|endoftext|>


<commit_before>var cheerio = require('cheerio');
var _ = require('underscore');
var fn = require('./fn');

var parseRule = function( val ){
    var rule = {};
    rule.$type = val.constructor.name;
    switch( rule.$type ){
        case 'String':
            rule.$fn = fn.text;
            rule.$rule = val;
            rule.$type = 'function';
            break;
        case 'Array':
            val = val[0];
            rule.$rule = val.$rule || '';
            rule.$fn = parseRule( val );
            delete rule.$fn.$rule;
            break;
        case 'Object':
            var subRules = _.omit( val, '$rule', '$fn', '$type');
            if( Object.keys(subRules).length ){
                rule.$type = 'Object';
                rule.$fn = {};
                rule.$rule = val.$rule || '';
                Object.keys(subRules).forEach(function(k){
                    val = subRules[k];
                    rule.$fn[k] = parseRule( val );
                });
            } else {
                rule.$rule = val.$rule ||'';
                rule.$type = 'function';
                rule.$fn = val.$fn;
            }
            break;
    }
    return rule;
};

exports.parseRule = parseRule;

function Extractor( rules ){
    this.rules = parseRule(rules);
}

Extractor.prototype.extract = function(html){
    var $ = cheerio(html);
    out = getItem($, this.rules );
    return out;
};

var getItem = function( $, rule ){
    if(typeof $ === 'string' )
        $ = cheerio.load($);
    var out;
    var elem = rule.$rule? $.find(rule.$rule) : $;
    switch ( rule.$type ){
        case 'function':
            out = elem.length? rule.$fn( elem ) : '';
            break;
        case 'Object':
            out = {};
            if(elem.length) {
                Object.keys(rule.$fn).forEach(function( key){
                    var subRule = rule.$fn[key];
                    out[key] = getItem( elem, subRule );
                });
            }
            break;
        case 'Array':
            out = [];
            if(elem.length) {
                _.each( elem, function(item){
                    var data = getItem(cheerio(item), rule.$fn );
                    out.push(data);
                });
            }
            break;
    }
    return out;
};

exports.getItem = getItem;

exports.Extractor = Extractor;
<commit_msg>Documentation<commit_after>"use strict";

var cheerio = require('cheerio');
var _ = require('underscore');
var fn = require('./fn');

var parseRule = function( val ){
    var rule = {};
    rule.$type = val.constructor.name;
    switch( rule.$type ){
        case 'String':
            rule.$fn = fn.text;
            rule.$rule = val;
            rule.$type = 'function';
            break;
        case 'Array':
            val = val[0];
            rule.$rule = val.$rule || '';
            rule.$fn = parseRule( val );
            delete rule.$fn.$rule;
            break;
        case 'Object':
            var subRules = _.omit( val, '$rule', '$fn', '$type');
            if( Object.keys(subRules).length ){
                rule.$type = 'Object';
                rule.$fn = {};
                rule.$rule = val.$rule || '';
                Object.keys(subRules).forEach(function(k){
                    val = subRules[k];
                    rule.$fn[k] = parseRule( val );
                });
            } else {
                rule.$rule = val.$rule ||'';
                rule.$type = 'function';
                rule.$fn = val.$fn;
            }
            break;
    }
    return rule;
};

exports.parseRule = parseRule;

var getItem = function( $, rule ){
    if(typeof $ === 'string' ){
      $ = cheerio.load($);
    }
    var out;
    var elem = rule.$rule? $.find(rule.$rule) : $;
    switch ( rule.$type ){
        case 'function':
            out = elem.length? rule.$fn( elem ) : '';
            break;
        case 'Object':
            out = {};
            if(elem.length) {
                Object.keys(rule.$fn).forEach(function( key){
                    var subRule = rule.$fn[key];
                    out[key] = getItem( elem, subRule );
                });
            }
            break;
        case 'Array':
            out = [];
            if(elem.length) {
                _.each( elem, function(item){
                    var data = getItem(cheerio(item), rule.$fn );
                    out.push(data);
                });
            }
            break;
    }
    return out;
};
exports.getItem = getItem;
/**
 * Extractor
 * @class
 * Extract data from HTML pages based on as schema.
 * A schema consists of following.
 * * names of fields to be fetched
 * * CSS rules for each fields
 * * Data extractor function for each fields.
 *
 * @param {Object} schema schema definition. Schema definition can have nested schema at any level.
 * @return {undefined}
 */
function Extractor( schema ){
    this.rules = parseRule( schema );
}

/**
 * extract data from a html string/page
 *
 * @param {String} html HTML page.
 * @return {Object} extracted data as per schema definition.
 */
Extractor.prototype.extract = function(html){
    var $ = cheerio(html);
    var out = getItem($, this.rules );
    return out;
};

exports.Extractor = Extractor;
<|endoftext|>


<commit_before>
function debug(data) {
  self.postMessage({type: 'debug', data: data})
}

Error.stackTraceLimit = 200;

var Module = {};
Module.TOTAL_MEMORY = 128 * 1024 * 1024;
Module.noFSInit = true;
Module.noExitRuntime = true;

function stdin() {
  return null;
}

function stdout(x) {
  self.postMessage({type: 'stdout', data: x})
}

function stderr(x) {
  self.postMessage({type: 'stderr', data: x})
}

function debugit(x) {
  self.postMessage({type: 'debug', data: x})
}

function onerror(e) {
  if (typeof console != 'undefined') {
    console.log(e.stack)
  }
  self.postMessage({type: 'error', data: e.toString()})
  throw e
}

debug('fetching filesystem stubs...')

try {
  importScripts('./lazyfiles.js');
} catch (e) {
  onerror(e)
}

Module.preRun = function() {
  try {
    // Create filesystem from lazy file metadata.
    FS.init(stdin, stdout, stderr);
    createLazyFiles(Module);
    // Sneakily replace _main with one that preps an interpreter.
    // Since we don't exit the runtime, this will set up the internal
    // state and them leave it for us to play with.
    Module['_main'] = function(argc, argv, wtf) {
      self.postMessage({type: 'status', data: 'loaded'})
      Module['_rpython_startup_code']();
      var pypy_home = allocate(intArrayFromString(""), 'i8', ALLOC_NORMAL);
      Module['_pypy_setup_home'](pypy_home, 0);
      var pypy_code = allocate(intArrayFromString("import code\nc = code.InteractiveConsole()"), 'i8', ALLOC_NORMAL);
      Module['_pypy_execute_source'](pypy_code);
      Module['_free'](pypy_code);
      pypy_push_input("print 'Welcome to PyPy.js'", true)
      pypy_push_input("from test import pystone", true)
      self.postMessage({type: 'status', data: 'ready'})
      return 0;
    }
  } catch (e) {
    onerror(e)
  }
}

function pypy_push_input(code, nomsg) {
  try {
    if (!nomsg) self.postMessage({type: 'status', data: 'working'})
    code = "c.push('" + code.replace(/'/g, "\\'") + "')"
    var pypy_code = allocate(intArrayFromString(code), 'i8', ALLOC_NORMAL);
    var res = Module['_pypy_execute_source'](pypy_code);
    Module['_free'](pypy_code);
    if (!nomsg) self.postMessage({type: 'status', data: 'ready', res: res})
    return res
  } catch (e) {
    if (typeof console != 'undefined') {
      console.log(e.stack)
    }
    self.postMessage({type: 'error', data: e.toString()})
  }
}

debug('fetching asmjs code...')

//try {
//  importScripts('./pypy-js.js');
//} catch (e) {
//  onerror(e)
//}

var xhr = new XMLHttpRequest();
xhr.open('GET', './pypy-js.js', false);
xhr.send(null);
if (xhr.status >= 400) {
  onerror('failed to load pypy-js.js');
}

debug('loading asmjs code...')

eval(xhr.responseText)

self.addEventListener('message', function(e) {
  var msg = e.data;
  switch (msg.type) {
    case 'input':
      pypy_push_input(msg.data);
      break;
  }
})
<commit_msg>Escape backslases in input code string.<commit_after>
function debug(data) {
  self.postMessage({type: 'debug', data: data})
}

Error.stackTraceLimit = 200;

var Module = {};
Module.TOTAL_MEMORY = 128 * 1024 * 1024;
Module.noFSInit = true;
Module.noExitRuntime = true;

function stdin() {
  return null;
}

function stdout(x) {
  self.postMessage({type: 'stdout', data: x})
}

function stderr(x) {
  self.postMessage({type: 'stderr', data: x})
}

function debugit(x) {
  self.postMessage({type: 'debug', data: x})
}

function onerror(e) {
  if (typeof console != 'undefined') {
    console.log(e.stack)
  }
  self.postMessage({type: 'error', data: e.toString()})
  throw e
}

debug('fetching filesystem stubs...')

try {
  importScripts('./lazyfiles.js');
} catch (e) {
  onerror(e)
}

Module.preRun = function() {
  try {
    // Create filesystem from lazy file metadata.
    FS.init(stdin, stdout, stderr);
    createLazyFiles(Module);
    // Sneakily replace _main with one that preps an interpreter.
    // Since we don't exit the runtime, this will set up the internal
    // state and them leave it for us to play with.
    Module['_main'] = function(argc, argv, wtf) {
      self.postMessage({type: 'status', data: 'loaded'})
      Module['_rpython_startup_code']();
      var pypy_home = allocate(intArrayFromString(""), 'i8', ALLOC_NORMAL);
      Module['_pypy_setup_home'](pypy_home, 0);
      var pypy_code = allocate(intArrayFromString("import code\nc = code.InteractiveConsole()"), 'i8', ALLOC_NORMAL);
      Module['_pypy_execute_source'](pypy_code);
      Module['_free'](pypy_code);
      pypy_push_input("print 'Welcome to PyPy.js'", true)
      pypy_push_input("from test import pystone", true)
      self.postMessage({type: 'status', data: 'ready'})
      return 0;
    }
  } catch (e) {
    onerror(e)
  }
}

function pypy_push_input(code, nomsg) {
  try {
    if (!nomsg) self.postMessage({type: 'status', data: 'working'})
    code = code.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
    code = "c.push('" + code + "')"
    var pypy_code = allocate(intArrayFromString(code), 'i8', ALLOC_NORMAL);
    var res = Module['_pypy_execute_source'](pypy_code);
    Module['_free'](pypy_code);
    if (!nomsg) self.postMessage({type: 'status', data: 'ready', res: res})
    return res
  } catch (e) {
    if (typeof console != 'undefined') {
      console.log(e.stack)
    }
    self.postMessage({type: 'error', data: e.toString()})
  }
}

debug('fetching asmjs code...')

//try {
//  importScripts('./pypy-js.js');
//} catch (e) {
//  onerror(e)
//}

var xhr = new XMLHttpRequest();
xhr.open('GET', './pypy-js.js', false);
xhr.send(null);
if (xhr.status >= 400) {
  onerror('failed to load pypy-js.js');
}

debug('loading asmjs code...')

eval(xhr.responseText)

self.addEventListener('message', function(e) {
  var msg = e.data;
  switch (msg.type) {
    case 'input':
      pypy_push_input(msg.data);
      break;
  }
})
<|endoftext|>


<commit_before>'use strict';
// Is there a better way to pick up window globals?
var Backbone = (window && window.Backbone) || require('backbone');
var _ = (window && window._) || require('underscore');
var querystring = require('qs');
var diff = require('deep-diff');

/**
 * Backbone.History overrides.
 * @type {Backbone.History}
 */
var QueryHistory = Backbone.History.extend( /** @lends QueryHistory# **/{

  /**
   * Override history constructor to init some properties and set the embedded query
   * model listener.
   * @constructs
   * @type {Backbone.History}
   */
  constructor: function() {
    this.previousQuery = {};
    this.queryHandlers = [];
    this.listenTo(this.query, 'change', this.onQueryModelChange);
    Backbone.History.call(this);
  },

  /**
   * Extracts querystrings from routes.
   * @type {RegExp}
   */
  queryMatcher: /^([^?]*?)(?:\?([\s\S]*))?$/,

  /**
   * Model emcompassing current query state. You can read and set properties
   * on this Model and `Backbone.history.navigate()` will automatically be called.
   * @type {Backbone.Model}
   */
  query: new Backbone.Model(),

  /**
   * Parse a fragment into a query object and call handlers matching.
   * @param {String} fragment Route fragment.
   * @param {Object} options Navigation options.
   */
  loadQuery: function(fragment, options) {
    var query = this._fragmentToQueryObject(fragment);
    var previous = this.previousQuery;

    // Save previous query.
    this.previousQuery = query;

    // Diff new and old queries.
    var diffs = this._getDiffs(previous, query);
    if (!diffs.length) return;

    // Set embedded model to new query object, firing 'change' events.
    this.stopListening(this.query, 'change', this.onQueryModelChange);
    this.query.set(query);
    this.listenTo(this.query, 'change', this.onQueryModelChange);

    // Call each function that subscribes to these items.
    // This is intentional, rather than fire events on each changed item;
    // this way, you don't have to debounce your handlers since they are only called once,
    // even if multiple query items change.
    _.each(this.queryHandlers, function(handler) {
      var intersections = _.intersection(diffs, handler.bindings);
      if (intersections.length) {
        handler.callback(fragment, _.pick(query, intersections));
      }
    });
  },

  /**
   * Override loadUrl & watch return value. Trigger event if no route was matched.
   * @return {Boolean} True if a route was matched.
   */
  loadUrl: function() {
    var matched = Backbone.History.prototype.loadUrl.apply(this, arguments);
    if (!matched) {
      this.trigger('routeNotFound', arguments);
    }
    return matched;
  },

  /**
   * Add loadQuery hook.
   * Add 'forceTrigger' option that will trigger a route regardless of whether
   * or not we're already at that route.
   * Also trigger '[before, after]Navigate' event.
   *
   * Backbone.History is the prototype name, Backbone.history is the actual object,
   * but Backbone.History stores the 'started' flag. Whatever.
   * @param {String} fragment History fragment.
   * @param {Object} options  Navigation options.
   */
  navigate: function(fragment, options) {
    if (!Backbone.History.started) return false;

    if (!options) options = {};

    // Throw a navigate route so we can hook to this elsewhere in the app.
    // This is usually the event you'll want to listen to.
    this.trigger('beforeNavigate', fragment, options);

    // Fire querystring routes.
    if (options.trigger) {
      this.loadQuery(fragment, options);
    }

    // Support 'forceTrigger' to trigger a route even if the url hasn't changed.
    // Have to check History.started here if we call loadUrl directly.
    if (options.forceTrigger && this.fragment === fragment) {
      this.loadUrl(fragment);
    } else {
      // Call navigate on prototype since we just overrode it.
      Backbone.History.prototype.navigate.call(this, fragment, options);
    }

    // Throw an 'afterNavigate' route for those who care.
    this.trigger('afterNavigate', fragment, options);
  },

  /**
   * When the query model changes, run all associated routes.
   * @param  {Model}  model   Attached model.
   * @param  {Object} options Change options.
   */
  onQueryModelChange: function(model, options) {
    var fragment = this.fragment || '';
    var oldQS = querystring.stringify(this.previousQuery);
    var newQS = querystring.stringify(model.toJSON());
    this.navigate(fragment.replace(oldQS, newQS), {trigger: true});
  },

  /**
   * Add a query to be tested when the fragment changes.
   * @param  {Array}   bindings  Query keys to listen to.
   * @param  {Function} callback Callback to call when these keys change.
   */
  queryHandler: function(bindings, callback) {
    this.queryHandlers.push({bindings: bindings, callback: callback});
  },

  /**
   * Given two objects, compute their differences and list them.
   * When diffing deep objects, return one string for the object and one for each child.
   * This allows functions to bind to deep properties or its parent.
   * E.g. a change to a.b.c returns ['a', 'a.b', 'a.b.c']
   *
   * This uses DeepDiff (flitbit/diff), which can detect changes deep within objects.
   * We don't use objects in querystrings quite yet, but we do arrays. And that might change.
   *
   * @example
   *   _getDiffs({q: 'foo', deep: {object: 'blah'}}, {q: 'bar', fq: 'foo', deep: {object: 'blah2'}})
   *     -> ['q', 'fq', 'deep', 'deep.object']
   *
   * @param  {Object} lhs Left hand object.
   * @param  {Object} rhs Right hand (new) object.
   * @return {Array}      Array of string differences.
   */
  _getDiffs: function(lhs, rhs) {
    var diffs = diff(lhs, rhs);
    var diffKeys = _.reduce(diffs, function(result, diff) {
      var paths = _.map(diff.path, function(path, i) {
        return _.first(diff.path, i + 1).join('.');
      });
      return result.concat(paths);
    }, []);
    return _.uniq(diffKeys);
  },

  /**
   * Given a fragment, return a query object.
   * @param  {String} fragment Route fragment.
   * @return {Object}          Query object.
   */
  _fragmentToQueryObject: function(fragment) {
    return querystring.parse(this._fragmentToQueryString(fragment));
  },

  /**
   * Given a fragment, return a query string.
   * @param  {String} fragment Route fragment.
   * @return {String}          Query string.
   */
  _fragmentToQueryString: function(fragment) {
    if (!fragment) return '';
    var match = fragment.match(this.queryMatcher);
    return match[2] || '';
  }
});

var RouterProto = Backbone.Router.prototype;
/**
 * Backbone.Router overrides.
 * @type {Backbone.Router}
 */
var QueryRouter = Backbone.Router.extend(/** @lends QueryRouter# */{
  /**
   * Bind query routes.
   *
   * Remember that handlers will only fire once per navigation. If for some reason you'd like
   * a handler to fire for each individual change, bind to the 'change:{key}' events on
   * Backbone.history.query, which is just a Backbone.Model (and fires all of the usual
   * events).
   *
   * They are expected to be attached in the following configuration:
   *
   * ```javascript
   * queryRoutes: [
   *   'key1,key2,key3': 'handlerName',
   *   'q, sort, rows': function() { // ... },
   *   'nested.object': 'deepHandler'
   * ]
   * ```
   */
  _bindRoutes: function() {
    if (!this.queryRoutes) return;
    this.queryRoutes = _.result(this, 'queryRoutes');
    var qRoute, qRoutes = _.keys(this.queryRoutes);
    while ((qRoute = qRoutes.pop()) != null) {
      this.queryHandler(qRoute, this.queryRoutes[qRoute]);
    }
    RouterProto._bindRoutes.apply(this, arguments);
  },

  /**
   * Bind a queryHandler. Very similar to Backbone.Router#route, except that args
   * are provided by Backbone.history#queryHandler, rather than being extracted
   * in the router from the fragment.
   * @param  {String|array}  bindings Query key bindings.
   * @param  {String}   [name]        Listener name.
   * @param  {Function} callback      Listener callback.
   */
  queryHandler: function(bindings, name, callback) {
    bindings = this._normalizeBindings(bindings);
    if (_.isFunction(name)) {
      callback = name;
      name = '';
    }
    if (!callback) callback = this[name];
    var router = this;
    Backbone.history.queryHandler(bindings, function(fragment, args) {
      router.execute(callback, [args]);
      router.trigger.apply(router, ['route:' + name].concat(args));
      router.trigger('route', name, args);
      Backbone.history.trigger('route', router, name, args);
    });
    return this;
  },

  /**
   * Normalize bindings - convert to array and trim whitespace.
   * @param  {String} bindings Bindings definition.
   * @return {Array}           Normalized bindings.
   */
  _normalizeBindings: function(bindings) {
    if (_.isString(bindings)) {
      bindings = bindings.split(',');
    }
    return _.invoke(bindings, 'trim');
  }
});

// Override default Backbone.Router constructor.
Backbone.Router = QueryRouter;

// Replace Backbone.history.
Backbone.history = new QueryHistory();
<commit_msg>Remove forceTrigger and events, should be another plugin<commit_after>'use strict';
// Is there a better way to pick up window globals?
var Backbone = (window && window.Backbone) || require('backbone');
var _ = (window && window._) || require('underscore');
var querystring = require('qs');
var diff = require('deep-diff');

/**
 * Backbone.History overrides.
 * @type {Backbone.History}
 */
var QueryHistory = Backbone.History.extend( /** @lends QueryHistory# **/{

  /**
   * Override history constructor to init some properties and set the embedded query
   * model listener.
   * @constructs
   * @type {Backbone.History}
   */
  constructor: function() {
    this.previousQuery = {};
    this.queryHandlers = [];
    this.listenTo(this.query, 'change', this.onQueryModelChange);
    Backbone.History.call(this);
  },

  /**
   * Extracts querystrings from routes.
   * @type {RegExp}
   */
  queryMatcher: /^([^?]*?)(?:\?([\s\S]*))?$/,

  /**
   * Model emcompassing current query state. You can read and set properties
   * on this Model and `Backbone.history.navigate()` will automatically be called.
   * @type {Backbone.Model}
   */
  query: new Backbone.Model(),

  /**
   * Parse a fragment into a query object and call handlers matching.
   * @param {String} fragment Route fragment.
   * @param {Object} options Navigation options.
   */
  loadQuery: function(fragment, options) {
    var query = this._fragmentToQueryObject(fragment);
    var previous = this.previousQuery;

    // Save previous query.
    this.previousQuery = query;

    // Diff new and old queries.
    var diffs = this._getDiffs(previous, query);
    if (!diffs.length) return;

    // Set embedded model to new query object, firing 'change' events.
    this.stopListening(this.query, 'change', this.onQueryModelChange);
    this.query.set(query);
    this.listenTo(this.query, 'change', this.onQueryModelChange);

    // Call each function that subscribes to these items.
    // This is intentional, rather than fire events on each changed item;
    // this way, you don't have to debounce your handlers since they are only called once,
    // even if multiple query items change.
    _.each(this.queryHandlers, function(handler) {
      var intersections = _.intersection(diffs, handler.bindings);
      if (intersections.length) {
        handler.callback(fragment, _.pick(query, intersections));
      }
    });
  },

  /**
   * Override loadUrl & watch return value. Trigger event if no route was matched.
   * @return {Boolean} True if a route was matched.
   */
  loadUrl: function() {
    var matched = Backbone.History.prototype.loadUrl.apply(this, arguments);
    if (!matched) {
      this.trigger('routeNotFound', arguments);
    }
    return matched;
  },

  /**
   * Add loadQuery hook.
   *
   * @param {String} fragment History fragment.
   * @param {Object} options  Navigation options.
   */
  navigate: function(fragment, options) {
    if (!Backbone.History.started) return false;
    if (!options) options = {};

    // Fire querystring routes.
    if (options.trigger) {
      this.loadQuery(fragment, options);
    }

    // Call navigate on prototype since we just overrode it.
    Backbone.History.prototype.navigate.call(this, fragment, options);
  },

  /**
   * When the query model changes, run all associated routes.
   * @param  {Model}  model   Attached model.
   * @param  {Object} options Change options.
   */
  onQueryModelChange: function(model, options) {
    var fragment = this.fragment || '';
    var oldQS = querystring.stringify(this.previousQuery);
    var newQS = querystring.stringify(model.toJSON());
    this.navigate(fragment.replace(oldQS, newQS), {trigger: true});
  },

  /**
   * Add a query to be tested when the fragment changes.
   * @param  {Array}   bindings  Query keys to listen to.
   * @param  {Function} callback Callback to call when these keys change.
   */
  queryHandler: function(bindings, callback) {
    this.queryHandlers.push({bindings: bindings, callback: callback});
  },

  /**
   * Given two objects, compute their differences and list them.
   * When diffing deep objects, return one string for the object and one for each child.
   * This allows functions to bind to deep properties or its parent.
   * E.g. a change to a.b.c returns ['a', 'a.b', 'a.b.c']
   *
   * This uses DeepDiff (flitbit/diff), which can detect changes deep within objects.
   * We don't use objects in querystrings quite yet, but we do arrays. And that might change.
   *
   * @example
   *   _getDiffs({q: 'foo', deep: {object: 'blah'}}, {q: 'bar', fq: 'foo', deep: {object: 'blah2'}})
   *     -> ['q', 'fq', 'deep', 'deep.object']
   *
   * @param  {Object} lhs Left hand object.
   * @param  {Object} rhs Right hand (new) object.
   * @return {Array}      Array of string differences.
   */
  _getDiffs: function(lhs, rhs) {
    var diffs = diff(lhs, rhs);
    var diffKeys = _.reduce(diffs, function(result, diff) {
      var paths = _.map(diff.path, function(path, i) {
        return _.first(diff.path, i + 1).join('.');
      });
      return result.concat(paths);
    }, []);
    return _.uniq(diffKeys);
  },

  /**
   * Given a fragment, return a query object.
   * @param  {String} fragment Route fragment.
   * @return {Object}          Query object.
   */
  _fragmentToQueryObject: function(fragment) {
    return querystring.parse(this._fragmentToQueryString(fragment));
  },

  /**
   * Given a fragment, return a query string.
   * @param  {String} fragment Route fragment.
   * @return {String}          Query string.
   */
  _fragmentToQueryString: function(fragment) {
    if (!fragment) return '';
    var match = fragment.match(this.queryMatcher);
    return match[2] || '';
  }
});

var RouterProto = Backbone.Router.prototype;
/**
 * Backbone.Router overrides.
 * @type {Backbone.Router}
 */
var QueryRouter = Backbone.Router.extend(/** @lends QueryRouter# */{
  /**
   * Bind query routes.
   *
   * Remember that handlers will only fire once per navigation. If for some reason you'd like
   * a handler to fire for each individual change, bind to the 'change:{key}' events on
   * Backbone.history.query, which is just a Backbone.Model (and fires all of the usual
   * events).
   *
   * They are expected to be attached in the following configuration:
   *
   * ```javascript
   * queryRoutes: [
   *   'key1,key2,key3': 'handlerName',
   *   'q, sort, rows': function() { // ... },
   *   'nested.object': 'deepHandler'
   * ]
   * ```
   */
  _bindRoutes: function() {
    if (!this.queryRoutes) return;
    this.queryRoutes = _.result(this, 'queryRoutes');
    var qRoute, qRoutes = _.keys(this.queryRoutes);
    while ((qRoute = qRoutes.pop()) != null) {
      this.queryHandler(qRoute, this.queryRoutes[qRoute]);
    }
    RouterProto._bindRoutes.apply(this, arguments);
  },

  /**
   * Bind a queryHandler. Very similar to Backbone.Router#route, except that args
   * are provided by Backbone.history#queryHandler, rather than being extracted
   * in the router from the fragment.
   * @param  {String|array}  bindings Query key bindings.
   * @param  {String}   [name]        Listener name.
   * @param  {Function} callback      Listener callback.
   */
  queryHandler: function(bindings, name, callback) {
    bindings = this._normalizeBindings(bindings);
    if (_.isFunction(name)) {
      callback = name;
      name = '';
    }
    if (!callback) callback = this[name];
    var router = this;
    Backbone.history.queryHandler(bindings, function(fragment, args) {
      router.execute(callback, [args]);
      router.trigger.apply(router, ['route:' + name].concat(args));
      router.trigger('route', name, args);
      Backbone.history.trigger('route', router, name, args);
    });
    return this;
  },

  /**
   * Normalize bindings - convert to array and trim whitespace.
   * @param  {String} bindings Bindings definition.
   * @return {Array}           Normalized bindings.
   */
  _normalizeBindings: function(bindings) {
    if (_.isString(bindings)) {
      bindings = bindings.split(',');
    }
    return _.invoke(bindings, 'trim');
  }
});

// Override default Backbone.Router constructor.
Backbone.Router = QueryRouter;

// Replace Backbone.history.
Backbone.history = new QueryHistory();
<|endoftext|>