<commit_before>// ==UserScript==
// @name         Meetup Better Event Exporter
// @namespace    http://boris.joff3.com
// @version      1.0
// @description  Export full Meetup event description to Google Calendar
// @author       Boris Joffe
// @match        http://*.meetup.com/*
// @match        https://*.meetup.com/*
// @grant        none
// ==/UserScript==
/* jshint -W097 */
/* eslint-disable no-console, no-unused-vars */
'use strict';

/*
The MIT License (MIT)

Copyright (c) 2015 Boris Joffe

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

// Util
var DEBUG = false;
function dbg() {
	if (DEBUG)
		console.log.apply(console, arguments);

	return arguments[0];
}

var
	qs = document.querySelector.bind(document),
	err = console.error.bind(console),
	log = console.log.bind(console),
	euc = encodeURIComponent;

function qsv(elmStr, parent) {
	var elm = parent ? parent.querySelector(elmStr) : qs(elmStr);
	if (!elm) err('(qs) Could not get element -', elmStr);
	return elm;
}

function updateExportLink() {
	log('Event Exporter running');

	var
		calLink = qsv('a[href*="google.com/calendar"]'),
		descElm = qsv('#event-description-wrap'),
		desc;

	if (descElm.innerText) {
		desc = descElm.innerText;
	} else {
		// fallback, HTML encoded entities will appear broken
		desc = descElm.innerHTML
		              .replace(/
\s*/g, '\n') // fix newlines
		              .replace(/]*>/g, '[$1] ') // show link urls
		              .replace(/<[^>]*>/g, '');  // strip html tags
	}

	var meetupGroupName = qsv('meta[property="og:title"]').getAttribute('content');

	// Google? doesn't allow calendar links over a certain length
	var leadingText = euc(meetupGroupName + '\n' + location.href + '\n\n');
	var leadingTextTruncated = euc('[Details cut off]\n' + location.href + '\n');
	var linkWithoutDetails = calLink.href.replace(/details=([^&]*)/, 'details=');

	// limit seems to be around 2000-3000 chars but may not be a full url limit and seems to vary depending on the Meetup content
	var FULL_LINK_MAX_CHARS = 2300; //2543;
	var FULL_DETAILS_MAX_CHARS = FULL_LINK_MAX_CHARS - linkWithoutDetails.length;
	var DETAILS_MAX_CHARS = FULL_DETAILS_MAX_CHARS - leadingText.length;
	var ELLIPSIS = '...';

	var isTruncated = false;
	dbg('original desc length =', euc(desc).length);
	if (euc(desc).length > DETAILS_MAX_CHARS) {
		dbg('truncating');
		desc = desc.replace(/(\s)\s*/g, '$1');    // condense whitespace
		desc = leadingTextTruncated + euc(desc);  // inform user about truncation
		desc = desc.slice(0, FULL_DETAILS_MAX_CHARS - ELLIPSIS.length) + ELLIPSIS;
		isTruncated = true;
	} else {
		dbg('not truncating');
		desc = leadingText + euc(desc);
	}

	calLink.href = linkWithoutDetails.replace(/details=/, 'details=' + desc);
	dbg('desc text len =', desc.length);
	dbg('full link length =', calLink.href.length);

	calLink.target = '_blank';

	// show color change to notify user that link changed
	var lightGreen = 'rgba(0, 255, 0, 0.1)';
	var lightYellow = 'rgba(255, 255, 0, 0.1)';
	var linkColor = isTruncated ? lightYellow : lightGreen;
	calLink.parentNode.style.backgroundColor = linkColor;
	qsv('#addToCalAction').style.backgroundColor = linkColor;
}

window.addEventListener('load', updateExportLink, true);
<commit_msg>add text saying whether description is truncated (turned off for now)<commit_after>// ==UserScript==
// @name         Meetup Better Event Exporter
// @namespace    http://boris.joff3.com
// @version      1.0
// @description  Export full Meetup event description to Google Calendar
// @author       Boris Joffe
// @match        http://*.meetup.com/*
// @match        https://*.meetup.com/*
// @grant        none
// ==/UserScript==
/* jshint -W097 */
/* eslint-disable no-console, no-unused-vars */
'use strict';

/*
The MIT License (MIT)

Copyright (c) 2015 Boris Joffe

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

// Util
var DEBUG = false;
function dbg() {
	if (DEBUG)
		console.log.apply(console, arguments);

	return arguments[0];
}

var
	qs = document.querySelector.bind(document),
	err = console.error.bind(console),
	log = console.log.bind(console),
	euc = encodeURIComponent;

function qsv(elmStr, parent) {
	var elm = parent ? parent.querySelector(elmStr) : qs(elmStr);
	if (!elm) err('(qs) Could not get element -', elmStr);
	return elm;
}

function updateExportLink() {
	log('Event Exporter running');

	var
		calLink = qsv('a[href*="google.com/calendar"]'),
		descElm = qsv('#event-description-wrap'),
		desc;

	if (descElm.innerText) {
		desc = descElm.innerText;
	} else {
		// fallback, HTML encoded entities will appear broken
		desc = descElm.innerHTML
		              .replace(/
\s*/g, '\n') // fix newlines
		              .replace(/]*>/g, '[$1] ') // show link urls
		              .replace(/<[^>]*>/g, '');  // strip html tags
	}

	var meetupGroupName = qsv('meta[property="og:title"]').getAttribute('content');

	// Google? doesn't allow calendar links over a certain length
	var leadingText = euc(meetupGroupName + '\n' + location.href + '\n\n');
	var leadingTextTruncated = euc('[Details cut off]\n' + location.href + '\n');
	var linkWithoutDetails = calLink.href.replace(/details=([^&]*)/, 'details=');

	// limit seems to be around 2000-3000 chars but may not be a full url limit and seems to vary depending on the Meetup content
	var FULL_LINK_MAX_CHARS = 2300; //2543;
	var FULL_DETAILS_MAX_CHARS = FULL_LINK_MAX_CHARS - linkWithoutDetails.length;
	var DETAILS_MAX_CHARS = FULL_DETAILS_MAX_CHARS - leadingText.length;
	var ELLIPSIS = '...';

	var isTruncated = false;
	dbg('original desc length =', euc(desc).length);
	if (euc(desc).length > DETAILS_MAX_CHARS) {
		dbg('truncating');
		desc = desc.replace(/(\s)\s*/g, '$1');    // condense whitespace
		desc = leadingTextTruncated + euc(desc);  // inform user about truncation
		desc = desc.slice(0, FULL_DETAILS_MAX_CHARS - ELLIPSIS.length) + ELLIPSIS;
		isTruncated = true;
	} else {
		dbg('not truncating');
		desc = leadingText + euc(desc);
	}

	calLink.href = linkWithoutDetails.replace(/details=/, 'details=' + desc);
	//calLink.innerHTML += isTruncated ? ' (truncated)' : ' (full)';
	dbg('desc text len =', desc.length);
	dbg('full link length =', calLink.href.length);

	calLink.target = '_blank';

	// show color change to notify user that link changed
	var lightGreen = 'rgba(0, 255, 0, 0.1)';
	var lightYellow = 'rgba(255, 255, 0, 0.1)';
	var linkColor = isTruncated ? lightYellow : lightGreen;
	calLink.parentNode.style.backgroundColor = linkColor;
	qsv('#addToCalAction').style.backgroundColor = linkColor;
}

window.addEventListener('load', updateExportLink, true);
<|endoftext|>


<commit_before>!(function ($) {

  var UWidget = function (element, options) {
    this.init($(element), options);
  };

  UWidget.prototype = {
    options: {
      url: null,
      handler: null,
      template: null,
      sort: {
        enabled: false,
        name: 'sort',
        values: ['id', 'date'],
        labels: ['Identifier', 'Date']
      },
      direction: {
        enabled: false,
        name: 'direction',
        values: ['desc', 'asc'],
        labels: ['Descending', 'Ascending']
      },
      filters: {
        ebabled: false,
        name: 'filters',
        values: [],
        labels: []
      }
    },

    init: function ($element, options) {
      this.$element = $element;
      this.options = $.extend(true, {}, this.options, options);
      this._xhrCache = {};

      if (!this.options.url || !this.options.handler || !this.options.template)
        throw new Error('You must define a widget url, an ajax handler and a template');

      this
        ._initActions()
        ._initFromDOM()
        .fetch();
    },

    _initActions: function () {
      var i, checked;
      this.$actions = $('');

      if (this.options.sort.enabled) {
        this.$sort = $('<select name="'+ this.options.sort.name +'"></select>')
          .on('change', false, $.proxy(this._updateActions, this));

        for (i = 0; i < this.options.sort.values.length; i++)
          this.$sort.append('<option value="' + this.options.sort.values[i] + '">' + this.options.sort.labels[i] + '</option>');

        this.$actions.append(this.$sort);
      }

      if (this.options.direction.enabled) {
        this.$direction = $('<select name="'+ this.options.direction.name +'"></select>')
          .on('change', false, $.proxy(this._updateActions, this));

        for (i = 0; i < this.options.direction.values.length; i++)
          this.$direction.append('<option value="' + this.options.direction.values[i] + '">' + this.options.direction.labels[i] + '</option>');

        this.$actions.append(this.$direction);
      }

      if (this.options.filters.enabled) {
        this.$filters = $('')
          .on('change', false, $.proxy(this._updateActions, this));

        for (i = 0; i < this.options.filters.values.length; i++) {
          checked = this.$element.data('filters') && new RegExp(this.options.filters.labels[i], 'i').test(this.$element.data('filters'));
          this.$filters.append(this.options.filters.labels[i] + ' <input type="checkbox" name="filters[]" value="' + this.options.filters.values[i] + '" ' + (checked ? 'checked' : '') + '/>');
        }

        this.$actions.append(this.$filters);
      }

      this.$container = $('

');
      this.$info = $('UWidget');

      this.$element
        .append(this.$actions)
        .append(this.$container)
        .append(this.$info);

      this._updateActions();

      return this;
    },

    _initFromDOM: function () {
      if (this.$element.data('width'))
        this.$element.css('width', this.$element.data('width'));

      if (this.$element.data('height')) {
        this.$element.css('height', this.$element.data('height'));
        this.$container.css('height', this.$element.height() - this.$actions.height() - this.$info.height());
      }

      return this;
    },

    _updateActions: function () {
      if (this.options.sort.enabled)
        this.$element.data('sort', this.$sort.val());

      if (this.options.direction.enabled)
        this.$element.data('direction', this.$direction.val());

      if (this.options.filters.enabled) {
        var val = [];

        this.$actions.find('input[type=checkbox]:checked').each(function () {
          val.push($(this).val());
        });

        this.$element.data('filters', val.join(', '));
      }

      this.fetch();
    },

    getUrl: function () {
      var url = ('function' === typeof this.options.url ? this.options.url(this.options) : this.options.url) + '?uwidget',
        options = ['sort', 'direction', 'filters'],
        value = '';

      for (var i = 0; i < options.length; i++) {
        value = this.$element.data([options[i]] + '');

        if (this.options[options[i]].enabled && value.length)
          url += '&' + this.options[options[i]].name + '=' + value;
      }

      return url;
    },

    fetch: function () {
      var that = this,
        url = that.getUrl();

      this.$element
        .removeClass('error')
        .removeClass('fetched')
        .addClass('fetching');

      if ('undefined' !== typeof this._xhrCache[url])
        return this._updateCollection.apply(this, this._xhrCache[url]);

      $.ajax($.extend(true, {}, {
        url: url
      }, that.$element.data('remoteOptions')))
        .done(function () {
          that._updateCollection.apply(that, arguments);
          that._xhrCache[url] = arguments;
        })
        .fail(function () {
          that.$container.addClass('error');
        })
        .always(function () {
          that.$container.removeClass('fetching');
        });
    },

    _updateCollection: function (collection) {
      this.$container.html('').addClass('fetched');
      collection = this.options.handler.apply(this, arguments);

      for (var i = 0; i < collection.length; i++)
        this.$container.append(tmpl(this.options.template, collection[i]));
    }
  };

  $.fn.UWidget = function (options) {
    return new UWidget(this, options);
  };

  // Simple JavaScript Templating
  // John Resig - http://ejohn.org/ - MIT Licensed
  (function(){
    var cache = {};

    this.tmpl = function tmpl(str, data){
      // Figure out if we're getting a template, or if we need to
      // load the template - and be sure to cache the result.
      var fn = !/\W/.test(str) ?
        cache[str] = cache[str] ||
          tmpl(document.getElementById(str).innerHTML) :

        // Generate a reusable function that will serve as a template
        // generator (and which will be cached).
        new Function("obj",
          "var p=[],print=function(){p.push.apply(p,arguments);};" +

          // Introduce the data as local variables using with(){}
          "with(obj){p.push('" +

          // Convert the template into pure JavaScript
          str
            .replace(/[\r\t\n]/g, " ")
            .split("<%").join("\t")
            .replace(/((^|%>)[^\t]*)'/g, "$1\r")
            .replace(/\t=(.*?)%>/g, "',$1,'")
            .split("\t").join("');")
            .split("%>").join("p.push('")
            .split("\r").join("\\'")
          + "');}return p.join('');");

      // Provide some basic currying to the user
      return data ? fn(data) : fn;
    };
  })();
})(window.jQuery);
<commit_msg>- fixed API querry args<commit_after>!(function ($) {

  var UWidget = function (element, options) {
    this.init($(element), options);
  };

  UWidget.prototype = {
    options: {
      url: null,
      handler: null,
      template: null,
      sort: {
        enabled: false,
        name: 'sort',
        values: ['id', 'date'],
        labels: ['Identifier', 'Date']
      },
      direction: {
        enabled: false,
        name: 'direction',
        values: ['desc', 'asc'],
        labels: ['Descending', 'Ascending']
      },
      filters: {
        ebabled: false,
        name: 'filters',
        values: [],
        labels: []
      }
    },

    init: function ($element, options) {
      this.$element = $element;
      this.options = $.extend(true, {}, this.options, options);
      this._xhrCache = {};

      if (!this.options.url || !this.options.handler || !this.options.template)
        throw new Error('You must define a widget url, an ajax handler and a template');

      this
        ._initActions()
        ._initFromDOM()
        .fetch();
    },

    _initActions: function () {
      var i, checked;
      this.$actions = $('');

      if (this.options.sort.enabled) {
        this.$sort = $('<select name="'+ this.options.sort.name +'"></select>')
          .on('change', false, $.proxy(this._updateActions, this));

        for (i = 0; i < this.options.sort.values.length; i++)
          this.$sort.append('<option value="' + this.options.sort.values[i] + '">' + this.options.sort.labels[i] + '</option>');

        this.$actions.append(this.$sort);
      }

      if (this.options.direction.enabled) {
        this.$direction = $('<select name="'+ this.options.direction.name +'"></select>')
          .on('change', false, $.proxy(this._updateActions, this));

        for (i = 0; i < this.options.direction.values.length; i++)
          this.$direction.append('<option value="' + this.options.direction.values[i] + '">' + this.options.direction.labels[i] + '</option>');

        this.$actions.append(this.$direction);
      }

      if (this.options.filters.enabled) {
        this.$filters = $('')
          .on('change', false, $.proxy(this._updateActions, this));

        for (i = 0; i < this.options.filters.values.length; i++) {
          checked = this.$element.data('filters') && new RegExp(this.options.filters.labels[i], 'i').test(this.$element.data('filters'));
          this.$filters.append(this.options.filters.labels[i] + ' <input type="checkbox" name="filters[]" value="' + this.options.filters.values[i] + '" ' + (checked ? 'checked' : '') + '/>');
        }

        this.$actions.append(this.$filters);
      }

      this.$container = $('

');
      this.$info = $('UWidget');

      this.$element
        .append(this.$actions)
        .append(this.$container)
        .append(this.$info);

      this._updateActions();

      return this;
    },

    _initFromDOM: function () {
      if (this.$element.data('width'))
        this.$element.css('width', this.$element.data('width'));

      if (this.$element.data('height')) {
        this.$element.css('height', this.$element.data('height'));
        this.$container.css('height', this.$element.height() - this.$actions.height() - this.$info.height());
      }

      return this;
    },

    _updateActions: function () {
      if (this.options.sort.enabled)
        this.$element.data('sort', this.$sort.val());

      if (this.options.direction.enabled)
        this.$element.data('direction', this.$direction.val());

      if (this.options.filters.enabled) {
        var val = [];

        this.$actions.find('input[type=checkbox]:checked').each(function () {
          val.push($(this).val());
        });

        this.$element.data('filters', val.join(', '));
      }

      this.fetch();
    },

    getUrl: function () {
      var url = ('function' === typeof this.options.url ? this.options.url(this.options) : this.options.url),
        options = ['sort', 'direction', 'filters'],
        value = '';

      url += -1 !== url.indexOf('?') ? '&uwidget' : '?uwidget';

      for (var i = 0; i < options.length; i++) {
        value = this.$element.data([options[i]] + '');

        if (this.options[options[i]].enabled && value.length)
          url += '&' + this.options[options[i]].name + '=' + value;
      }

      return url;
    },

    fetch: function () {
      var that = this,
        url = that.getUrl();

      this.$element
        .removeClass('error')
        .removeClass('fetched')
        .addClass('fetching');

      if ('undefined' !== typeof this._xhrCache[url])
        return this._updateCollection.apply(this, this._xhrCache[url]);

      $.ajax($.extend(true, {}, {
        url: url
      }, that.$element.data('remoteOptions')))
        .done(function () {
          that._updateCollection.apply(that, arguments);
          that._xhrCache[url] = arguments;
        })
        .fail(function () {
          that.$container.addClass('error');
        })
        .always(function () {
          that.$container.removeClass('fetching');
        });
    },

    _updateCollection: function (collection) {
      this.$container.html('').addClass('fetched');
      collection = this.options.handler.apply(this, arguments);

      for (var i = 0; i < collection.length; i++)
        this.$container.append(tmpl(this.options.template, collection[i]));
    }
  };

  $.fn.UWidget = function (options) {
    return new UWidget(this, options);
  };

  // Simple JavaScript Templating
  // John Resig - http://ejohn.org/ - MIT Licensed
  (function(){
    var cache = {};

    this.tmpl = function tmpl(str, data){
      // Figure out if we're getting a template, or if we need to
      // load the template - and be sure to cache the result.
      var fn = !/\W/.test(str) ?
        cache[str] = cache[str] ||
          tmpl(document.getElementById(str).innerHTML) :

        // Generate a reusable function that will serve as a template
        // generator (and which will be cached).
        new Function("obj",
          "var p=[],print=function(){p.push.apply(p,arguments);};" +

          // Introduce the data as local variables using with(){}
          "with(obj){p.push('" +

          // Convert the template into pure JavaScript
          str
            .replace(/[\r\t\n]/g, " ")
            .split("<%").join("\t")
            .replace(/((^|%>)[^\t]*)'/g, "$1\r")
            .replace(/\t=(.*?)%>/g, "',$1,'")
            .split("\t").join("');")
            .split("%>").join("p.push('")
            .split("\r").join("\\'")
          + "');}return p.join('');");

      // Provide some basic currying to the user
      return data ? fn(data) : fn;
    };
  })();
})(window.jQuery);
<|endoftext|>


<commit_before>(function(){
var mod = angular.module('caspy.transaction', ['caspy.api', 'caspy.ui', 'generic']);

mod.factory('TransactionService', ['ResourceWrapper', 'caspyAPI',
    function(ResourceWrapper, caspyAPI) {
        function splitcmp(a, b) {
            if (0 < a.amount && 0 < b.amount)
                return 1/a.amount - 1/b.amount;
            return a.amount - b.amount;
        }

        function mapTransactions(transactions) {
            return transactions.map(function(xdata) {
                var xact = {
                    'date': xdata.date,
                    'description': xdata.description,
                    'splits': xdata.splits.sort(splitcmp)
                };
                return xact;
            });
        }

        return function(book_id) {
            var res = caspyAPI.get_resource('transaction', {'book_id': book_id});
            var rw = new ResourceWrapper(res, 'transaction_id');
            rw.orig_all = rw.all;
            rw.all = function() {
                return this.orig_all().then(mapTransactions);
            }
            return rw;
        };
    }]
);

mod.controller('TransactionController'
    ,['$injector'
    , '$routeParams'
    , 'ListControllerMixin'
    , 'TransactionService'
    , function($injector
             , $routeParams
             , ListControllerMixin
             , TransactionService
        ) {
        $injector.invoke(ListControllerMixin, this);
        var ref = this;
        this.book_id = $routeParams['book_id'];
        this.dataservice = TransactionService(this.book_id);
        this.assign('transactions', this.dataservice.all());
        this.pk = 'transaction_id';
    }]
);

mod.controller('TransactionEditController'
    ,['$scope', 'focus',
    function($scope, focus) {
        var ctrl = this;
        this.splits = function(splits) {
            if (arguments.length)
                $scope.transaction.splits = splits;
            return $scope.transaction.splits;
        };
        this.addSplit = function addSplit(amount) {
            var splitObj = {
                     'amount': amount
                    ,'status': 'n'
                    ,'number': ''
                    ,'description': ''
                };
            splitObj.auto = true;
            this.splits().push(splitObj);
            if (arguments.length)
                focus('split.auto');
        };

        function nonzero(split) {
            return split.amount || split.auto;
        }

        this.onSplitChange = function(split) {
            split.auto = false;
            var total = 0;
            var auto;
            var splits = this.splits(this.splits().filter(nonzero));
            splits.forEach(function(s, i) {
                if (s.auto)
                    auto = i;
                else
                    total += +s.amount;
            });
            if (Math.abs(total) >= 0.1) {
                if (typeof auto !== 'undefined')
                    splits[auto].amount = -total;
                else
                    this.addSplit(-total);
            } else {
                splits.splice(auto, 1);
            }
        };
        this.onTransactionChange = function() {
            if (typeof this.splits() === 'undefined')
                this.splits([]);
            if (0 == this.splits().length)
                this.addSplit();
            focus("cspFocus == 'date'");
        }
        $scope.$watch('transaction', function() {
            if ($scope.transaction)
                ctrl.onTransactionChange();
        });
    }]
);

mod.directive('cspTransactionEdit', function() {
    return {
          scope: {
            transaction: '='
          }
        , controller: 'TransactionEditController'
        , templateUrl: 'partials/transaction/transaction-edit.html'
    };
});

})();
<commit_msg>Use new init mechanism for transactions<commit_after>(function(){
var mod = angular.module('caspy.transaction', ['caspy.api', 'caspy.ui', 'generic']);

mod.factory('TransactionService', ['ResourceWrapper', 'caspyAPI',
    function(ResourceWrapper, caspyAPI) {
        function splitcmp(a, b) {
            if (0 < a.amount && 0 < b.amount)
                return 1/a.amount - 1/b.amount;
            return a.amount - b.amount;
        }

        function mapTransactions(transactions) {
            return transactions.map(function(xdata) {
                var xact = {
                    'date': xdata.date,
                    'description': xdata.description,
                    'splits': xdata.splits.sort(splitcmp)
                };
                return xact;
            });
        }

        return function(book_id) {
            var res = caspyAPI.get_resource('transaction', {'book_id': book_id});
            var rw = new ResourceWrapper(res, 'transaction_id');
            rw.orig_all = rw.all;
            rw.all = function() {
                return this.orig_all().then(mapTransactions);
            }
            return rw;
        };
    }]
);

mod.controller('TransactionController'
    ,['$injector'
    , '$routeParams'
    , 'ListControllerMixin'
    , 'TransactionService'
    , function($injector
             , $routeParams
             , ListControllerMixin
             , TransactionService
        ) {
        $injector.invoke(ListControllerMixin, this);
        var ref = this;
        this.book_id = $routeParams['book_id'];
        this.dataservice = TransactionService(this.book_id);
        this.assign('transactions', this.dataservice.all());
        this.pk = 'transaction_id';
        this.newitem = function() { return {splits: []}; };
    }]
);

mod.controller('TransactionEditController'
    ,['$scope', 'focus',
    function($scope, focus) {
        var ctrl = this;
        this.splits = function(splits) {
            if (arguments.length)
                $scope.transaction.splits = splits;
            return $scope.transaction.splits;
        };
        this.addSplit = function addSplit(amount) {
            var splitObj = {
                     'amount': amount
                    ,'status': 'n'
                    ,'number': ''
                    ,'description': ''
                };
            splitObj.auto = true;
            this.splits().push(splitObj);
            if (arguments.length)
                focus('split.auto');
        };

        function nonzero(split) {
            return split.amount || split.auto;
        }

        this.onSplitChange = function(split) {
            split.auto = false;
            var total = 0;
            var auto;
            var splits = this.splits(this.splits().filter(nonzero));
            splits.forEach(function(s, i) {
                if (s.auto)
                    auto = i;
                else
                    total += +s.amount;
            });
            if (Math.abs(total) >= 0.1) {
                if (typeof auto !== 'undefined')
                    splits[auto].amount = -total;
                else
                    this.addSplit(-total);
            } else {
                splits.splice(auto, 1);
            }
        };
        this.onTransactionChange = function() {
            if (0 == this.splits().length)
                this.addSplit();
            focus("cspFocus == 'date'");
        }
        $scope.$watch('transaction', function() {
            if ($scope.transaction)
                ctrl.onTransactionChange();
        });
    }]
);

mod.directive('cspTransactionEdit', function() {
    return {
          scope: {
            transaction: '='
          }
        , controller: 'TransactionEditController'
        , templateUrl: 'partials/transaction/transaction-edit.html'
    };
});

})();
<|endoftext|>


<commit_before>'use strict';
class MenuList{

    constructor() {
        this._price = 4;
        this._basePrice = 0.5;
        this._discountPrice = 1;
    }

    sendOne() {
        //send to somewhere
    }

    sendTwo() {
        //send to somewhere
    }

    calculateTotalPrice(isSpecailDeal) {
        let total = 0;

        if (isSpecailDeal) {
            total = this.calculateCommonPrice(total);

            total += this._price * 0.95;

            this.sendOne();
        } else {
            total = this.calculateCommonPrice(total);

            total += this._price * 0.8;

            this.sendTwo();
        }

        return total;
    }

    calculateCommonPrice(total) {
        total += this._basePrice;
        total -= this._discountPrice;
        return total;
    }
}
module.exports = MenuList;
<commit_msg>[Bobo | Yangjie] [Consolidate Duplicate Conditional Fragments] Move common code before conditional.<commit_after>'use strict';
class MenuList{

    constructor() {
        this._price = 4;
        this._basePrice = 0.5;
        this._discountPrice = 1;
    }

    sendOne() {
        //send to somewhere
    }

    sendTwo() {
        //send to somewhere
    }

    calculateTotalPrice(isSpecailDeal) {
        let total = 0;

        total = this.calculateCommonPrice(total);

        if (isSpecailDeal) {
            total += this._price * 0.95;

            this.sendOne();
        } else {
            total += this._price * 0.8;

            this.sendTwo();
        }

        return total;
    }

    calculateCommonPrice(total) {
        total += this._basePrice;
        total -= this._discountPrice;
        return total;
    }
}
module.exports = MenuList;
<|endoftext|>


<commit_before>/**
 * @name Agenda Editor
 * @description Edit the JSON file with the data of the Computer Club Medical Systems (CCMS) meetings.
 * @author Ton van Lankveld (ton.van.lankveld@philips.com)
 * @version 0.0.1 (2016-03-04)
 *
 * Used library: jQuery 1.11.3 (http://jquery.com/)
 *               jQuery plugin: jquery.json 2.5.1 (https://github.com/krinkle/jquery-json)
 *
 * Documentation: JsDoc 3 Toolkit (http://usejsdoc.org/)
 */

/**
* @function
* @name blinkServerIndicator
* @description Let the server indictor blink one time.
* @param {string} status - Server status: 'ok' | 'fault'
* @returns None
*/
function blinkServerIndicator(status) {
    "use strict"
    if ((status === 'ok') || (status === 'fault')) {
        var trans = $('#ServerIndicator').addClass(status);
        setTimeout(function() {
        trans.removeClass(status);
    }, 1000);
    }
    return;
}

/**
* @function
* @name buildHTMLagendaTable
* @description Build the HTML agenda table
* @param {array} agendaArray - Matrix with the data of the meetings
* @returns {string} HTMLout
*/
function buildHTMLagendaTable(agendaArray) {
    "use strict";
    var HTMLout = "";
    var HTMLtableBegin = "
\n
Data van de komende bijeenkomsten
\n
\n
	Datum	Tijd	Onderwerp	Groep	Locatie	Contactpersoon
\n
\n
";
    var HTMLtbody = "";
    var HTMLtableEnd = "
\n
";
    var HTMLrowOdd = "";
    var HTMLrowEven = "";
    var oTRoTDRS2 = "
";
    var cTDoTDRS2 = "	";
    var bttnEdit = "";
    var bttnDel = "";
    var meetingIso8601Str = "";
    var meetingDateStr = "";
    var SaST = ""; // Start and Stop Time of meeting

    var NoR = agendaArray.length; // Number of Rows
    var i = 0; // Row number
    while (i < NoR) {
        HTMLrowOdd = "";
        HTMLrowEven = "";
        bttnEdit = "<button id=\'edit" + (i+1) +  "\' type=\'button\'>Wijzig</button>";
        bttnDel = "<button id=\'del" + (i+1) +  "\' type=\'button\'>Verwijder</button>";
        meetingIso8601Str = (agendaArray[i].start).substring(0,10);
        meetingDateStr = iso8601toStringNl(meetingIso8601Str);
        SaST = (agendaArray[i].start).substring(11,16) + " - " + (agendaArray[i].end).substring(11,16) + " uur";
        HTMLrowOdd = oTRoTDRS2 + bttnEdit + cTDoTDRS2 + meetingDateStr + cTDoTDRS2 + SaST + "	" + agendaArray[i].onderwerp + "	" + agendaArray[i].groep + cTDoTDRS2 + agendaArray[i].location + "	" + agendaArray[i].contact + cTDoTDRS2 + bttnDel + "
\n";
        HTMLrowEven = "
" + agendaArray[i].subject + "	" + agendaArray[i].group + "	" + agendaArray[i].email + "
\n";
        HTMLtbody = HTMLtbody + HTMLrowOdd + HTMLrowEven;
        i += 1;
    }
    HTMLout = HTMLtableBegin + HTMLtbody + HTMLtableEnd;
    return HTMLout;
}

/**
* @function
* @name deleteMeeting
* @description Delete one row of the agenda
* @param {array} agendaArray - Matrix with the data of the meetings
* @param {int} rowNumber - Number of row to be deleted
* @returns {string} agendaArray or EMPTYARRAY
*/
function deleteMeeting(agendaArray, rowNumber) {
    "use strict";
    var EMPTYARRAY = [];

    var NoR = agendaArray.length;  // Number of Rows
    if (NoR < (rowNumber - 1)) {
        return agendaArray;
    }
    if (NoR < 1) {
        return EMPTYARRAY;
    }
    agendaArray.splice(rowNumber, 1);
    return agendaArray;
}

/**
* @function
* @name sortAgenda
* @description Sort the meetings on date-time, of the 'start'key
* @param {array} agendaArr - Agenda array to be sorted
* @return {array} agendaArr - Sorted agenda array
*/
function sortAgenda(agendaArr) {
    "use strict";
    if (agendaArr.length < 2) {
        return agendaArr;
    }
    agendaArr.sort(function(a, b) {
        var dateA = new Date(a.start);
        var dateB = new Date(b.start);
        return dateA - dateB; //sort by date ascending
    });
    return agendaArr;
}

/**
 * @name Main loop
 * @requires jQuery
 */
 "use strict";
 $('section.error').hide();

<commit_msg>Main loop extended<commit_after>/**
 * @name Agenda Editor
 * @description Edit the JSON file with the data of the Computer Club Medical Systems (CCMS) meetings.
 * @author Ton van Lankveld (ton.van.lankveld@philips.com)
 * @version 0.0.1 (2016-03-05)
 *
 * Used library: jQuery 1.11.3 (http://jquery.com/)
 *               jQuery plugin: jquery.json 2.5.1 (https://github.com/krinkle/jquery-json)
 *
 * Documentation: JsDoc 3 Toolkit (http://usejsdoc.org/)
 */

/**
* @function
* @name blinkServerIndicator
* @description Let the server indictor blink one time.
* @param {string} status - Server status: 'ok' | 'fault'
* @returns None
*/
function blinkServerIndicator(status) {
    "use strict"
    if ((status === 'ok') || (status === 'fault')) {
        var trans = $('#ServerIndicator').addClass(status);
        setTimeout(function() {
        trans.removeClass(status);
    }, 1000);
    }
    return;
}

/**
* @function
* @name buildHTMLagendaTable
* @description Build the HTML agenda table
* @param {array} agendaArray - Matrix with the data of the meetings
* @returns {string} HTMLout
*/
function buildHTMLagendaTable(agendaArray) {
    "use strict";
    var HTMLout = "";
    var HTMLtableBegin = "
\n
Data van de komende bijeenkomsten
\n
\n
	Datum	Tijd	Onderwerp	Groep	Locatie	Contactpersoon
\n
\n
";
    var HTMLtbody = "";
    var HTMLtableEnd = "
\n
";
    var HTMLrowOdd = "";
    var HTMLrowEven = "";
    var oTRoTDRS2 = "
";
    var cTDoTDRS2 = "	";
    var bttnEdit = "";
    var bttnDel = "";
    var meetingIso8601Str = "";
    var meetingDateStr = "";
    var SaST = ""; // Start and Stop Time of meeting

    var NoR = agendaArray.length; // Number of Rows
    var i = 0; // Row number
    while (i < NoR) {
        HTMLrowOdd = "";
        HTMLrowEven = "";
        bttnEdit = "<button id=\'edit" + (i+1) +  "\' type=\'button\'>Wijzig</button>";
        bttnDel = "<button id=\'del" + (i+1) +  "\' type=\'button\'>Verwijder</button>";
        meetingIso8601Str = (agendaArray[i].start).substring(0,10);
        meetingDateStr = iso8601toStringNl(meetingIso8601Str);
        SaST = (agendaArray[i].start).substring(11,16) + " - " + (agendaArray[i].end).substring(11,16) + " uur";
        HTMLrowOdd = oTRoTDRS2 + bttnEdit + cTDoTDRS2 + meetingDateStr + cTDoTDRS2 + SaST + "	" + agendaArray[i].onderwerp + "	" + agendaArray[i].groep + cTDoTDRS2 + agendaArray[i].location + "	" + agendaArray[i].contact + cTDoTDRS2 + bttnDel + "
\n";
        HTMLrowEven = "
" + agendaArray[i].subject + "	" + agendaArray[i].group + "	" + agendaArray[i].email + "
\n";
        HTMLtbody = HTMLtbody + HTMLrowOdd + HTMLrowEven;
        i += 1;
    }
    HTMLout = HTMLtableBegin + HTMLtbody + HTMLtableEnd;
    return HTMLout;
}

/**
* @function
* @name deleteMeeting
* @description Delete one row of the agenda
* @param {array} agendaArray - Matrix with the data of the meetings
* @param {int} rowNumber - Number of row to be deleted
* @returns {string} agendaArray or EMPTYARRAY
*/
function deleteMeeting(agendaArray, rowNumber) {
    "use strict";
    var EMPTYARRAY = [];

    var NoR = agendaArray.length;  // Number of Rows
    if (NoR < (rowNumber - 1)) {
        return agendaArray;
    }
    if (NoR < 1) {
        return EMPTYARRAY;
    }
    agendaArray.splice(rowNumber, 1);
    return agendaArray;
}

/**
* @function
* @name sortAgenda
* @description Sort the meetings on date-time, of the 'start'key
* @param {array} agendaArr - Agenda array to be sorted
* @return {array} agendaArr - Sorted agenda array
*/
function sortAgenda(agendaArr) {
    "use strict";
    if (agendaArr.length < 2) {
        return agendaArr;
    }
    agendaArr.sort(function(a, b) {
        var dateA = new Date(a.start);
        var dateB = new Date(b.start);
        return dateA - dateB; //sort by date ascending
    });
    return agendaArr;
}

/**
 * @name Main loop
 * @requires jQuery
 */
    "use strict";
    var JSONFILEPATH = "data/ccms-agenda.json";
    var agendaArrayNotSave = [];
    var agendaArrayLoadError = [{start:"",end:"",onderwerp:"De agenda wordt niet van de server opgehaald. Wacht een maar minuten en laad de Editor pagina dan opnieuw.
Als het probleem aanhoudt, neem dan contact op met Ton.",subject:"",groep:"",group:"",location:"",contact:"Ton van Lankveld",email:"websites@ccms-best.nl"}];
    var agendaArrayChecked = [];
    var meetingArray = [];
    var HTMLstr = "";

    $("section.error").hide();
    agendaArrayNotSave = loadJSONfromServer(JSONFILEPATH);
    if (!agendaArrayNotSave) {
        agendaArrayChecked = agendaArrayLoadError;
    } else {
        // Sanatize and validate uploaded agenda data
        for (var i in agendaArrayNotSave) {
            meetingArray = agendaArrayNotSave[i];
            agendaArrayChecked[i] = filterValidateMeetingArray(meetingArray);
        }
    }
    HTMLstr = buildHTMLagendaTable(agendaArrayChecked);
    $("#meetings").prepend(HTMLstr);

<|endoftext|>


<commit_before>function addContextMenuTo(selector) {
    selector = selector + ', ' + selector + ' *';
    var matches;
    ['matches', 'webkitMatchesSelector', 'webkitMatches', 'matchesSelector'].some(function(m) {
        if (m in document.documentElement) {
            matches = m;
            return true;
        }
    });

    var isHovering = false;
    document.addEventListener('mouseover', function(event) {
        if (event.target && event.target[matches](selector)) {
            if (event.path) {
                for (var i = 0; i < event.path.length; i++) {
                    var element = event.path[i];
                    if (element[matches] && element[matches]('a')) {
                        createContextMenu(element.href);
                        isHovering = true;
                        break;
                    }
                }
            }
        } else if (isHovering) {
            isHovering = false;
        }
    });
    document.addEventListener('mouseout', function(event) {
        if (isHovering && (!event.target || !event.target[matches](selector))) {
            isHovering = false;
        }
    });
}

function createContextMenu(linkUrl) {
    if (linkUrl && linkUrl.match('^//.*$')) {
        var tabUrl = window.location.href;
        var patternMatch = tabUrl.match('^(https|http)://(.+)/.*$');
        if (patternMatch) {
            chrome.runtime.sendMessage({action: 'createContextMenu', link: patternMatch[1] + ':' + linkUrl}, function (response) {});
        } else {
            console.log("Could not determine what to do with link: " + linkUrl);
        }
    } else if (linkUrl && linkUrl.match('^/.*$')) {
        var tabUrl = window.location.href;
        var patternMatch = tabUrl.match('^(https|http)://([^/]+)/.*$');
        if (patternMatch) {
            chrome.runtime.sendMessage({action: 'createContextMenu', link: patternMatch[1] + '://' + patternMatch[2] + linkUrl}, function (response) {});
        } else {
            console.log("Could not determine what to do with link: " + linkUrl);
        }
    } else if (linkUrl && (linkUrl.match('^(https|http|acestream|sop)://.+$') || linkUrl.match('^(http|https)://.*\.(torrent|torrent\?.+)$'))) {
        chrome.runtime.sendMessage({action: 'createContextMenu', link: linkUrl}, function (response) {});
    } else if (!linkUrl || linkUrl.trim() == ''
        || (linkUrl && (linkUrl.indexOf('#') == 0
        || linkUrl.indexOf('mailto') == 0
        || linkUrl.indexOf('javascript') == 0
        || linkUrl.indexOf('irc') == 0))) {
        //Do nothing to these links.
    } else {
        console.log("Could not determine what to do with link: " + linkUrl);
    }
}

addContextMenuTo('a');

$(document).ready(function() {
    for (var i = 0; i < allModules.length; i++) {
        var module = allModules[i];
        if (module.createCustomContextMenus) {
            module.createCustomContextMenus();
        }
    }
});
<commit_msg>Added workaround for missing event.path<commit_after>function getEventPath(event) {
    var path = [];
    var node = event.target;
    while(node != document.body) {
        path.push(node);
        node = node.parentNode;
    }
    return path;
}

function addContextMenuTo(selector) {
    selector = selector + ', ' + selector + ' *';
    var matches;
    ['matches', 'webkitMatchesSelector', 'webkitMatches', 'matchesSelector'].some(function(m) {
        if (m in document.documentElement) {
            matches = m;
            return true;
        }
    });

    var isHovering = false;
    document.addEventListener('mouseover', function(event) {
        if (event.target && event.target[matches](selector)) {
            if (!event.path) {
                console.log("Using workaround to get event.path");
                event.path = getEventPath(event);
            }
            for (var i = 0; i < event.path.length; i++) {
                var element = event.path[i];
                if (element[matches] && element[matches]('a')) {
                    createContextMenu(element.href);
                    isHovering = true;
                    break;
                }
            }
        } else if (isHovering) {
            isHovering = false;
        }
    });
    document.addEventListener('mouseout', function(event) {
        if (isHovering && (!event.target || !event.target[matches](selector))) {
            isHovering = false;
        }
    });
}

function createContextMenu(linkUrl) {
    if (linkUrl && linkUrl.match('^//.*$')) {
        var tabUrl = window.location.href;
        var patternMatch = tabUrl.match('^(https|http)://(.+)/.*$');
        if (patternMatch) {
            chrome.runtime.sendMessage({action: 'createContextMenu', link: patternMatch[1] + ':' + linkUrl}, function (response) {});
        } else {
            console.log("Could not determine what to do with link: " + linkUrl);
        }
    } else if (linkUrl && linkUrl.match('^/.*$')) {
        var tabUrl = window.location.href;
        var patternMatch = tabUrl.match('^(https|http)://([^/]+)/.*$');
        if (patternMatch) {
            chrome.runtime.sendMessage({action: 'createContextMenu', link: patternMatch[1] + '://' + patternMatch[2] + linkUrl}, function (response) {});
        } else {
            console.log("Could not determine what to do with link: " + linkUrl);
        }
    } else if (linkUrl && (linkUrl.match('^(https|http|acestream|sop)://.+$') || linkUrl.match('^(http|https)://.*\.(torrent|torrent\?.+)$'))) {
        chrome.runtime.sendMessage({action: 'createContextMenu', link: linkUrl}, function (response) {});
    } else if (!linkUrl || linkUrl.trim() == ''
        || (linkUrl && (linkUrl.indexOf('#') == 0
        || linkUrl.indexOf('mailto') == 0
        || linkUrl.indexOf('javascript') == 0
        || linkUrl.indexOf('irc') == 0))) {
        //Do nothing to these links.
    } else {
        console.log("Could not determine what to do with link: " + linkUrl);
    }
}

addContextMenuTo('a');

$(document).ready(function() {
    for (var i = 0; i < allModules.length; i++) {
        var module = allModules[i];
        if (module.createCustomContextMenus) {
            module.createCustomContextMenus();
        }
    }
});
<|endoftext|>


<commit_before>// Copyright 2002-2014, University of Colorado Boulder

/**
 * Model for a toggle button that sticks when pushed down and pops up when
 * pushed a second time.
 *
 * @author Sam Reid
 * @author John Blanco
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var ButtonModel = require( 'SUN/experimental/buttons/ButtonModel' );
  var DerivedProperty = require( 'AXON/DerivedProperty' );

  /**
   *
   * @param valueA {Object} one value for the toggle
   * @param valueB {Object} other value for the toggle
   * @param valueProperty {Property<Object>} axon property that can be either valueA or valueB.  Would have preferred to call this `property` but it would clash with the property function name.
   * @constructor
   */
  function StickyToggleButtonModel( valueA, valueB, valueProperty ) {
    var thisModel = this;

    this.valueA = valueA;
    this.valueB = valueB;
    this.valueProperty = valueProperty;

    ButtonModel.call( this );

    // When the user releases the toggle button, it should only fire a
    // toggle event if it is not during the same action in which they
    // pressed the button.  Track the state to see if they have already
    // pushed the button.
    // Note: Does this need to be reset when the simulation does "reset
    // all"?  I (sreid) can't find any negative consequences in the user
    // interface of not resetting it, but maybe I missed something. Or maybe
    // it would be safe to reset it anyway.
    this.addProperty( 'readyToToggleUp', false );

    // If the button is untoggled and the user presses it, show it pressed and
    // toggle the state right away.  When the button is released, untoggle the
    // state (unless it was part of the same action that toggled the button
    // down in the first place).
    this.property( 'down' ).link( function( down ) {
      if ( thisModel.enabled && thisModel.over ) {
        if ( down && valueProperty.value === valueA ) {
          thisModel.toggle();
          thisModel.readyToToggleUp = false;
        }
        if ( !down && valueProperty.value === valueB ) {
          if ( thisModel.readyToToggleUp ) {
            thisModel.toggle();
          }
          else {
            thisModel.readyToToggleUp = true;
          }
        }
      }

      //Handle the case where the pointer moved out then up over a toggle button, so it will respond to the next press
      if ( !down && !thisModel.over ) {
        thisModel.readyToToggleUp = true;
      }
    } );

    //Make the button ready to toggle when enabled
    this.property( 'enabled' ).onValue( true, function() {
      thisModel.readyToToggleUp = true;
    } );
  }

  return inherit( ButtonModel, StickyToggleButtonModel, {
    toggle: function() {
      assert && assert( this.valueProperty.value === this.valueA || this.valueProperty.value === this.valueB );
      if ( this.valueProperty.value === this.valueA ) {
        this.valueProperty.value = this.valueB;
      }
      else {
        this.valueProperty.value = this.valueA;
      }
    }
  } );
} );<commit_msg>Lint fix.<commit_after>// Copyright 2002-2014, University of Colorado Boulder

/**
 * Model for a toggle button that sticks when pushed down and pops up when
 * pushed a second time.
 *
 * @author Sam Reid
 * @author John Blanco
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var ButtonModel = require( 'SUN/experimental/buttons/ButtonModel' );

  /**
   *
   * @param valueA {Object} one value for the toggle
   * @param valueB {Object} other value for the toggle
   * @param valueProperty {Property<Object>} axon property that can be either valueA or valueB.  Would have preferred to call this `property` but it would clash with the property function name.
   * @constructor
   */
  function StickyToggleButtonModel( valueA, valueB, valueProperty ) {
    var thisModel = this;

    this.valueA = valueA;
    this.valueB = valueB;
    this.valueProperty = valueProperty;

    ButtonModel.call( this );

    // When the user releases the toggle button, it should only fire a
    // toggle event if it is not during the same action in which they
    // pressed the button.  Track the state to see if they have already
    // pushed the button.
    // Note: Does this need to be reset when the simulation does "reset
    // all"?  I (sreid) can't find any negative consequences in the user
    // interface of not resetting it, but maybe I missed something. Or maybe
    // it would be safe to reset it anyway.
    this.addProperty( 'readyToToggleUp', false );

    // If the button is untoggled and the user presses it, show it pressed and
    // toggle the state right away.  When the button is released, untoggle the
    // state (unless it was part of the same action that toggled the button
    // down in the first place).
    this.property( 'down' ).link( function( down ) {
      if ( thisModel.enabled && thisModel.over ) {
        if ( down && valueProperty.value === valueA ) {
          thisModel.toggle();
          thisModel.readyToToggleUp = false;
        }
        if ( !down && valueProperty.value === valueB ) {
          if ( thisModel.readyToToggleUp ) {
            thisModel.toggle();
          }
          else {
            thisModel.readyToToggleUp = true;
          }
        }
      }

      //Handle the case where the pointer moved out then up over a toggle button, so it will respond to the next press
      if ( !down && !thisModel.over ) {
        thisModel.readyToToggleUp = true;
      }
    } );

    //Make the button ready to toggle when enabled
    this.property( 'enabled' ).onValue( true, function() {
      thisModel.readyToToggleUp = true;
    } );
  }

  return inherit( ButtonModel, StickyToggleButtonModel, {
    toggle: function() {
      assert && assert( this.valueProperty.value === this.valueA || this.valueProperty.value === this.valueB );
      if ( this.valueProperty.value === this.valueA ) {
        this.valueProperty.value = this.valueB;
      }
      else {
        this.valueProperty.value = this.valueA;
      }
    }
  } );
} );<|endoftext|>


<commit_before>// @flow

import type { AppState } from '../redux/redux-setup';

import * as React from 'react';
import { View, Text, StyleSheet, LayoutAnimation } from 'react-native';
import PropTypes from 'prop-types';

import { connect } from 'lib/utils/redux-utils';

type Props = {|
  visible: bool,
|};
class DisconnectedBar extends React.PureComponent<Props> {

  static propTypes = {
    visible: PropTypes.bool.isRequired,
  };

  componentDidUpdate(prevProps: Props) {
    if (this.props.visible !== prevProps.visible) {
      LayoutAnimation.easeInEaseOut();
    }
  }

  render() {
    const disconnectedBarStyles = [ styles.disconnectedBar ];
    let text;
    if (this.props.visible) {
      text = <Text style={styles.disconnectedText}>DISCONNECTED</Text>;
    } else {
      disconnectedBarStyles.push(styles.hiddenDisconnectedBar);
    }
    return <View style={disconnectedBarStyles}>{text}</View>;
  }

}

const styles = StyleSheet.create({
  disconnectedBar: {
    backgroundColor: '#CC0000',
    padding: 5,
  },
  hiddenDisconnectedBar: {
    height: 0,
    padding: 0,
  },
  disconnectedText: {
    fontSize: 14,
    textAlign: 'center',
    color: 'white',
  },
});

export default connect((state: AppState) => ({
  visible: state.connection.showDisconnectedBar,
}))(DisconnectedBar);
<commit_msg>[native] visible -> showDisconnectedBar in DisconnectedBar<commit_after>// @flow

import type { AppState } from '../redux/redux-setup';

import * as React from 'react';
import { View, Text, StyleSheet, LayoutAnimation } from 'react-native';
import PropTypes from 'prop-types';

import { connect } from 'lib/utils/redux-utils';

type Props = {|
  // Redux state
  showDisconnectedBar: bool,
|};
class DisconnectedBar extends React.PureComponent<Props> {

  static propTypes = {
    showDisconnectedBar: PropTypes.bool.isRequired,
  };

  componentDidUpdate(prevProps: Props) {
    if (this.props.showDisconnectedBar !== prevProps.showDisconnectedBar) {
      LayoutAnimation.easeInEaseOut();
    }
  }

  render() {
    const disconnectedBarStyles = [ styles.disconnectedBar ];
    let text;
    if (this.props.showDisconnectedBar) {
      text = <Text style={styles.disconnectedText}>DISCONNECTED</Text>;
    } else {
      disconnectedBarStyles.push(styles.hiddenDisconnectedBar);
    }
    return <View style={disconnectedBarStyles}>{text}</View>;
  }

}

const styles = StyleSheet.create({
  disconnectedBar: {
    backgroundColor: '#CC0000',
    padding: 5,
  },
  hiddenDisconnectedBar: {
    height: 0,
    padding: 0,
  },
  disconnectedText: {
    fontSize: 14,
    textAlign: 'center',
    color: 'white',
  },
});

export default connect((state: AppState) => ({
  showDisconnectedBar: state.connection.showDisconnectedBar,
}))(DisconnectedBar);
<|endoftext|>


<commit_before>/* global define: false */
define([
	'lodash',
	'vexflow',
], function(_, Vex, StaveNoteFactory) {
	"use strict";

	var MAX_STAVE_BARS = 5;

	// Knows how to render a single bar of a staff.
	var Stave = function(clef, position) {
		this.init(clef, position);
	};

	_.extend(Stave.prototype, {
		clef: '',
		start_x: 0,
		start_y: 0,
		maxWidth: null,
		maxBarCount: 4,
		firstBarWidth: 90,
		defaultWidth: 120,
		margin: {
			left: 30,
			right: 4
		},
		position: {
			index: 0,
			count: 0
		},
		displayConfig: {
			clef: false,
			keySignature: false,
			staveConnector: false
		},
		init: function(clef, position) {
			if(!clef || !position) {
				throw new Error("missing stave clef or position");
			}
			if(!this.validatePosition(position)) {
				throw new Error("missing or invalid stave position");
			}

			this.clef = clef;
			this.position = position;
		},
		validatePosition: function(position) {
			var numRe = /^\d+$/;

			// check that all the required position properties
			// are present and are positive integers
			if(!position.hasOwnProperty('index')
				|| !position.hasOwnProperty('count')
				|| !position.hasOwnProperty('maxCount')
				|| !numRe.test(position.index)
				|| !numRe.test(position.count)
				|| !numRe.test(position.maxCount)) {
				return false;
			}

			// ensure the maximum count (number of bars) is nonzero
			if(position.maxCount === 0) {
				return false;
			}

			return true;
		},
		render: function() {
			this.createStaveBar();
			this.createStaveVoice();
			this.formatStaveVoice();

			this.drawStaveVoice();
			this.drawStaveBar();

			if(this.isConnected()) {
				this.renderConnected();
				this.renderStaveConnector();
			}

			this.notate();

			return this;
		},
		renderConnected: function() {
			this.doConnected('render');
		},
		renderStaveConnector: function() {
			if(this.displayConfig.staveConnector) {
				this.createStaveConnector();
				this.drawStaveConnector();
			}
		},
		createStaveConnector: function() {
			var connector = new Vex.Flow.StaveConnector(this.getStaveBar(), this.connectedStave.getStaveBar());
			connector.setType(Vex.Flow.StaveConnector.type.BRACE);
			this.staveConnector = connector;
		},
		drawStaveConnector: function() {
			var ctx = this.getContext();
			if(this.staveConnector) {
				this.staveConnector.setContext(ctx).draw();
			}
		},
		createStaveBar: function() {
			var x = this.start_x;
			var y = this.start_y;
			var width = this.width;
			var staveBar = new Vex.Flow.Stave(x, y, width);

			if(this.isFirstBar()) {
				staveBar.setBegBarType(Vex.Flow.Barline.type.SINGLE);
				staveBar.setEndBarType(Vex.Flow.Barline.type.NONE);
			} else if(this.isLastBar()) {
				staveBar.setBegBarType(Vex.Flow.Barline.type.NONE);
				staveBar.setEndBarType(Vex.Flow.Barline.type.SINGLE);
			} else {
				staveBar.setBegBarType(Vex.Flow.Barline.type.NONE);
				staveBar.setEndBarType(Vex.Flow.Barline.type.NONE);
			}

			staveBar.setContext(this.getContext());

			if(this.displayConfig.clef) {
				staveBar.addClef(this.clef);
			}
			if(this.displayConfig.keySignature) {
				staveBar.addKeySignature(this.keySignature.getVexKey());
			}

			this.staveBar = staveBar;
		},
		createStaveVoice: function() {
			var voice, formatter;
			if(this.hasStaveNotes()) {
				voice = new Vex.Flow.Voice(Vex.Flow.TIME4_4);
				voice.addTickables(this.createStaveNotes());
			}
			this.staveVoice = voice;
		},
		formatStaveVoice: function() {
			var formatter, voice = this.staveVoice;
			if(voice) {
				formatter = new Vex.Flow.Formatter();
				formatter.joinVoices([voice]).formatToStave([voice], this.staveBar);
			}
		},
		drawStaveVoice: function() {
			if(this.staveVoice) {
				this.staveVoice.draw(this.getContext(), this.staveBar);
			}
		},
		drawStaveBar: function() {
			var ctx = this.getContext();
			this.staveBar.draw(ctx);
		},
		notate: function() {
			if(this.notater) {
				this.notater.notate();
			}
		},
		setMaxBars: function(n) {
			this.maxBars = n;
		},
		setStartX: function(x) {
			this.start_x = x;
			this.doConnected('setStartX', x);
		},
		setMaxWidth: function(w) {
			this.maxWidth = w;
			this.doConnected('setMaxWidth', w);
		},
		setWidth: function(w) {
			this.width = w;
			this.doConnected('setWidth', w);
		},
		setNoteFactory: function(noteFactory) {
			this.noteFactory = noteFactory;
		},
		setNotater: function(notater) {
			this.notater = notater;
		},
		connect: function(stave) {
			this.connectedStave = stave;
		},
		isConnected: function() {
			return this.connectedStave ? true : false;
		},
		doConnected: function(method) {
			var args = Array.prototype.slice.call(arguments, 1);
			if(this.isConnected()) {
				this.connectedStave[method].apply(this.connectedStave, args);
			}
		},
		getConnected: function() {
			return this.connectedStave;
		},
		getWidth: function() {
			return this.width;
		},
		getHeight: function() {
			return this.height;
		},
		getStaveBar: function() {
			return this.staveBar;
		},
		getStartX: function() {
			return this.start_x;
		},
		getClef: function() {
			return this.clef;
		},
		getTopY: function() {
			return this.staveBar.getYForTopText();
		},
		getBottomY: function() {
			return this.staveBar.getBottomY();
		},
		getContext: function() {
			return this.vexRenderer.getContext();
		},
		createStaveNotes: function() {
			return this.noteFactory.createStaveNotes();
		},
		hasStaveNotes: function() {
			if(this.noteFactory) {
				return this.noteFactory.hasStaveNotes();
			}
			return false;
		},
		setKeySignature: function(keySignature) {
			this.keySignature = keySignature;
		},
		setRenderer: function(renderer) {
			this.vexRenderer = renderer;
		},
		setDisplayOptions: function(opts) {
			opts = opts || {};
			this.displayConfig = _.cloneDeep(this.displayConfig || {});
			_.extend(this.displayConfig, opts);
		},
		enableDisplayOptions: function(opts) {
			var trueVal = function() { return true; };
			var displayConfig = _.zipObject(opts, _.map(opts, trueVal));
			this.setDisplayOptions(displayConfig);
		},
		updatePosition: function() {
			var start_x, width;

			if(this.isFirstBar()) {
				this.start_x = this.margin.left;
				this.width = this.firstBarWidth;
			} else {
				start_x = (this.margin.left + this.firstBarWidth);
				width = Math.floor((this.maxWidth - start_x) / this.position.maxCount);
				start_x += ((this.position.index - 1) * width);

				this.start_x = start_x;

				if(this.isLastBar()) {
					// stretch to fill remaining area
					this.width = this.maxWidth - this.start_x - this.margin.right;
				} else {
					this.width = width;
				}
			}

			this.start_y = 75 * (this.clef === 'treble' ? 1 : 2);
		},
		isFirstBar: function() {
			return this.position.index === 0;
		},
		isLastBar: function() {
			return this.position.index === this.position.count;
		}
	});

	return Stave;
});
<commit_msg>remove unused variables<commit_after>/* global define: false */
define([
	'lodash',
	'vexflow',
], function(_, Vex) {
	"use strict";

	// Knows how to render a single bar of a staff.
	var Stave = function(clef, position) {
		this.init(clef, position);
	};

	_.extend(Stave.prototype, {
		clef: '',
		start_x: 0,
		start_y: 0,
		maxWidth: null,
		maxBarCount: 4,
		firstBarWidth: 90,
		defaultWidth: 120,
		margin: {
			left: 30,
			right: 4
		},
		position: {
			index: 0,
			count: 0
		},
		displayConfig: {
			clef: false,
			keySignature: false,
			staveConnector: false
		},
		init: function(clef, position) {
			if(!clef || !position) {
				throw new Error("missing stave clef or position");
			}
			if(!this.validatePosition(position)) {
				throw new Error("missing or invalid stave position");
			}

			this.clef = clef;
			this.position = position;
		},
		validatePosition: function(position) {
			var numRe = /^\d+$/;

			// check that all the required position properties
			// are present and are positive integers
			if(!position.hasOwnProperty('index')
				|| !position.hasOwnProperty('count')
				|| !position.hasOwnProperty('maxCount')
				|| !numRe.test(position.index)
				|| !numRe.test(position.count)
				|| !numRe.test(position.maxCount)) {
				return false;
			}

			// ensure the maximum count (number of bars) is nonzero
			if(position.maxCount === 0) {
				return false;
			}

			return true;
		},
		render: function() {
			this.createStaveBar();
			this.createStaveVoice();
			this.formatStaveVoice();

			this.drawStaveVoice();
			this.drawStaveBar();

			if(this.isConnected()) {
				this.renderConnected();
				this.renderStaveConnector();
			}

			this.notate();

			return this;
		},
		renderConnected: function() {
			this.doConnected('render');
		},
		renderStaveConnector: function() {
			if(this.displayConfig.staveConnector) {
				this.createStaveConnector();
				this.drawStaveConnector();
			}
		},
		createStaveConnector: function() {
			var connector = new Vex.Flow.StaveConnector(this.getStaveBar(), this.connectedStave.getStaveBar());
			connector.setType(Vex.Flow.StaveConnector.type.BRACE);
			this.staveConnector = connector;
		},
		drawStaveConnector: function() {
			var ctx = this.getContext();
			if(this.staveConnector) {
				this.staveConnector.setContext(ctx).draw();
			}
		},
		createStaveBar: function() {
			var x = this.start_x;
			var y = this.start_y;
			var width = this.width;
			var staveBar = new Vex.Flow.Stave(x, y, width);

			if(this.isFirstBar()) {
				staveBar.setBegBarType(Vex.Flow.Barline.type.SINGLE);
				staveBar.setEndBarType(Vex.Flow.Barline.type.NONE);
			} else if(this.isLastBar()) {
				staveBar.setBegBarType(Vex.Flow.Barline.type.NONE);
				staveBar.setEndBarType(Vex.Flow.Barline.type.SINGLE);
			} else {
				staveBar.setBegBarType(Vex.Flow.Barline.type.NONE);
				staveBar.setEndBarType(Vex.Flow.Barline.type.NONE);
			}

			staveBar.setContext(this.getContext());

			if(this.displayConfig.clef) {
				staveBar.addClef(this.clef);
			}
			if(this.displayConfig.keySignature) {
				staveBar.addKeySignature(this.keySignature.getVexKey());
			}

			this.staveBar = staveBar;
		},
		createStaveVoice: function() {
			var voice, formatter;
			if(this.hasStaveNotes()) {
				voice = new Vex.Flow.Voice(Vex.Flow.TIME4_4);
				voice.addTickables(this.createStaveNotes());
			}
			this.staveVoice = voice;
		},
		formatStaveVoice: function() {
			var formatter, voice = this.staveVoice;
			if(voice) {
				formatter = new Vex.Flow.Formatter();
				formatter.joinVoices([voice]).formatToStave([voice], this.staveBar);
			}
		},
		drawStaveVoice: function() {
			if(this.staveVoice) {
				this.staveVoice.draw(this.getContext(), this.staveBar);
			}
		},
		drawStaveBar: function() {
			var ctx = this.getContext();
			this.staveBar.draw(ctx);
		},
		notate: function() {
			if(this.notater) {
				this.notater.notate();
			}
		},
		setMaxBars: function(n) {
			this.maxBars = n;
		},
		setStartX: function(x) {
			this.start_x = x;
			this.doConnected('setStartX', x);
		},
		setMaxWidth: function(w) {
			this.maxWidth = w;
			this.doConnected('setMaxWidth', w);
		},
		setWidth: function(w) {
			this.width = w;
			this.doConnected('setWidth', w);
		},
		setNoteFactory: function(noteFactory) {
			this.noteFactory = noteFactory;
		},
		setNotater: function(notater) {
			this.notater = notater;
		},
		connect: function(stave) {
			this.connectedStave = stave;
		},
		isConnected: function() {
			return this.connectedStave ? true : false;
		},
		doConnected: function(method) {
			var args = Array.prototype.slice.call(arguments, 1);
			if(this.isConnected()) {
				this.connectedStave[method].apply(this.connectedStave, args);
			}
		},
		getConnected: function() {
			return this.connectedStave;
		},
		getWidth: function() {
			return this.width;
		},
		getHeight: function() {
			return this.height;
		},
		getStaveBar: function() {
			return this.staveBar;
		},
		getStartX: function() {
			return this.start_x;
		},
		getClef: function() {
			return this.clef;
		},
		getTopY: function() {
			return this.staveBar.getYForTopText();
		},
		getBottomY: function() {
			return this.staveBar.getBottomY();
		},
		getContext: function() {
			return this.vexRenderer.getContext();
		},
		createStaveNotes: function() {
			return this.noteFactory.createStaveNotes();
		},
		hasStaveNotes: function() {
			if(this.noteFactory) {
				return this.noteFactory.hasStaveNotes();
			}
			return false;
		},
		setKeySignature: function(keySignature) {
			this.keySignature = keySignature;
		},
		setRenderer: function(renderer) {
			this.vexRenderer = renderer;
		},
		setDisplayOptions: function(opts) {
			opts = opts || {};
			this.displayConfig = _.cloneDeep(this.displayConfig || {});
			_.extend(this.displayConfig, opts);
		},
		enableDisplayOptions: function(opts) {
			var trueVal = function() { return true; };
			var displayConfig = _.zipObject(opts, _.map(opts, trueVal));
			this.setDisplayOptions(displayConfig);
		},
		updatePosition: function() {
			var start_x, width;

			if(this.isFirstBar()) {
				this.start_x = this.margin.left;
				this.width = this.firstBarWidth;
			} else {
				start_x = (this.margin.left + this.firstBarWidth);
				width = Math.floor((this.maxWidth - start_x) / this.position.maxCount);
				start_x += ((this.position.index - 1) * width);

				this.start_x = start_x;

				if(this.isLastBar()) {
					// stretch to fill remaining area
					this.width = this.maxWidth - this.start_x - this.margin.right;
				} else {
					this.width = width;
				}
			}

			this.start_y = 75 * (this.clef === 'treble' ? 1 : 2);
		},
		isFirstBar: function() {
			return this.position.index === 0;
		},
		isLastBar: function() {
			return this.position.index === this.position.count;
		}
	});

	return Stave;
});
<|endoftext|>


<commit_before>function applyQuirks(text,pattern) {

    // Case
    console.log(pattern.line);
    switch (pattern.case) {
        case "lower":
            text = text.toLowerCase();
            break;
        case "upper":
            text = text.toUpperCase();
            break;
        case "title":
            text = text.toLowerCase().replace(/\b\w/g, function(t) { return t.toUpperCase(); });
            break;
        case "inverted":
            text = text.replace(/[a-zA-Z]/g, function(t) {
                var out = t.toUpperCase();
                if (out==t) {
                    return t.toLowerCase();
                } else {
                    return out;
                }
            });
            break;
        case "alternating":
            var buffer = text.toLowerCase().split('');
            for(var i=0; i<buffer.length; i+=2){
                buffer[i] = buffer[i].toUpperCase();
            }
            text = buffer.join('');
            break;
        case "alt-lines":
            if (pattern.line == 0) {
                buffer = text.toLowerCase();
            } else {
                buffer = text.toUpperCase();
            }
            text = buffer;
            break;
    }

    // Replacements
    try {
        var replace = {};
        for (i=0; i<pattern.replacements.length; i++) {
            var replacement = pattern.replacements[i];
            replace[replacement[0]] = replacement[1];
        }
    } catch(e) {
        replace = {};
    }

    try {
        var regex = {};
        for (i=0; i<pattern.regexes.length; i++) {
            var re = pattern.regexes[i];
            regex[re[0]] = re[1];
        }
    } catch(e) {
        regex = {};
    }

    var empty = true;
    for(var key in replace) {
        empty = false;
        break;
    }
    for(var key in regex) {
        empty = false;
        break;
    }

    try {
        if (!empty) {
            try {
                var replacementStrings = Object.keys(replace);
            } catch(e) {
                var replacementStrings = [];
            }
            for (i=0;i<replacementStrings.length;i++) {
                replacementStrings[i] = replacementStrings[i].replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
            }
            try {
                var regexStrings = Object.keys(regex);
            } catch(e) {
                var regexStrings = [];
            }
            if (replacementStrings.length!=0 && regexStrings.length!=0) {
                var reg_from = new RegExp(replacementStrings.join("|")+"|"+regexStrings.join("|"), "g");
            } else if (replacementStrings.length!=0 && regexStrings.length==0) {
                var reg_from = new RegExp(replacementStrings.join("|"), "g");
            } else if (replacementStrings.length==0 && regexStrings.length!=0) {
                var reg_from = new RegExp(regexStrings.join("|"), "g");
            } else {
                var reg_from = new RegExp("", "g");
            }
            text = text.replace(reg_from, function($1) {
                if (replace[$1]) {
                    return replace[$1]
                } else {
                    for (var reg in regexStrings) {
                        var original_text = $1;
                        if (RegExp(regexStrings[reg],'g').test($1)) {
                            var insert_text = regex[regexStrings[reg]];
                            insert_text = insert_text.replace(/([^\\]|^)(\$1)/g, function($1,$2,$3) {
                                return $2+original_text;
                            });
                            insert_text = insert_text.replace(/\\\$1/g, "\$1");
                            return insert_text;
                        }
                    }
                }
                return "";
            });
        }
    } catch(e) {}

    // Prefix
    if (pattern.quirk_prefix) {
        text = pattern.quirk_prefix+' '+text;
    }

    // Suffix
    if (pattern.quirk_suffix) {
        text = text+' '+pattern.quirk_suffix;
    }

    return text
}

function depunct(txt) {
    return txt.replace(/[.,?!']/g, '');
}<commit_msg>casing fixing<commit_after>function applyQuirks(text,pattern) {

    // Case
    console.log(pattern.line);
    switch (pattern.case) {
        case "lower":
            text = text.toLowerCase();
            break;
        case "upper":
            text = text.toUpperCase();
            break;
        case "title":
            text = text.toLowerCase().replace(/\b\w/g, function(t) { return t.toUpperCase(); });
            break;
        case "inverted":
            text = text.replace(/[a-zA-Z]/g, function(t) {
                var out = t.toUpperCase();
                if (out==t) {
                    return t.toLowerCase();
                } else {
                    return out;
                }
            });
            break;
        case "alternating":
            var buffer = text.toLowerCase().split('');
            for(var i=0; i<buffer.length; i+=2){
                buffer[i] = buffer[i].toUpperCase();
            }
            text = buffer.join('');
            break;
        case "alt-lines":
            if (pattern.line) {
                buffer = text.toLowerCase();
            } else {
                buffer = text.toUpperCase();
            }
            text = buffer;
            break;
    }

    // Replacements
    try {
        var replace = {};
        for (i=0; i<pattern.replacements.length; i++) {
            var replacement = pattern.replacements[i];
            replace[replacement[0]] = replacement[1];
        }
    } catch(e) {
        replace = {};
    }

    try {
        var regex = {};
        for (i=0; i<pattern.regexes.length; i++) {
            var re = pattern.regexes[i];
            regex[re[0]] = re[1];
        }
    } catch(e) {
        regex = {};
    }

    var empty = true;
    for(var key in replace) {
        empty = false;
        break;
    }
    for(var key in regex) {
        empty = false;
        break;
    }

    try {
        if (!empty) {
            try {
                var replacementStrings = Object.keys(replace);
            } catch(e) {
                var replacementStrings = [];
            }
            for (i=0;i<replacementStrings.length;i++) {
                replacementStrings[i] = replacementStrings[i].replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
            }
            try {
                var regexStrings = Object.keys(regex);
            } catch(e) {
                var regexStrings = [];
            }
            if (replacementStrings.length!=0 && regexStrings.length!=0) {
                var reg_from = new RegExp(replacementStrings.join("|")+"|"+regexStrings.join("|"), "g");
            } else if (replacementStrings.length!=0 && regexStrings.length==0) {
                var reg_from = new RegExp(replacementStrings.join("|"), "g");
            } else if (replacementStrings.length==0 && regexStrings.length!=0) {
                var reg_from = new RegExp(regexStrings.join("|"), "g");
            } else {
                var reg_from = new RegExp("", "g");
            }
            text = text.replace(reg_from, function($1) {
                if (replace[$1]) {
                    return replace[$1]
                } else {
                    for (var reg in regexStrings) {
                        var original_text = $1;
                        if (RegExp(regexStrings[reg],'g').test($1)) {
                            var insert_text = regex[regexStrings[reg]];
                            insert_text = insert_text.replace(/([^\\]|^)(\$1)/g, function($1,$2,$3) {
                                return $2+original_text;
                            });
                            insert_text = insert_text.replace(/\\\$1/g, "\$1");
                            return insert_text;
                        }
                    }
                }
                return "";
            });
        }
    } catch(e) {}

    // Prefix
    if (pattern.quirk_prefix) {
        text = pattern.quirk_prefix+' '+text;
    }

    // Suffix
    if (pattern.quirk_suffix) {
        text = text+' '+pattern.quirk_suffix;
    }

    return text
}

function depunct(txt) {
    return txt.replace(/[.,?!']/g, '');
}<|endoftext|>


<commit_before>function applyQuirks(text,pattern) {

    // Case
    //try {
        pattern.character = pattern.character?pattern.character:{};
        switch (pattern.character['case']) {
            case "lower":
                text = text.toLowerCase();
                break;
            case "upper":
                text = text.toUpperCase();
                break;
            case "title":
                text = text.toLowerCase().replace(/\b\w/g, function(t) { return t.toUpperCase(); });
                break;
            case "inverted":
                text = text.replace(/[a-zA-Z]/g, function(t) {
                    var out = t.toUpperCase();
                    if (out==t) {
                        return t.toLowerCase();
                    } else {
                        return out;
                    }
                });
                break;
            case "alternating":
                var buffer = text.toLowerCase().split('');
                for(var i=0; i<buffer.length; i+=2){
                    buffer[i] = buffer[i].toUpperCase();
                }
                text = buffer.join('');
                break;
            case "alt-lines":
                if (pattern.line == 0) {
                    buffer = text.toLowerCase();
                } else {
                    buffer = text.toUpperCase();
                }
                text = buffer;
                break;
        }
    //} catch(e) {}

    // Replacements
    try {
        var replace = {};
        for (i=0; i<pattern.replacements.length; i++) {
            var replacement = pattern.replacements[i];
            replace[replacement[0]] = replacement[1];
        }
    } catch(e) {
        replace = {};
    }

    try {
        var regex = {};
        for (i=0; i<pattern.regexes.length; i++) {
            var re = pattern.regexes[i];
            regex[re[0]] = re[1];
        }
    } catch(e) {
        regex = {};
    }

    var empty = true;
    for(var key in replace) {
        empty = false;
        break;
    }
    for(var key in regex) {
        empty = false;
        break;
    }

    try {
        if (!empty) {
            try {
                var replacementStrings = Object.keys(replace);
            } catch(e) {
                var replacementStrings = [];
            }
            for (i=0;i<replacementStrings.length;i++) {
                replacementStrings[i] = replacementStrings[i].replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
            }
            try {
                var regexStrings = Object.keys(regex);
            } catch(e) {
                var regexStrings = [];
            }
            if (replacementStrings.length!=0 && regexStrings.length!=0) {
                var reg_from = new RegExp(replacementStrings.join("|")+"|"+regexStrings.join("|"), "g");
            } else if (replacementStrings.length!=0 && regexStrings.length==0) {
                var reg_from = new RegExp(replacementStrings.join("|"), "g");
            } else if (replacementStrings.length==0 && regexStrings.length!=0) {
                var reg_from = new RegExp(regexStrings.join("|"), "g");
            } else {
                var reg_from = new RegExp("", "g");
            }
            text = text.replace(reg_from, function($1) {
                if (replace[$1]) {
                    return replace[$1]
                } else {
                    for (var reg in regexStrings) {
                        var original_text = $1;
                        if (RegExp(regexStrings[reg],'g').test($1)) {
                            var insert_text = regex[regexStrings[reg]];
                            insert_text = insert_text.replace(/([^\\]|^)(\$1)/g, function($1,$2,$3) {
                                return $2+original_text;
                            });
                            insert_text = insert_text.replace(/\\\$1/g, "\$1");
                            return insert_text;
                        }
                    }
                }
                return "";
            });
        }
    } catch(e) {}

    // Prefix
    if (pattern.quirk_prefix) {
        text = pattern.quirk_prefix+' '+text;
    }

    // Suffix
    if (pattern.quirk_suffix) {
        text = text+' '+pattern.quirk_suffix;
    }

    return text
}

function depunct(txt) {
    return txt.replace(/[.,?!']/g, '');
}<commit_msg>casing fixing<commit_after>function applyQuirks(text,pattern) {

    // Case
    //try {
        console.log(pattern);
        pattern.character = pattern.character?pattern.character:{};
        switch (pattern.character['case']) {
            case "lower":
                text = text.toLowerCase();
                break;
            case "upper":
                text = text.toUpperCase();
                break;
            case "title":
                text = text.toLowerCase().replace(/\b\w/g, function(t) { return t.toUpperCase(); });
                break;
            case "inverted":
                text = text.replace(/[a-zA-Z]/g, function(t) {
                    var out = t.toUpperCase();
                    if (out==t) {
                        return t.toLowerCase();
                    } else {
                        return out;
                    }
                });
                break;
            case "alternating":
                var buffer = text.toLowerCase().split('');
                for(var i=0; i<buffer.length; i+=2){
                    buffer[i] = buffer[i].toUpperCase();
                }
                text = buffer.join('');
                break;
            case "alt-lines":
                if (pattern.line == 0) {
                    buffer = text.toLowerCase();
                } else {
                    buffer = text.toUpperCase();
                }
                text = buffer;
                break;
        }
    //} catch(e) {}

    // Replacements
    try {
        var replace = {};
        for (i=0; i<pattern.replacements.length; i++) {
            var replacement = pattern.replacements[i];
            replace[replacement[0]] = replacement[1];
        }
    } catch(e) {
        replace = {};
    }

    try {
        var regex = {};
        for (i=0; i<pattern.regexes.length; i++) {
            var re = pattern.regexes[i];
            regex[re[0]] = re[1];
        }
    } catch(e) {
        regex = {};
    }

    var empty = true;
    for(var key in replace) {
        empty = false;
        break;
    }
    for(var key in regex) {
        empty = false;
        break;
    }

    try {
        if (!empty) {
            try {
                var replacementStrings = Object.keys(replace);
            } catch(e) {
                var replacementStrings = [];
            }
            for (i=0;i<replacementStrings.length;i++) {
                replacementStrings[i] = replacementStrings[i].replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
            }
            try {
                var regexStrings = Object.keys(regex);
            } catch(e) {
                var regexStrings = [];
            }
            if (replacementStrings.length!=0 && regexStrings.length!=0) {
                var reg_from = new RegExp(replacementStrings.join("|")+"|"+regexStrings.join("|"), "g");
            } else if (replacementStrings.length!=0 && regexStrings.length==0) {
                var reg_from = new RegExp(replacementStrings.join("|"), "g");
            } else if (replacementStrings.length==0 && regexStrings.length!=0) {
                var reg_from = new RegExp(regexStrings.join("|"), "g");
            } else {
                var reg_from = new RegExp("", "g");
            }
            text = text.replace(reg_from, function($1) {
                if (replace[$1]) {
                    return replace[$1]
                } else {
                    for (var reg in regexStrings) {
                        var original_text = $1;
                        if (RegExp(regexStrings[reg],'g').test($1)) {
                            var insert_text = regex[regexStrings[reg]];
                            insert_text = insert_text.replace(/([^\\]|^)(\$1)/g, function($1,$2,$3) {
                                return $2+original_text;
                            });
                            insert_text = insert_text.replace(/\\\$1/g, "\$1");
                            return insert_text;
                        }
                    }
                }
                return "";
            });
        }
    } catch(e) {}

    // Prefix
    if (pattern.quirk_prefix) {
        text = pattern.quirk_prefix+' '+text;
    }

    // Suffix
    if (pattern.quirk_suffix) {
        text = text+' '+pattern.quirk_suffix;
    }

    return text
}

function depunct(txt) {
    return txt.replace(/[.,?!']/g, '');
}<|endoftext|>


<commit_before>var trackApp = angular.module('trackApp', []);

/*
 ===========================================
                CONTROLLERS
 ===========================================
 */
// Main Angular controller for app.
function mainController($scope, $http, sampleFactory) {
    $scope.test = 'Hello world!';
    $scope.factory = sampleFactory;
}

mainController.$inject = ['$scope', '$http', 'sampleFactory'];

/*
 ===========================================
                SERVICES
 ===========================================
 */

trackApp.factory('sampleFactory', function() {
    return 'test';
});

/*
 ===========================================
                EVEMTS
 ===========================================
 */

// Init setup and attach event listeners.
document.addEventListener('DOMContentLoaded', function(e) {
    var closeButton = document.querySelector('#close-button');
    closeButton.addEventListener('click', function(e) {
        window.close();
    });
});
<commit_msg>modified angular app.js<commit_after>var trackApp = angular.module('trackApp', []);

/*
 ===========================================
                CONTROLLERS
 ===========================================
 */

// home page for app
trackApp.controller('MainCtrl', function ($scope, $http, sampleFactory) {
    $scope.test = 'Hello world!';
    $scope.factory = sampleFactory;
});

// header controller
trackApp.controller('HeaderCtrl', function ($scope, $location) {
    $scope.$location = $location;
});

/*
 ===========================================
                SERVICES
 ===========================================
 */

trackApp.factory('sampleFactory', function() {
    return 'test';
});

/*
 ===========================================
                ROUTES
 ===========================================
 */

trackApp.config(function ($routeProvider) {

    $routeProvider
        .when('/', {
            templateUrl: 'views/main.html',
            controller: 'MainCtrl'
        })
        .when('/activity', {
            templateUrl: 'views/activity.html',
            controller: 'MainCtrl'
        })
        .otherwise({
            redirectTo: '/'
        });
});

/*
 ===========================================
                EVEMTS
 ===========================================
 */

// Init setup and attach event listeners.
document.addEventListener('DOMContentLoaded', function(e) {
    var closeButton = document.querySelector('#close-button');
    closeButton.addEventListener('click', function(e) {
        window.close();
    });
});
<|endoftext|>


<commit_before>/* global chrome io */

// const server = 'https://devtools-remote.herokuapp.com/'
const server = 'http://localhost:8000/'

var debuggee = {}
var isAttached = false
var app = {}
var tabRef
var socketRef

var io = io(server, {
  autoConnect: false
})

function resetSockets(tab){
  tabRef = tab
  debuggee.tabId = tab.id

  getDebuggerTarget().then( target => {

    if (target.attached){
      console.warn('debuggee.already attached')
      chrome.debugger.detach(debuggee)
    }

    if (target.url.startsWith("chrome://")) {
      return app.setBadgeText("ERR")
    }

    app.setBadgeText("oo0")
    attachDebuggerAndSocket(debuggee, tab)
  })
}

function getDebuggerTarget(fn){
  return new Promise((resolve, reject) =>
    chrome.debugger.getTargets(targetsArr => {
      var arr = targetsArr.filter( t => t.tabId == debuggee.tabId)
      resolve(arr && arr[0])
    }));
};

function attachDebuggerAndSocket(debuggee, tab){
  console.log('debugger.attach', tab)
  chrome.debugger.attach(debuggee, '1.1', function () {
    console.log('debugger.attached')
    app.setBadgeText("o0o")
  })

  if (io && io.connected){
    console.log('socket.disconnecting previous socket')
    io.disconnect()
  }
  console.log('socket.connecting')
  io.connect()
}

// socket-side
app.onSocketConnect = function () {
  console.log('socket.connect');
  app.setBadgeText("0oo");
  socketRef = this

  this.on('data.request', app.onSocketDataRequest);
  this.on('sessionCreated', app.onSessionCreated);

  this.emit('hello', {
    title: tabRef.title,
    url: tabRef.url,
    userAgent: navigator.userAgent
  })
};

app.onSocketDisconnect = function() {
  console.log('socket.disconnect')

  this.off('data.request')
  this.off('sessionCreated')

  socketRef = null

  getDebuggerTarget().then(target =>{
    if (target && target.attached) {
      chrome.debugger.detach(debuggee, _ => console.log('debugger.detached'))
    }
  })
};

app.onSocketDataRequest = function (data) {
  console.log('socket.data.request', data.id, data)

  if (data.method === 'Page.canScreencast') {
    var reply = {
      id: data.id,
      result: {
        result: true
      }
    }

    this.emit('data.response', reply)
    return
  }

  chrome.debugger.sendCommand(debuggee, data.method, data.params, function (response) {
    console.log('debugger.command.sent', data.id, response)

    var reply = {
      id: data.id,
      result: response
    }

    console.log('socket.data.response', reply.id, reply)
    this.emit('data.response', reply)
  }.bind(this))
};

app.getURL = function(sessionId){

  app.setBadgeText("ooo")

  fetch(server + sessionId + '/json')
    .then( r => r.json())
    .then( targets => {

      console.log('Inspectable targets on ', server, ':');

      targets.forEach( t => {
        /* t looks like: {
          description: "",
          devtoolsFrontendUrl: "/devtools/devtools.html?ws=devtoolsremote.com/devtools/page/lQOtx1HAAC",
          devtoolsUrl: "chrome-devtools://devtools/remote/serve_rev/@06a2e…m/devtools/page/lQOtx1HAAC&remoteFrontend=true&dockSide=unlocked",
          id: "lQOtx1HuFkFfAQ3AAAAC",
          title: "chrome.debugger - Google Chrome",
          type: "page",
          url: "https://developer.chrome.com/extensions/debugger#type-TargetInfo",
          webSocketDebuggerUrl: "ws://devtoolsremote.com/devtools/page/lQOtx1HAAC"
        } */

        console.log('%c%s', "font-weight: bold;", t.title);
        console.log('\t %c%s', "color: gray; font-size: 90%;", t.url);
        console.log('\t Inspection URL: %c%s', "color: blue;", t.devtoolsUrl);

        if (t.url == tabRef.url)
          app.copyToClipboard(t.devtoolsUrl);
      })
    });
};

io.on('connect', app.onSocketConnect)
io.on('disconnect', app.onSocketDisconnect);

app.copyToClipboard = function(text){
    var input = document.createElement('input');
    document.body.appendChild(input);
    input.value = text;
    input.focus();
    input.select();
    document.execCommand('copy');
    input.remove();

    app.setBadgeText("copied")
    setTimeout(app.setBadgeText, 600);
}

// chrome-side
app.onBrowserAction = function(tab){
  app.setBadgeText("ooo")
  resetSockets(tab);
};

app.setBadgeText = function(text){
  chrome.browserAction.setBadgeBackgroundColor({color: text == "ERR" ? 'red' : '#5CC77D'});
  chrome.browserAction.setBadgeText({text: text || ""});
}

app.onDebuggerEvent = function (source, method, params) {
  console.log('debugger.event.recieved', source, method, params)
  socketRef.emit('data.event', {
    method: method,
    params: params
  })
};

app.onDebuggerDetach = function (debuggee, reason) {
  console.log('debugger.detached', reason)
  io.disconnect()

  app.setBadgeText("clear")
  setTimeout(app.setBadgeText, 500);
};

app.onSessionCreated = function(sessionId) {
  console.log('sessionId', sessionId)
  app.getURL(sessionId)
}

chrome.browserAction.onClicked.addListener(app.onBrowserAction);
chrome.runtime.onMessage.addListener(app.onRuntimeMessage);
chrome.debugger.onEvent.addListener(app.onDebuggerEvent)
chrome.debugger.onDetach.addListener(app.onDebuggerDetach)

<commit_msg>StandardJS formatting<commit_after>/* global chrome io */

const server = 'https://devtools-remote.herokuapp.com/'
// const server = 'http://localhost:8000/'

var debuggee = {}
var app = {}
var tabRef
var socketRef

var connection = io(server, {
  autoConnect: false
})

function resetSockets (tab) {
  tabRef = tab
  debuggee.tabId = tab.id

  getDebuggerTarget().then(target => {
    if (target.attached) {
      console.warn('debuggee.already attached')
      chrome.debugger.detach(debuggee)
    }

    if (target.url.startsWith('chrome://')) {
      return app.setBadgeText('ERR')
    }

    app.setBadgeText('oo0')
    attachDebuggerAndSocket(debuggee, tab)
  })
}

function getDebuggerTarget (fn) {
  return new Promise((resolve, reject) =>
    chrome.debugger.getTargets(targetsArr => {
      var arr = targetsArr.filter(t => t.tabId === debuggee.tabId)
      resolve(arr && arr[0])
    }))
}

function attachDebuggerAndSocket (debuggee, tab) {
  console.log('debugger.attach', tab)
  chrome.debugger.attach(debuggee, '1.1', function () {
    console.log('debugger.attached')
    app.setBadgeText('o0o')
  })

  if (connection && connection.connected) {
    console.log('socket.disconnecting previous socket')
    connection.disconnect()
  }
  console.log('socket.connecting')
  connection.connect()
}

// socket-side
app.onSocketConnect = function () {
  console.log('socket.connect')
  app.setBadgeText('0oo')
  socketRef = this

  this.on('data.request', app.onSocketDataRequest)
  this.on('sessionCreated', app.onSessionCreated)

  this.emit('hello', {
    title: tabRef.title,
    url: tabRef.url,
    userAgent: navigator.userAgent
  })
}

app.onSocketDisconnect = function () {
  console.log('socket.disconnect')

  this.off('data.request')
  this.off('sessionCreated')

  socketRef = null

  getDebuggerTarget().then(target => {
    if (target && target.attached) {
      chrome.debugger.detach(debuggee, _ => console.log('debugger.detached'))
    }
  })
}

app.onSocketDataRequest = function (data) {
  console.log('socket.data.request', data.id, data)

  if (data.method === 'Page.canScreencast') {
    var reply = {
      id: data.id,
      result: {
        result: true
      }
    }

    this.emit('data.response', reply)
    return
  }

  chrome.debugger.sendCommand(debuggee, data.method, data.params, function (response) {
    console.log('debugger.command.sent', data.id, response)

    var reply = {
      id: data.id,
      result: response
    }

    console.log('socket.data.response', reply.id, reply)
    this.emit('data.response', reply)
  }.bind(this))
}

app.getURL = function (sessionId) {
  app.setBadgeText('ooo')

  window.fetch(server + sessionId + '/json')
    .then(r => r.json())
    .then(targets => {
      console.log('Inspectable targets on ', server, ':')
      targets.forEach(t => {
        /* t looks like: {
          description: "",
          devtoolsFrontendUrl: "/devtools/devtools.html?ws=devtoolsremote.com/devtools/page/lQOtx1HAAC",
          devtoolsUrl: "chrome-devtools://devtools/remote/serve_rev/@06a2e…m/devtools/page/lQOtx1HAAC&remoteFrontend=true&dockSide=unlocked",
          id: "lQOtx1HuFkFfAQ3AAAAC",
          title: "chrome.debugger - Google Chrome",
          type: "page",
          url: "https://developer.chrome.com/extensions/debugger#type-TargetInfo",
          webSocketDebuggerUrl: "ws://devtoolsremote.com/devtools/page/lQOtx1HAAC"
        } */

        console.log('%c%s', 'font-weight: bold;', t.title)
        console.log('\t %c%s', 'color: gray; font-size: 90%;', t.url)
        console.log('\t Inspection URL: %c%s', 'color: blue;', t.devtoolsUrl)

        if (t.url === tabRef.url) {
          app.copyToClipboard(t.devtoolsUrl)
        }
      })
    })
}

connection.on('connect', app.onSocketConnect)
connection.on('disconnect', app.onSocketDisconnect)

app.copyToClipboard = function (text) {
  var input = document.createElement('input')
  document.body.appendChild(input)
  input.value = text
  input.focus()
  input.select()
  document.execCommand('copy')
  input.remove()

  app.setBadgeText('copied')
  setTimeout(app.setBadgeText, 600)
}

// chrome-side
app.onBrowserAction = function (tab) {
  app.setBadgeText('ooo')
  resetSockets(tab)
}

app.setBadgeText = function (text) {
  chrome.browserAction.setBadgeBackgroundColor({
    color: text === 'ERR' ? 'red' : '#5CC77D'
  })

  chrome.browserAction.setBadgeText({
    text: text || ''
  })
}

app.onDebuggerEvent = function (source, method, params) {
  console.log('debugger.event.recieved', source, method, params)
  socketRef.emit('data.event', {
    method: method,
    params: params
  })
}

app.onDebuggerDetach = function (debuggee, reason) {
  console.log('debugger.detached', reason)
  io.disconnect()

  app.setBadgeText('clear')
  setTimeout(app.setBadgeText, 500)
}

app.onSessionCreated = function (sessionId) {
  console.log('sessionId', sessionId)
  app.getURL(sessionId)
}

chrome.browserAction.onClicked.addListener(app.onBrowserAction)
chrome.runtime.onMessage.addListener(app.onRuntimeMessage)
chrome.debugger.onEvent.addListener(app.onDebuggerEvent)
chrome.debugger.onDetach.addListener(app.onDebuggerDetach)
<|endoftext|>