<commit_before>import assert from 'assert'
import { c1 } from '../../../build/wikimedia-page-library-pcs'
import domino from 'domino'

const Page = c1.Page
const Themes = c1.Themes

/* eslint-disable no-global-assign, no-native-reassign */
describe('pcs.c1.Page', () => {
  const emptyHTML = '<title>Foo</title>

'

  describe('.setup()', () => {
    it('all', () => {
      window = domino.createWindow(
        'Quick facts')
      document = window.document

      Page.setup({
        platform: 'ios',
        clientVersion: '6.2.1',
        theme: 'dark',
        dimImages: true,
        margins: { top: '1px', right: '2px', bottom: '3px', left: '4px' },
        areTablesInitiallyExpanded: true,
        textSizeAdjustmentPercentage: '100%',
        scrollTop: 64,
        loadImages: true
      })

      assert.ok(document.body.classList.contains('pcs-theme-dark'))
      assert.ok(document.body.classList.contains('pcs-dim-images'))
      assert.strictEqual(document.body.style.marginTop, '1px')
      assert.strictEqual(document.body.style.marginRight, '2px')
      assert.strictEqual(document.body.style.marginBottom, '3px')
      assert.strictEqual(document.body.style.marginLeft, '4px')
      assert.strictEqual(document.body.style['text-size-adjust'], '100%')
      assert.strictEqual(Page.testing.getScroller().testing.getScrollTop(), 64)
    })
  })

  describe('.setTheme()', () => {
    it('sepia', () => {
      document = domino.createDocument(emptyHTML)
      Page.setTheme(Themes.SEPIA)
      assert.ok(document.body.classList.contains(Themes.SEPIA))
    })
  })

  describe('.setDimImages()', () => {
    it('true + callback', () => {
      window = domino.createWindow(emptyHTML)
      document = window.document

      Page.setDimImages(true)

      assert.ok(document.body.classList.contains('pcs-dim-images'))
    })

    it('false', () => {
      window = domino.createWindow(emptyHTML)
      document = window.document

      Page.setDimImages(false)

      assert.ok(!document.body.classList.contains('pcs-dim-images'))
    })
  })

  describe('.setMargins()', () => {
    it('all', () => {
      window = domino.createWindow(emptyHTML)
      document = window.document

      Page.setMargins({ top: '1px', right: '2px', bottom: '3px', left: '4px' })

      assert.strictEqual(document.body.style.marginTop, '1px')
      assert.strictEqual(document.body.style.marginRight, '2px')
      assert.strictEqual(document.body.style.marginBottom, '3px')
      assert.strictEqual(document.body.style.marginLeft, '4px')
    })

    it('nothing', () => {
      window = domino.createWindow(emptyHTML)
      document = window.document

      Page.setMargins({})

      assert.strictEqual(document.body.style.marginTop, '')
      assert.strictEqual(document.body.style.marginRight, '')
      assert.strictEqual(document.body.style.marginBottom, '')
      assert.strictEqual(document.body.style.marginLeft, '')
    })
  })

  describe('.setTextSizeAdjustmentPercentage()', () => {
    it('120%', () => {
      window = domino.createWindow(emptyHTML)
      document = window.document

      Page.setTextSizeAdjustmentPercentage('120%')

      assert.strictEqual(document.body.style['text-size-adjust'], '120%')
    })
  })

  describe('.setScrollTop()', () => {
    it('all', () => {
      window = domino.createWindow(emptyHTML)
      document = window.document

      Page.setScrollTop(64)

      assert.strictEqual(Page.testing.getScroller().testing.getScrollTop(), 64)
    })
  })

  describe('.setEditButtons()', () => {
    it('simple', () => {
      window = domino.createWindow(
        '')
      document = window.document

      Page.setEditButtons(false, true)

      assert.ok(document.documentElement.classList.contains('no-editing'))
      assert.ok(document.documentElement.classList.contains('page-protected'))
    })
  })

  describe('.getRevision()', () => {
    it('all', () => {
      window = domino.createWindow(
        '')
      document = window.document

      assert.strictEqual(Page.getRevision(), '907165344')
    })
  })

  describe('.getTableOfContents()', () => {
    it('all', () => {
      window = domino.createWindow(`

Foo

Foo

Foo

Foo

Foo

Foo

Foo

Foo

Foo

Foo

      `)
      document = window.document

      const result = Page.getTableOfContents()
      const expectedNumbers = ['1', '1.1', '1.1.1', '1.2', '1.2.1', '1.3', '2']
      assert.strictEqual(result.length, 7, 'result should have 7 entries (3 excluded)')
      assert.strictEqual(result.length, expectedNumbers.length)
      result.forEach((tocSection, idx) => {
        assert.ok(tocSection.level, 'level should be present')
        assert.ok(tocSection.id, 'id should be present')
        assert.strictEqual(tocSection.number, expectedNumbers[idx], 'should have correct number')
        assert.ok(tocSection.anchor, 'anchor should be present')
        assert.ok(tocSection.title, 'title should be present')
      })
    })
  })
})<commit_msg>Hygiene: Update Page.setTextSizeAdjustmentPercentage tests<commit_after>import assert from 'assert'
import { c1 } from '../../../build/wikimedia-page-library-pcs'
import domino from 'domino'

const Page = c1.Page
const Themes = c1.Themes

/* eslint-disable no-global-assign, no-native-reassign */
describe('pcs.c1.Page', () => {
  const emptyHTML = '<title>Foo</title>

'

  describe('.setup()', () => {
    it('all', () => {
      window = domino.createWindow(
        'Quick facts')
      document = window.document

      Page.setup({
        platform: 'ios',
        clientVersion: '6.2.1',
        theme: 'dark',
        dimImages: true,
        margins: { top: '1px', right: '2px', bottom: '3px', left: '4px' },
        areTablesInitiallyExpanded: true,
        textSizeAdjustmentPercentage: '100%',
        scrollTop: 64,
        loadImages: true
      })

      assert.ok(document.body.classList.contains('pcs-theme-dark'))
      assert.ok(document.body.classList.contains('pcs-dim-images'))
      assert.strictEqual(document.body.style.marginTop, '1px')
      assert.strictEqual(document.body.style.marginRight, '2px')
      assert.strictEqual(document.body.style.marginBottom, '3px')
      assert.strictEqual(document.body.style.marginLeft, '4px')
      assert.strictEqual(document.body.style['font-size'], '95%')
      // assert.strictEqual(document.body.style['text-size-adjust'], '100%')
      assert.strictEqual(Page.testing.getScroller().testing.getScrollTop(), 64)
    })
  })

  describe('.setTheme()', () => {
    it('sepia', () => {
      document = domino.createDocument(emptyHTML)
      Page.setTheme(Themes.SEPIA)
      assert.ok(document.body.classList.contains(Themes.SEPIA))
    })
  })

  describe('.setDimImages()', () => {
    it('true + callback', () => {
      window = domino.createWindow(emptyHTML)
      document = window.document

      Page.setDimImages(true)

      assert.ok(document.body.classList.contains('pcs-dim-images'))
    })

    it('false', () => {
      window = domino.createWindow(emptyHTML)
      document = window.document

      Page.setDimImages(false)

      assert.ok(!document.body.classList.contains('pcs-dim-images'))
    })
  })

  describe('.setMargins()', () => {
    it('all', () => {
      window = domino.createWindow(emptyHTML)
      document = window.document

      Page.setMargins({ top: '1px', right: '2px', bottom: '3px', left: '4px' })

      assert.strictEqual(document.body.style.marginTop, '1px')
      assert.strictEqual(document.body.style.marginRight, '2px')
      assert.strictEqual(document.body.style.marginBottom, '3px')
      assert.strictEqual(document.body.style.marginLeft, '4px')
    })

    it('nothing', () => {
      window = domino.createWindow(emptyHTML)
      document = window.document

      Page.setMargins({})

      assert.strictEqual(document.body.style.marginTop, '')
      assert.strictEqual(document.body.style.marginRight, '')
      assert.strictEqual(document.body.style.marginBottom, '')
      assert.strictEqual(document.body.style.marginLeft, '')
    })
  })

  describe('.setTextSizeAdjustmentPercentage()', () => {
    it('120%', () => {
      window = domino.createWindow(emptyHTML)
      document = window.document

      Page.setTextSizeAdjustmentPercentage('100%')

      assert.strictEqual(document.body.style['font-size'], '95%')
      // assert.strictEqual(document.body.style['text-size-adjust'], '100%')
    })
  })

  describe('.setScrollTop()', () => {
    it('all', () => {
      window = domino.createWindow(emptyHTML)
      document = window.document

      Page.setScrollTop(64)

      assert.strictEqual(Page.testing.getScroller().testing.getScrollTop(), 64)
    })
  })

  describe('.setEditButtons()', () => {
    it('simple', () => {
      window = domino.createWindow(
        '')
      document = window.document

      Page.setEditButtons(false, true)

      assert.ok(document.documentElement.classList.contains('no-editing'))
      assert.ok(document.documentElement.classList.contains('page-protected'))
    })
  })

  describe('.getRevision()', () => {
    it('all', () => {
      window = domino.createWindow(
        '')
      document = window.document

      assert.strictEqual(Page.getRevision(), '907165344')
    })
  })

  describe('.getTableOfContents()', () => {
    it('all', () => {
      window = domino.createWindow(`

Foo

Foo

Foo

Foo

Foo

Foo

Foo

Foo

Foo

Foo

      `)
      document = window.document

      const result = Page.getTableOfContents()
      const expectedNumbers = ['1', '1.1', '1.1.1', '1.2', '1.2.1', '1.3', '2']
      assert.strictEqual(result.length, 7, 'result should have 7 entries (3 excluded)')
      assert.strictEqual(result.length, expectedNumbers.length)
      result.forEach((tocSection, idx) => {
        assert.ok(tocSection.level, 'level should be present')
        assert.ok(tocSection.id, 'id should be present')
        assert.strictEqual(tocSection.number, expectedNumbers[idx], 'should have correct number')
        assert.ok(tocSection.anchor, 'anchor should be present')
        assert.ok(tocSection.title, 'title should be present')
      })
    })
  })
})<|endoftext|>


<commit_before>var BackupUtils = {};

$(document).ready(
	function() {
		var create_backup_button = $('.create-backup-button');
		var create_backup_url = create_backup_button.data('create-backup-url');
		var save_backup_url = create_backup_button.data('save-backup-url');
		var app_key = create_backup_button.data('dropbox-app-key');
		var redirect_url = create_backup_button.data('dropbox-redirect-url');
		var processing_animation_image = $('img', create_backup_button);
		var backup_icon = $('span', create_backup_button);
		var backup_list = $('#backup-list');
		var FinishAnimation = function() {
			create_backup_button.prop('disabled', false);
			processing_animation_image.hide();
			backup_icon.show();
		};
		var GetAccessToDropbox = function() {
			var url = 'https://www.dropbox.com/1/oauth2/authorize'
				+ '?response_type=code'
				+ '&client_id=' + app_key
				+ '&redirect_uri=' + encodeURIComponent(
					location.protocol + '//' + location.host + redirect_url
				)
				+ '&force_reapprove=true';
			open(url, '_blank', 'width=640, height=480');
		};
		BackupUtils.error = function(xhr, text_status) {
			FinishAnimation();
			AjaxErrorDialog.handler(xhr, text_status);
		};

		var global_data = {backup_path: '', create_time: ''};
		window.Backup = {
			create: function(authorization_code) {
				var data = $.extend(
					{
						authorization_code: authorization_code,
						backup_path: global_data.backup_path,
						create_time: global_data.create_time
					},
					CSRF_TOKEN
				);

				$.post(
					save_backup_url,
					data,
					function() {
						FinishAnimation();

						if (backup_list.length) {
							backup_list.yiiGridView(
								'update',
								{
									url:
										location.pathname
											+ location.search
											+ location.hash
								}
							);
						}
					}
				).fail(BackupUtils.error);
			},
			error: AjaxErrorDialog.show
		};

		create_backup_button.click(
			function() {
				BackupDialog.show(
					function() {
						create_backup_button.prop('disabled', true);
						processing_animation_image.show();
						backup_icon.hide();

						if (backup_list.length) {
							backup_list.yiiGridView(
								'update',
								{
									type: 'POST',
									url: create_backup_url,
									data: CSRF_TOKEN,
									success: function(data) {
										backup_list.yiiGridView(
											'update',
											{
												url:
													location.pathname
														+ location.search
														+ location.hash
											}
										);

										global_data = JSON.parse(data);
										GetAccessToDropbox();
									}
								}
							);
						} else {
							$.post(
								create_backup_url,
								CSRF_TOKEN,
								function(data) {
									global_data = data;
									GetAccessToDropbox();
								},
								'json'
							).fail(BackupUtils.error);
						}

						BackupDialog.hide();
					}
				);
			}
		);
	}
);
<commit_msg>Issue #193: disable the forcing Dropbox access requiring.<commit_after>var BackupUtils = {};

$(document).ready(
	function() {
		var create_backup_button = $('.create-backup-button');
		var create_backup_url = create_backup_button.data('create-backup-url');
		var save_backup_url = create_backup_button.data('save-backup-url');
		var app_key = create_backup_button.data('dropbox-app-key');
		var redirect_url = create_backup_button.data('dropbox-redirect-url');
		var processing_animation_image = $('img', create_backup_button);
		var backup_icon = $('span', create_backup_button);
		var backup_list = $('#backup-list');
		var FinishAnimation = function() {
			create_backup_button.prop('disabled', false);
			processing_animation_image.hide();
			backup_icon.show();
		};
		var GetAccessToDropbox = function() {
			var url = 'https://www.dropbox.com/1/oauth2/authorize'
				+ '?response_type=code'
				+ '&client_id=' + app_key
				+ '&redirect_uri=' + encodeURIComponent(
					location.protocol + '//' + location.host + redirect_url
				);
			open(url, '_blank', 'width=640, height=480');
		};
		BackupUtils.error = function(xhr, text_status) {
			FinishAnimation();
			AjaxErrorDialog.handler(xhr, text_status);
		};

		var global_data = {backup_path: '', create_time: ''};
		window.Backup = {
			create: function(authorization_code) {
				var data = $.extend(
					{
						authorization_code: authorization_code,
						backup_path: global_data.backup_path,
						create_time: global_data.create_time
					},
					CSRF_TOKEN
				);

				$.post(
					save_backup_url,
					data,
					function() {
						FinishAnimation();

						if (backup_list.length) {
							backup_list.yiiGridView(
								'update',
								{
									url:
										location.pathname
											+ location.search
											+ location.hash
								}
							);
						}
					}
				).fail(BackupUtils.error);
			},
			error: AjaxErrorDialog.show
		};

		create_backup_button.click(
			function() {
				BackupDialog.show(
					function() {
						create_backup_button.prop('disabled', true);
						processing_animation_image.show();
						backup_icon.hide();

						if (backup_list.length) {
							backup_list.yiiGridView(
								'update',
								{
									type: 'POST',
									url: create_backup_url,
									data: CSRF_TOKEN,
									success: function(data) {
										backup_list.yiiGridView(
											'update',
											{
												url:
													location.pathname
														+ location.search
														+ location.hash
											}
										);

										global_data = JSON.parse(data);
										GetAccessToDropbox();
									}
								}
							);
						} else {
							$.post(
								create_backup_url,
								CSRF_TOKEN,
								function(data) {
									global_data = data;
									GetAccessToDropbox();
								},
								'json'
							).fail(BackupUtils.error);
						}

						BackupDialog.hide();
					}
				);
			}
		);
	}
);
<|endoftext|>


<commit_before>APP.components.stripeCheckout = (function() {

  function init() {
    if($('#stripeForm').exists()) initStripe();
    if($('#stripePlan').exists()) initPlan();
  }

  function initPlan() {
    $('select#stripePlan').on('change', function() {
      var stripePlan = $(this).find(":selected").text();
      var stripeDescription = $('#stripeForm #stripeDescription').val();
      stripeDescription += ': ' + stripePlan + ' / Monat';
      $('#stripeForm #stripeDescription').val(stripeDescription);
    });
  }

  function initStripe() {

    var handler = StripeCheckout.configure({
      key: $('#stripeForm #publishable_key').val(),
      locale: 'de',
      currency: 'eur',
      allowRememberMe: false,
      name: 'imGrätzl.at',
      description: $('#stripeForm #stripeDescription').val(),
      email: $('#stripeForm #stripeEmail').val(),
      image: $('#stripeForm #stripeIcon').val(),
      //billingAddress: $('#stripeForm #stripeBillingAddress').val(),
      token: function(response) {
        // Get Stripe response infos and pass to hidden form fields
        $('#stripeForm #stripeToken').val(response.id);
        $('#stripeForm #stripeEmail').val(response.email);
        $('#stripeForm').submit();
      }
    });

    // Submit Stripe Form
    $('.stripe-submit').on('click', function(e) {
      e.preventDefault();

      var email = $('#stripeForm #stripeEmail').val();
      var amount = $('#stripeForm #amount').val();
      amount = amount.replace(/,/g, '.');
      amount = amount.replace(/\$/g, '').replace(/\,/g, '');
      amount = parseFloat(amount);
      amount = Math.floor(amount); // Abrunden auf ganze Zahl

      if (isNaN(amount)) {
        $('#flash').html('
Bitte gib einen gültigen Betrag (€) ein.
').show();
        document.location.href = '#';
      } else if (amount < 3.00) {
        $('#flash').html('
Der Betrag muss mindestens 3 € betragen.
').show();
        document.location.href = '#';
      } else if (email == '') {
        $('#flash').html('
Bitte gib deine E-Mail Adresse an.
').show();
        document.location.href = '#';
      } else {
        $('#flash').hide();
        amount = amount * 100; // Needs to be an integer!
        handler.open({
          amount: Math.round(amount),
          email: $('#stripeForm #stripeEmail').val(),
        })
      }
    });

    // Submit Subscription Stripe Form
    $('.stripe-submit-subscription').on('click', function(e) {
      e.preventDefault();

      if ($('select#stripePlan :selected').val() == '') {
        $('#flash').html('
Bitte wähle einen monatlichen Betrag aus.
').show();
        document.location.href = '#';
      } else {
        handler.open({
          panelLabel: "Jetzt untertsützen",
          email: $('#stripeForm #stripeEmail').val(),
          description: $('#stripeForm #stripeDescription').val(),
        });
      }
    });

    // Close Checkout on page navigation
    $(window).on('popstate', function() {
      handler.close();
    });

  }

  return {
    init: init
  };

})();
<commit_msg>js number amount checks<commit_after>APP.components.stripeCheckout = (function() {

  function init() {
    if($('#stripeForm').exists()) initStripe();
    if($('#stripePlan').exists()) initPlan();
  }

  function cleanUpAmount(amount) {
    amount = amount.replace(/,/g, '.');
    amount = amount.replace(/\$/g, '').replace(/\,/g, '');
    amount = parseFloat(amount);
    amount = Math.floor(amount); // Abrunden auf ganze Zahl
    return amount;
  }

  function initPlan() {
    $('select#stripePlan').on('change', function() {
      var stripePlan = $(this).find(":selected").text();
      var stripeDescription = $('#stripeForm #stripeDescription').val();
      stripeDescription += ': ' + stripePlan + ' / Monat';
      $('#stripeForm #stripeDescription').val(stripeDescription);
    });
  }

  function initStripe() {

    // onFocusOut -> Abrunden auf ganzen Betrag, wenn Zahl.
    $('#amount').focusout(function(){
      var amount = cleanUpAmount(this.value);
      if (!isNaN(amount)) {
        $(this).val(cleanUpAmount(this.value));
      }
    });

    var handler = StripeCheckout.configure({
      key: $('#stripeForm #publishable_key').val(),
      locale: 'de',
      currency: 'eur',
      allowRememberMe: false,
      name: 'imGrätzl.at',
      description: $('#stripeForm #stripeDescription').val(),
      email: $('#stripeForm #stripeEmail').val(),
      image: $('#stripeForm #stripeIcon').val(),
      //billingAddress: $('#stripeForm #stripeBillingAddress').val(),
      token: function(response) {
        // Get Stripe response infos and pass to hidden form fields
        $('#stripeForm #stripeToken').val(response.id);
        $('#stripeForm #stripeEmail').val(response.email);
        $('#stripeForm').submit();
      }
    });

    // Submit Stripe Form
    $('.stripe-submit').on('click', function(e) {
      e.preventDefault();

      var email = $('#stripeForm #stripeEmail').val();
      var amount = $('#stripeForm #amount').val();
      amount = cleanUpAmount(amount); // Abrunden auf ganzen Betrag

      if (isNaN(amount)) {
        $('#flash').html('
Bitte gib einen gültigen Betrag (€) ein.
').show();
        document.location.href = '#';
      } else if (amount < 3.00) {
        $('#flash').html('
Der Betrag muss mindestens 3 € betragen.
').show();
        document.location.href = '#';
      } else if (email == '') {
        $('#flash').html('
Bitte gib deine E-Mail Adresse an.
').show();
        document.location.href = '#';
      } else {
        $('#flash').hide();
        amount = amount * 100; // Needs to be an integer!
        handler.open({
          amount: Math.round(amount),
          email: $('#stripeForm #stripeEmail').val(),
        })
      }
    });

    // Submit Subscription Stripe Form
    $('.stripe-submit-subscription').on('click', function(e) {
      e.preventDefault();

      if ($('select#stripePlan :selected').val() == '') {
        $('#flash').html('
Bitte wähle einen monatlichen Betrag aus.
').show();
        document.location.href = '#';
      } else {
        handler.open({
          panelLabel: "Jetzt untertsützen",
          email: $('#stripeForm #stripeEmail').val(),
          description: $('#stripeForm #stripeDescription').val(),
        });
      }
    });

    // Close Checkout on page navigation
    $(window).on('popstate', function() {
      handler.close();
    });

  }

  return {
    init: init
  };

})();
<|endoftext|>


<commit_before>var app = angular.module('callcenterApplication', ['ngMessages', 'glue.directives']);

app.controller('WorkflowController', function ($scope, $rootScope, $http, $interval, $log, $window) {

	/* misc configuration data, for instance callerId for outbound calls */
	$scope.configuration;

	/* contains task data pushed by the TaskRouter JavaScript SDK */
	$scope.reservation;
	$scope.tasks;

	/* contains worker record received by the Twilio API or the TaskRouter JavaScript SDK */
	$scope.worker;

	/* TaskRouter Worker */
	$scope.workerJS;

	/* UI */
	$scope.UI = { warning: { browser: null, worker: null}};

	if ($window.location.protocol !== 'https:') {
		let message =  `Depending on your browser and/or settings capturing audio and video
										requires a secure (HTTPS) page. The demo may not work.`;
		$scope.UI.warning.browser = message;
	}

	/* request configuration data and tokens from the backend */
	$scope.init = function () {

		$http.get('/api/agents/session')
			.then(function onSuccess (response) {

				/* keep a local copy of the configuration and the worker */
				$scope.configuration = response.data.configuration;

				/* initialize Twilio worker js with token received from the backend */
				$scope.initWorker(response.data.tokens.worker);

				/* initialize Twilio client with token received from the backend */
				$scope.$broadcast('InitializePhone', { token: response.data.tokens.phone});

				/* initialize Twilio Chat client with token received from the backend */
				$scope.$broadcast('InitializeChat', { token: response.data.tokens.chatAndVideo, identity: response.data.worker.friendlyName});

				// initialize Twilio Video client
				$scope.$broadcast('InitializeVideo', { token: response.data.tokens.chatAndVideo });

			}, function onError (response) {
				/* session is not valid anymore */
				if (response.status === 403) {
					window.location.replace('/callcenter/');
				} else {
					$log.error(JSON.stringify(response));
					$scope.UI.warning.worker = JSON.stringify(response);
					$scope.$apply();
				}

			});

	};

	$scope.initWorker = function (token) {

		/* create TaskRouter Worker */
		$scope.workerJS = new Twilio.TaskRouter.Worker(token, true, $scope.configuration.twilio.workerIdleActivitySid, $scope.configuration.twilio.workerOfflineActivitySid);

		$scope.workerJS.on('ready', function (worker) {

			$log.log('TaskRouter Worker: ready');

			$scope.worker = worker;

		});

		$scope.workerJS.on('reservation.created', function (reservation) {

			$log.log('TaskRouter Worker: reservation.created');
			$log.log(reservation);

			$scope.reservation = reservation;
			$scope.$apply();

			$scope.startReservationCounter();

		});

		$scope.workerJS.on('reservation.accepted', function (reservation) {

			$log.log('TaskRouter Worker: reservation.accepted');
			$log.log(reservation);

			$scope.task = reservation.task;

			/* check if the customer name is a phone number */
			var pattern = /(.*)(\+[0-9]{8,20})(.*)$/;

			if (pattern.test($scope.task.attributes.name) === true) {
				$scope.task.attributes.nameIsPhoneNumber = true;
			}

			$scope.task.completed = false;
			$scope.reservation = null;
			$scope.stopReservationCounter();

			$scope.$apply();

		});

		$scope.workerJS.on('reservation.timeout', function (reservation) {

			$log.log('TaskRouter Worker: reservation.timeout');
			$log.log(reservation);

			/* reset all data */
			$scope.reservation = null;
			$scope.task = null;
			$scope.$apply();

		});

		$scope.workerJS.on('reservation.rescinded', function (reservation) {

			$log.log('TaskRouter Worker: reservation.rescinded');
			$log.log(reservation);

			/* reset all data */
			$scope.reservation = null;
			$scope.task = null;
			$scope.$apply();

		});

		$scope.workerJS.on('reservation.canceled', function (reservation) {

			$log.log('TaskRouter Worker: reservation.cancelled');
			$log.log(reservation);

			$scope.reservation = null;
			$scope.task = null;
			$scope.$apply();

		});

		$scope.workerJS.on('activity.update', function (worker) {

			$log.log('TaskRouter Worker: activity.update');
			$log.log(worker);

			$scope.worker = worker;
			$scope.$apply();

		});

		$scope.workerJS.on('token.expired', function () {

			$log.log('TaskRouter Worker: token.expired');

			$scope.reservation = null;
			$scope.task = null;
			$scope.$apply();

			/* the worker token expired, the agent shoud log in again, token is generated upon log in */
			window.location.replace('/callcenter/');

		});

		/* the agent's browser lost the connection to Twilio */
		$scope.workerJS.on('connected', function () {
			$log.log('TaskRouter Worker: WebSocket has connected');
			$scope.UI.warning.worker = null;
			$scope.$apply();
		});

		$scope.workerJS.on('disconnected', function () {
			$log.error('TaskRouter Worker: WebSocket has disconnected');
			$scope.UI.warning.worker = 'TaskRouter Worker: WebSocket has disconnected';
			$scope.$apply();
		});

		$scope.workerJS.on('error', function (error) {
			$log.error('TaskRouter Worker: an error occurred: ' + error.response + ' with message: ' + error.message);
			$scope.UI.warning.worker = 'TaskRouter Worker: an error occured: ' + error.response + ' with message: ' + error.message;
			$scope.$apply();
		});

	};

	$scope.acceptReservation = function (reservation) {

		$log.log('accept reservation with TaskRouter Worker JavaScript SDK');

		/* depending on the typ of taks that was created we handle the reservation differently */
		if (reservation.task.attributes.channel === 'video') {

			reservation.accept(

				function (err, reservation) {

					if (err) {
						$log.error(err);
						return;
					}

					$scope.$broadcast('ActivateVideo', { roomName: reservation.task.attributes.roomName });

				});

		}

		if (reservation.task.attributes.channel === 'chat') {

			reservation.accept(

				function (err, reservation) {

					if (err) {
						$log.error(err);
						return;
					}

					$scope.$broadcast('ActivateChat', { channelSid: reservation.task.attributes.channelSid });

				});

		}

		if (reservation.task.attributes.channel === 'phone' && reservation.task.attributes.type === 'inbound_call') {

			$log.log('dequeue reservation with  callerId: ' + $scope.configuration.twilio.callerId);
			reservation.conference($scope.configuration.twilio.callerId, undefined, undefined, function (err, reservation){

				if (err) {
					$log.error(err);
					return;
				}

			});

		}

		/* we accept the reservation and initiate a call to the customer's phone number */
		if (reservation.task.attributes.channel === 'phone' && reservation.task.attributes.type === 'callback_request') {

			reservation.accept(

				function (err, reservation) {

					if (err) {
						$log.error(err);
						return;
					}

					$scope.$broadcast('CallPhoneNumber', { phoneNumber: reservation.task.attributes.phone });

				});
		}
	};

	$scope.complete = function (reservation) {

		switch ($scope.task.attributes.channel) {
		case 'video':
			$scope.$broadcast('DestroyVideo');
			break;
		case 'chat':
			$scope.$broadcast('DestroyChat');
			break;
		default:
		// do nothing
		}

		$scope.workerJS.update('ActivitySid', $scope.configuration.twilio.workerIdleActivitySid, function (err, worker) {

			if (err) {
				$log.error(err);
				return;
			}

			$scope.reservation = null;
			$scope.task = null;
			$scope.$apply();

		});

	};

	$scope.callPhoneNumber = function (phoneNumber) {
		$rootScope.$broadcast('CallPhoneNumber', { phoneNumber: phoneNumber });
	};

	$scope.logout = function () {

		$http.post('/api/agents/logout')
			.then(function onSuccess (response) {
				window.location.replace('/callcenter/index.html');
			}, function onError (response) {
				$log.error(response);
			});

	};

	$scope.startReservationCounter = function () {

		$log.log('start reservation counter');
		$scope.reservationCounter = $scope.reservation.task.age;

		$scope.reservationInterval = $interval(function () {
			$scope.reservationCounter++;
		}, 1000);

	};

	$scope.stopReservationCounter = function () {

		if (angular.isDefined($scope.reservationInterval)) {
			$interval.cancel($scope.reservationInterval);
			$scope.reservationInterval = undefined;
		}

	};

});<commit_msg>Mark the task as completed<commit_after>var app = angular.module('callcenterApplication', ['ngMessages', 'glue.directives']);

app.controller('WorkflowController', function ($scope, $rootScope, $http, $interval, $log, $window) {

	/* misc configuration data, for instance callerId for outbound calls */
	$scope.configuration;

	/* contains task data pushed by the TaskRouter JavaScript SDK */
	$scope.reservation;
	$scope.tasks;

	/* contains worker record received by the Twilio API or the TaskRouter JavaScript SDK */
	$scope.worker;

	/* TaskRouter Worker */
	$scope.workerJS;

	/* UI */
	$scope.UI = { warning: { browser: null, worker: null}};

	if ($window.location.protocol !== 'https:') {
		let message =  `Depending on your browser and/or settings capturing audio and video
										requires a secure (HTTPS) page. The demo may not work.`;
		$scope.UI.warning.browser = message;
	}

	/* request configuration data and tokens from the backend */
	$scope.init = function () {

		$http.get('/api/agents/session')
			.then(function onSuccess (response) {

				/* keep a local copy of the configuration and the worker */
				$scope.configuration = response.data.configuration;

				/* initialize Twilio worker js with token received from the backend */
				$scope.initWorker(response.data.tokens.worker);

				/* initialize Twilio client with token received from the backend */
				$scope.$broadcast('InitializePhone', { token: response.data.tokens.phone});

				/* initialize Twilio Chat client with token received from the backend */
				$scope.$broadcast('InitializeChat', { token: response.data.tokens.chatAndVideo, identity: response.data.worker.friendlyName});

				// initialize Twilio Video client
				$scope.$broadcast('InitializeVideo', { token: response.data.tokens.chatAndVideo });

			}, function onError (response) {
				/* session is not valid anymore */
				if (response.status === 403) {
					window.location.replace('/callcenter/');
				} else {
					$log.error(JSON.stringify(response));
					$scope.UI.warning.worker = JSON.stringify(response);
					$scope.$apply();
				}

			});

	};

	$scope.initWorker = function (token) {

		/* create TaskRouter Worker */
		$scope.workerJS = new Twilio.TaskRouter.Worker(token, true, $scope.configuration.twilio.workerIdleActivitySid, $scope.configuration.twilio.workerOfflineActivitySid);

		$scope.workerJS.on('ready', function (worker) {

			$log.log('TaskRouter Worker: ready');

			$scope.worker = worker;

		});

		$scope.workerJS.on('reservation.created', function (reservation) {

			$log.log('TaskRouter Worker: reservation.created');
			$log.log(reservation);

			$scope.reservation = reservation;
			$scope.$apply();

			$scope.startReservationCounter();

		});

		$scope.workerJS.on('reservation.accepted', function (reservation) {

			$log.log('TaskRouter Worker: reservation.accepted');
			$log.log(reservation);

			$scope.task = reservation.task;

			/* check if the customer name is a phone number */
			var pattern = /(.*)(\+[0-9]{8,20})(.*)$/;

			if (pattern.test($scope.task.attributes.name) === true) {
				$scope.task.attributes.nameIsPhoneNumber = true;
			}

			$scope.task.completed = false;
			$scope.reservation = null;
			$scope.stopReservationCounter();

			$scope.$apply();

		});

		$scope.workerJS.on('reservation.timeout', function (reservation) {

			$log.log('TaskRouter Worker: reservation.timeout');
			$log.log(reservation);

			/* reset all data */
			$scope.reservation = null;
			$scope.task = null;
			$scope.$apply();

		});

		$scope.workerJS.on('reservation.rescinded', function (reservation) {

			$log.log('TaskRouter Worker: reservation.rescinded');
			$log.log(reservation);

			/* reset all data */
			$scope.reservation = null;
			$scope.task = null;
			$scope.$apply();

		});

		$scope.workerJS.on('reservation.canceled', function (reservation) {

			$log.log('TaskRouter Worker: reservation.cancelled');
			$log.log(reservation);

			$scope.reservation = null;
			$scope.task = null;
			$scope.$apply();

		});

		$scope.workerJS.on('activity.update', function (worker) {

			$log.log('TaskRouter Worker: activity.update');
			$log.log(worker);

			$scope.worker = worker;
			$scope.$apply();

		});

		$scope.workerJS.on('token.expired', function () {

			$log.log('TaskRouter Worker: token.expired');

			$scope.reservation = null;
			$scope.task = null;
			$scope.$apply();

			/* the worker token expired, the agent shoud log in again, token is generated upon log in */
			window.location.replace('/callcenter/');

		});

		/* the agent's browser lost the connection to Twilio */
		$scope.workerJS.on('connected', function () {
			$log.log('TaskRouter Worker: WebSocket has connected');
			$scope.UI.warning.worker = null;
			$scope.$apply();
		});

		$scope.workerJS.on('disconnected', function () {
			$log.error('TaskRouter Worker: WebSocket has disconnected');
			$scope.UI.warning.worker = 'TaskRouter Worker: WebSocket has disconnected';
			$scope.$apply();
		});

		$scope.workerJS.on('error', function (error) {
			$log.error('TaskRouter Worker: an error occurred: ' + error.response + ' with message: ' + error.message);
			$scope.UI.warning.worker = 'TaskRouter Worker: an error occured: ' + error.response + ' with message: ' + error.message;
			$scope.$apply();
		});

	};

	$scope.acceptReservation = function (reservation) {

		$log.log('accept reservation with TaskRouter Worker JavaScript SDK');

		/* depending on the typ of taks that was created we handle the reservation differently */
		if (reservation.task.attributes.channel === 'video') {

			reservation.accept(

				function (err, reservation) {

					if (err) {
						$log.error(err);
						return;
					}

					$scope.$broadcast('ActivateVideo', { roomName: reservation.task.attributes.roomName });

				});

		}

		if (reservation.task.attributes.channel === 'chat') {

			reservation.accept(

				function (err, reservation) {

					if (err) {
						$log.error(err);
						return;
					}

					$scope.$broadcast('ActivateChat', { channelSid: reservation.task.attributes.channelSid });

				});

		}

		if (reservation.task.attributes.channel === 'phone' && reservation.task.attributes.type === 'inbound_call') {

			$log.log('dequeue reservation with  callerId: ' + $scope.configuration.twilio.callerId);
			reservation.conference($scope.configuration.twilio.callerId, undefined, undefined, function (err, reservation) {

				if (err) {
					$log.error(err);
					return;
				}

			});

		}

		/* we accept the reservation and initiate a call to the customer's phone number */
		if (reservation.task.attributes.channel === 'phone' && reservation.task.attributes.type === 'callback_request') {

			reservation.accept(

				function (err, reservation) {

					if (err) {
						$log.error(err);
						return;
					}

					$scope.$broadcast('CallPhoneNumber', { phoneNumber: reservation.task.attributes.phone });

				});
		}
	};

	$scope.complete = function (reservation) {

		switch ($scope.task.attributes.channel) {
		case 'video':
			$scope.$broadcast('DestroyVideo');
			break;
		case 'chat':
			$scope.$broadcast('DestroyChat');
			break;
		default:
		// do nothing
		}

		$scope.workerJS.completeTask($scope.task.sid, function (error, completedTask) {
			if (error) {
				$log.error(error.code);
				$log.error(error.message);
				return;
			}
			$log.log('Completed Task: ' + completedTask.assignmentStatus);

		});

		$scope.workerJS.update('ActivitySid', $scope.configuration.twilio.workerIdleActivitySid, function (err, worker) {

			if (err) {
				$log.error(err);
				return;
			}

			$scope.reservation = null;
			$scope.task = null;
			$scope.$apply();

		});

	};

	$scope.callPhoneNumber = function (phoneNumber) {
		$rootScope.$broadcast('CallPhoneNumber', { phoneNumber: phoneNumber });
	};

	$scope.logout = function () {

		$http.post('/api/agents/logout')
			.then(function onSuccess (response) {
				window.location.replace('/callcenter/index.html');
			}, function onError (response) {
				$log.error(response);
			});

	};

	$scope.startReservationCounter = function () {

		$log.log('start reservation counter');
		$scope.reservationCounter = $scope.reservation.task.age;

		$scope.reservationInterval = $interval(function () {
			$scope.reservationCounter++;
		}, 1000);

	};

	$scope.stopReservationCounter = function () {

		if (angular.isDefined($scope.reservationInterval)) {
			$interval.cancel($scope.reservationInterval);
			$scope.reservationInterval = undefined;
		}

	};

});<|endoftext|>


<commit_before>
var app = angular.module('simpleapp', ['ng', 'ngRoute']);

app.controller(
    'simpleController',
    function ($scope, $location, $http) {
        $scope.currentUrl = $location.absUrl();
    }
);

app.config(
    function ($routeProvider, $locationProvider) {
        $locationProvider.html5Mode(true);
        $routeProvider.when(
            '/weather',
            {
                template: '
Weather for {{weather.name}}

{{weather | json}}
',
                resolve: {
                    weatherData: function ($http) {
                        return $http.get(
                            'http://api.openweathermap.org/data/2.5/weather?q=San%20Francisco,%20CA,%20US'
                        ).then(function (resp) { return resp.data; });
                    }
                },
                controller: function (weatherData, $scope) {
                    $scope.weather = weatherData;
                }
            }
        );
        $routeProvider.otherwise(
            {
                template: 'Weather'
            }
        );
    }
);
<commit_msg>Make the weather page use a named controller.<commit_after>
var app = angular.module('simpleapp', ['ng', 'ngRoute']);

app.controller(
    'simpleController',
    function ($scope, $location, $http) {
        $scope.currentUrl = $location.absUrl();
    }
);

app.controller(
    'weatherController',
    function (weatherData, $scope) {
        $scope.weather = weatherData;
    }
);

app.config(
    function ($routeProvider, $locationProvider) {
        $locationProvider.html5Mode(true);
        $routeProvider.when(
            '/weather',
            {
                template: '
Weather for {{weather.name}}

{{weather | json}}
',
                resolve: {
                    weatherData: function ($http) {
                        return $http.get(
                            'http://api.openweathermap.org/data/2.5/weather?q=San%20Francisco,%20CA,%20US'
                        ).then(function (resp) { return resp.data; });
                    }
                },
                controller: 'weatherController'
            }
        );
        $routeProvider.otherwise(
            {
                template: 'Weather'
            }
        );
    }
);
<|endoftext|>


<commit_before>'use strict';

var React = require('react');
var ReactDOM = require('react-dom');
var d3 = require('d3');

require('stylesheets/re-stock');

var ReadME = require('md/MAIN.md');

document.getElementById("content").innerHTML = ReadME;

var parseDate = d3.time.format("%Y-%m-%d").parse
d3.tsv("data/MSFT.tsv", function(err, data) {
	data.forEach((d, i) => {
		d.date = new Date(parseDate(d.date).getTime());
		d.open = +d.open;
		d.high = +d.high;
		d.low = +d.low;
		d.close = +d.close;
		d.volume = +d.volume;
		// console.log(d);
	});

	var Chart = require('lib/charts/CandleStickChartWithMACDIndicator');

	ReactDOM.render(<Chart data={data} type="hybrid"/>, document.getElementById("chart"));
});
<commit_msg>fix indexhtml<commit_after>'use strict';

var React = require('react');
var ReactDOM = require('react-dom');
var d3 = require('d3');

require('stylesheets/re-stock');

var ReadME = require('md/MAIN.md');

document.getElementById("content").innerHTML = ReadME;

var parseDate = d3.time.format("%Y-%m-%d").parse
d3.tsv("data/MSFT.tsv", function(err, data) {
	data.forEach((d, i) => {
		d.date = new Date(parseDate(d.date).getTime());
		d.open = +d.open;
		d.high = +d.high;
		d.low = +d.low;
		d.close = +d.close;
		d.volume = +d.volume;
		// console.log(d);
	});

	var Chart = require('lib/charts/CandleStickChartWithMACDIndicator');

	React.render(<Chart data={data} type="hybrid"/>, document.getElementById("chart"));
});
<|endoftext|>


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

'use strict';

const test = require('tape');
const L = require('lodash');
const jitter = require('../../../core/lib/jitter').jitter;
const util = require('../../../core/lib/engine_util');

test('jitter', function(t) {
  t.assert(jitter(1000) === 1000, 'Number and no other params should return the number');
  t.assert(jitter('1000') === '1000', 'String that is not a template and no other params should return the string');

  let fails1 = 0;
  for(let i = 0; i < 100; i++) {
    let largeDeviation = jitter('1000:5000');
    if (largeDeviation < 0) {
      t.assert(false, `largeDeviation is ${largeDeviation}; expected >= 0`);
      fails1++;
    }
  }
  if (fails1 === 0) {
    t.assert(true, 'Result should be >= 0');
  }

  let fails2 = 0;
  for(let i = 0; i < 100; i++) {
    let percentJitter = jitter('5000:20%');
    if (percentJitter < 4000 || percentJitter > 6000) {
      t.assert(false, `percentJitter is ${percentJitter}; expected >=4000 <=6000`);
      fails2++;
    }
  }
  if (fails2 === 0) {
    t.assert(true, 'Percentage-based jitter should be within bounds');
  }

  t.end();
});

test('loop - error handling', function(t) {
  let steps = [
    function(context, next) {
      return next(null, context);
    },
    function(context, next) {
      if (context.vars.$loopCount === 5) {
        return next(new Error('ESOMEERR'), context);
      } else {
        return next(null, context);
      }
    }
  ];
  let loop = util.createLoopWithCount(10, steps, { });
  loop({ vars: {} }, function(err, context) {
    t.assert(
      typeof err === 'object' && err.message === 'ESOMEERR',
      'Errors are returned normally from loop steps');
    t.end();
  });
});

test('rendering variables', function(t) {
  let str = 'Hello {{ name }}, hope your {{{ day }}} is going great!';
  let vars = {
    name: 'Hassy',
    day: 'Friday',
    favoriteThings: {
      color: 'red',
      food: 'tacos',
      day: 'Friday',
      animals: ['dogs', 'cats', 'ponies', 'donkeys']
    },
    zeroValue: 0
  };

  const render = util._renderVariables;

  t.assert(
    render(str, vars) === 'Hello Hassy, hope your Friday is going great!',
    'Variables are substituted with either double or triple curly braces');

  t.assert(
    render('{{ s }} - {{ s }} {}', { s: 'foo' }) === 'foo - foo {}',
    'Multiple instances of a variable get replaced');

  t.assert(
    render(' {{   foo}} ', { foo: 'bar' }) === ' bar ',
    'Whitespace inside templates is not significant');

  t.assert(
    render('Hello {{ name }}', { foo: 'bar', day: 'Sunday' }) === 'Hello undefined',
    'Undefined variables get replaced with undefined string');

  t.assert(
    render('', { foo: 'bar', name: 'Hassy', color: 'red' }) === '',
    'Empty string produces an empty string');

  t.assert(
    render('Hello world!', { foo: 'bar', name: 'Hassy', color: 'red' }) === 'Hello world!',
    'String with no templates produces itself');

  t.assert(
    render('{{ favoriteThings.color }}', vars) === 'red',
    'Object properties may be looked up with dots'
  );

  t.assert(
    render('{{ favoriteThings.animals[0] }}', vars) === 'dogs',
    'Numeric indexes may be used for property lookups'
  );

  t.assert(
    render('{{favoriteThings.dayOfTheWeek}}', vars) === '',
    'Non-existent property lookup returns an empty string'
  );

  t.assert(
    render('{{ favoriteThings.animals }}', vars) === vars.favoriteThings.animals,
    'Values returned from property lookups retain their type'
  );

  t.assert(
    render('abc-{{ favoriteThings.animals[1] }}-123-{{ day }} 🐢🚀', vars) === 'abc-cats-123-Friday 🐢🚀',
    'Values returned from property lookups are interpolated as expected'
  );

  t.assert(
    render('{{ zeroValue }}', vars) === 0,
    'Can render zero values'
  );

  t.end();
});
<commit_msg>add tests for boolean values<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

'use strict';

const test = require('tape');
const L = require('lodash');
const jitter = require('../../../core/lib/jitter').jitter;
const util = require('../../../core/lib/engine_util');

test('jitter', function(t) {
  t.assert(jitter(1000) === 1000, 'Number and no other params should return the number');
  t.assert(jitter('1000') === '1000', 'String that is not a template and no other params should return the string');

  let fails1 = 0;
  for(let i = 0; i < 100; i++) {
    let largeDeviation = jitter('1000:5000');
    if (largeDeviation < 0) {
      t.assert(false, `largeDeviation is ${largeDeviation}; expected >= 0`);
      fails1++;
    }
  }
  if (fails1 === 0) {
    t.assert(true, 'Result should be >= 0');
  }

  let fails2 = 0;
  for(let i = 0; i < 100; i++) {
    let percentJitter = jitter('5000:20%');
    if (percentJitter < 4000 || percentJitter > 6000) {
      t.assert(false, `percentJitter is ${percentJitter}; expected >=4000 <=6000`);
      fails2++;
    }
  }
  if (fails2 === 0) {
    t.assert(true, 'Percentage-based jitter should be within bounds');
  }

  t.end();
});

test('loop - error handling', function(t) {
  let steps = [
    function(context, next) {
      return next(null, context);
    },
    function(context, next) {
      if (context.vars.$loopCount === 5) {
        return next(new Error('ESOMEERR'), context);
      } else {
        return next(null, context);
      }
    }
  ];
  let loop = util.createLoopWithCount(10, steps, { });
  loop({ vars: {} }, function(err, context) {
    t.assert(
      typeof err === 'object' && err.message === 'ESOMEERR',
      'Errors are returned normally from loop steps');
    t.end();
  });
});

test('rendering variables', function(t) {
  let str = 'Hello {{ name }}, hope your {{{ day }}} is going great!';
  let vars = {
    name: 'Hassy',
    day: 'Friday',
    favoriteThings: {
      color: 'red',
      food: 'tacos',
      day: 'Friday',
      animals: ['dogs', 'cats', 'ponies', 'donkeys']
    },
    zeroValue: 0,
    falseValue: false,
    trueValue: true
  };

  const render = util._renderVariables;

  t.assert(
    render(str, vars) === 'Hello Hassy, hope your Friday is going great!',
    'Variables are substituted with either double or triple curly braces');

  t.assert(
    render('{{ s }} - {{ s }} {}', { s: 'foo' }) === 'foo - foo {}',
    'Multiple instances of a variable get replaced');

  t.assert(
    render(' {{   foo}} ', { foo: 'bar' }) === ' bar ',
    'Whitespace inside templates is not significant');

  t.assert(
    render('Hello {{ name }}', { foo: 'bar', day: 'Sunday' }) === 'Hello undefined',
    'Undefined variables get replaced with undefined string');

  t.assert(
    render('', { foo: 'bar', name: 'Hassy', color: 'red' }) === '',
    'Empty string produces an empty string');

  t.assert(
    render('Hello world!', { foo: 'bar', name: 'Hassy', color: 'red' }) === 'Hello world!',
    'String with no templates produces itself');

  t.assert(
    render('{{ favoriteThings.color }}', vars) === 'red',
    'Object properties may be looked up with dots'
  );

  t.assert(
    render('{{ favoriteThings.animals[0] }}', vars) === 'dogs',
    'Numeric indexes may be used for property lookups'
  );

  t.assert(
    render('{{favoriteThings.dayOfTheWeek}}', vars) === '',
    'Non-existent property lookup returns an empty string'
  );

  t.assert(
    render('{{ favoriteThings.animals }}', vars) === vars.favoriteThings.animals,
    'Values returned from property lookups retain their type'
  );

  t.assert(
    render('abc-{{ favoriteThings.animals[1] }}-123-{{ day }} 🐢🚀', vars) === 'abc-cats-123-Friday 🐢🚀',
    'Values returned from property lookups are interpolated as expected'
  );

  t.assert(
    render('{{ zeroValue }}', vars) === 0,
    'Can render zero values'
  );

  t.assert(
    render('{{ falseValue }}', vars) === false,
    'Can render false values'
  );

  t.assert(
    render('{{ trueValue }}', vars) === true,
    'Can render true values'
  );

  t.end();
});
<|endoftext|>


<commit_before>var Conduit = require('conduit')
var Destructible = require('destructible')
var cadence = require('cadence')
var util = require('util')
var Signal = require('signal')
var stream = require('stream')
var Staccato = require('staccato')
var http = require('http')
var Downgrader = require('downgrader')
var delta = require('delta')
var Interrupt = require('interrupt').createInterrupter('olio')
var coalesce = require('extant')
var Procession = require('procession')

function SocketFactory () {
}

SocketFactory.prototype.createReceiver = cadence(function (async, destructible, Receiver, message, socket) {
    async(function () {
        destructible.monitor('receiver', Receiver, message.from, message.to, async())
    }, function (receiver) {
        destructible.monitor('conduit', Conduit, receiver, socket, socket, async())
    }, function (conduit) {
        conduit.receiver.outbox.push({ module: 'olio', method: 'connect' })
    })
})

SocketFactory.prototype.createSender = cadence(function (async, destructible, from, Receiver, message, handle, index) {
    var through = new stream.PassThrough
    var readable = new Staccato.Readable(through)

    async(function () {
        var request = http.request({
            socketPath: message.socketPath,
            url: 'http://olio',
            headers: Downgrader.headers({
                'x-olio-to-index': index,
                'x-olio-to-name': message.name,
                'x-olio-from-index': from.index,
                'x-olio-from-name': from.name
            })
        })
        delta(async()).ee(request).on('upgrade')
        request.end()
    }, function (request, socket, head) {
        async(function () {
            destructible.monitor('receiver', Receiver, message.argv, index, message.count, async())
        }, function (receiver) {
            var sip = {
                outbox: receiver.outbox,
                inbox: new Procession
            }
            var shifter = sip.inbox.shifter()
            async(function () {
                destructible.monitor('conduit', Conduit, sip, socket, socket, head, async())
            }, function (conduit) {
                async(function () {
                    shifter.dequeue(async())
                }, function (header) {
                    Interrupt.assert(header.module == 'olio' && header.method == 'connect', 'failed to start middleware')
                    Interrupt.assert(shifter.shift() == null, 'unexpected traffic on connect')
                    conduit.receiver = receiver
                    // Do we do this or do we register an end to pumping instead? It
                    // would depend on how we feal about ending a Conduit. I do
                    // believe it pushed out a `null` to indicate that the stream
                    // has closed. A Window would look for this and wait for
                    // restart. The Window needs to be closed explicity.
                })
            }, function() {
                return [ receiver ]
            })
        })
    })
})

module.exports = SocketFactory
<commit_msg>Remove unused variables.<commit_after>var Conduit = require('conduit')
var Destructible = require('destructible')
var cadence = require('cadence')
var util = require('util')
var Signal = require('signal')
var stream = require('stream')
var Staccato = require('staccato')
var http = require('http')
var Downgrader = require('downgrader')
var delta = require('delta')
var Interrupt = require('interrupt').createInterrupter('olio')
var coalesce = require('extant')
var Procession = require('procession')

function SocketFactory () {
}

SocketFactory.prototype.createReceiver = cadence(function (async, destructible, Receiver, message, socket) {
    async(function () {
        destructible.monitor('receiver', Receiver, message.from, message.to, async())
    }, function (receiver) {
        destructible.monitor('conduit', Conduit, receiver, socket, socket, async())
    }, function (conduit) {
        conduit.receiver.outbox.push({ module: 'olio', method: 'connect' })
    })
})

SocketFactory.prototype.createSender = cadence(function (async, destructible, from, Receiver, message, handle, index) {
    async(function () {
        var request = http.request({
            socketPath: message.socketPath,
            url: 'http://olio',
            headers: Downgrader.headers({
                'x-olio-to-index': index,
                'x-olio-to-name': message.name,
                'x-olio-from-index': from.index,
                'x-olio-from-name': from.name
            })
        })
        delta(async()).ee(request).on('upgrade')
        request.end()
    }, function (request, socket, head) {
        async(function () {
            destructible.monitor('receiver', Receiver, message.argv, index, message.count, async())
        }, function (receiver) {
            var sip = {
                outbox: receiver.outbox,
                inbox: new Procession
            }
            var shifter = sip.inbox.shifter()
            async(function () {
                destructible.monitor('conduit', Conduit, sip, socket, socket, head, async())
            }, function (conduit) {
                async(function () {
                    shifter.dequeue(async())
                }, function (header) {
                    Interrupt.assert(header.module == 'olio' && header.method == 'connect', 'failed to start middleware')
                    Interrupt.assert(shifter.shift() == null, 'unexpected traffic on connect')
                    conduit.receiver = receiver
                    // Do we do this or do we register an end to pumping instead? It
                    // would depend on how we feal about ending a Conduit. I do
                    // believe it pushed out a `null` to indicate that the stream
                    // has closed. A Window would look for this and wait for
                    // restart. The Window needs to be closed explicity.
                })
            }, function() {
                return [ receiver ]
            })
        })
    })
})

module.exports = SocketFactory
<|endoftext|>


<commit_before>/**
* This file is part of taolin project (http://taolin.fbk.eu)
* Copyright (C) 2008, 2009 FBK Foundation, (http://www.fbk.eu)
* Authors: SoNet Group (see AUTHORS.txt)
*
* Taolin is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation version 3 of the License.
*
* Taolin is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Taolin. If not, see <http://www.gnu.org/licenses/>.
*
*/

westPanel = new Ext.Panel({
    region:'west',
    id:'west-panel',
    title:'Social Bar',
    split:true,
    width: 220,
    minSize: 220,
    maxSize: 400,
    /* This panel should not be closed, only collapsed */
    tools: toolsnotclose,
    hideCollapseTool:true,
    collapsible: true,
    margins:'5 0 5 5',
    cmargins:'5 5 5 5',
    layout:'accordion',
    layoutConfig:{
        hideCollapseTool:true,
        titleCollapse:true,
        activeOnTop: false
    },
    items: [{
        xtype:'timeline'
        /* Be careful if you want to change this id. It is used several times
         * to access to the timeline and to its methods (in Timeline.js or in
         * reloadTimeline() into functions.js)
         */
        ,id: 'timeline'
    },{
        xtype:'userprofile'
        ,id: 'user_profile'
    },{
        title:'Edit your profile',
        border:false,
        autoScroll:true,
        iconCls:'settings',
        frame:true,
        id:'settings',
        layout: 'fit',
        collapsible:true,
        hideCollapseTool:true,
        tools: toolsnotclose,
        listeners: {
            /* When this accordion panel collapse it expands automatically
             * the other panel
             *
             * not in use
             */
            /*collapse: expandUserPanel,*/
            render: function(t){
                t.add(new Ext.ux.fbk.sonet.Settings());
            }
        }
    }]

    /**
      * @param {String} login requested user's login
      */
    ,showPublik: function(login){
        var tab = Ext.getCmp('wp-publik-tab');

        tab.store.load({params: {login: login}});
    }

    /**
      * @param {Integer} id requested user's id
      *
      */
    ,showPhotos: function(id){
        var tab = Ext.getCmp('wp-photos-tab');

        tab.store.load({params: {id: id}});
    }

    /** showUser function
     * show selected user's profile
     * @param {Integer} reqid requested user's id
     * @param {bool} hidePanel if true the user profile panel has not to be shown
     * @param {String} source for logging porpouse, it records the place where the requests started
     */
    ,showUser: function(reqid, hidePanel, logparams){

        if (!reqid) reqid = '';
        if (!hidePanel) {
            hidePanel = false;
        }

        Ext.Ajax.request({
            url : 'users/getinfo/'+reqid,
            method: 'GET',
            params: {src: logparams},
            success: function ( result, request ) {
                /*
                 * Whenever this function shows user info it shall expand both
                 * western panel and accordion panel containing 'user_image' div
                 */
                westPanel.expand();

                // Show user info (aka first tab of tabpanel)
                Ext.getCmp('user_profile').items.items[1].setActiveTab(0);

                if(!hidePanel) expandUserPanel();
                var jsondata = Ext.util.JSON.decode(result.responseText);
                westPanel.showedUser = jsondata.user;
                var user_text = '';

                if(reqid==='') { //this call always gives access to this user data
                    Ext.get("logged_as_username").update(
                        ''+jsondata.user.login+''
                    );
                    window.thisId = jsondata.user.id;
                    window.thisLogin = jsondata.user.login;
                    if(jsondata.user.email)
                        window.thisEmail = jsondata.user.email;
                }

                westPanel.showPublik(jsondata.user.login);
                westPanel.showPhotos(jsondata.user.id);

                //save in a retrievable place if this photo is user's photo
                //and then show tools
                westPanel.showTools = ((!reqid) || (reqid == window.thisId));
                showText(westPanel.showTools, 'user-profile-edit-div'); // Shows tools and Edit box only if the showed profile belongs to the user

                if (('photo' in jsondata.user) && (jsondata.user.photo)){
                    Ext.get("user_photo").dom.src = jsondata.user.photo;
                } else {
                    Ext.get("user_photo").dom.src = 'img/nophoto.png';
                }

                var mod_description = jsondata.user.mod_description;
                // call the methods urlize and smilize only if the object is not null
                if(mod_description) {
                    mod_description=mod_description.urlize().smilize();
                    //replaces \n with
 for visualization in html
                    mod_description=Ext.util.Format.htmlDecode(mod_description.replace(/(\n)/g,'
'));
                }

                var tpl = new Ext.XTemplate(
                    '
',
                    '

{name} {surname}',
                    '<tpl if="((this.reqid === \'\') || (this.reqid == window.thisId))">',
                        'Edit',
                    '</tpl>',
                    '
',
                    '',
                    /* check if the user is "chattable" */
                    '<tpl if="((this.reqid !== \'\') && (login) && (jabber.u_n !== login) && (active === \'1\'))">',
                        '

Chat with {name} {surname}
',
                    '</tpl>
',
                    /* if s/he is not a champion, suggest as a champion! */
                    '<tpl if="((this.reqid !== \'\') && (active !== \'1\'))">',
                        '

{name} is not a champion. You can suggest {name} to SoNet team as a new champion!
',
                    '</tpl>
',
                    '
Login: ',
                    ' {[values.login ? values.login : "unavailable"]} ',
                    '<tpl if="email">',
                            '
E-mail:  {email}',
                    '</tpl>',
                    '<tpl if="((phone) && (phone != \'0\'))">',
                        '
Phone: {phone}',
                    '</tpl>',
                    '<tpl if="((phone2) && (phone2 != \'0\'))">',
                        '
Phone 2: {phone2}',
                    '</tpl>',
                    '<tpl if="((personal_page) && (personal_page != \'null\'))">',
                        '
Home page: {[values.personal_page.substr(0,7)==="http://" ? values.personal_page.substr(7) : values.personal_page]}',
                    '</tpl>',
                    '<tpl if="building_id">',
                        '
Workplace: where\'s {[this.getPronoun(values.gender)]} office?',
                    '</tpl>',
                    '<tpl if="date_of_birth">',
                        '
Date of birth: {[Date.parseDate(values.date_of_birth, "Y-m-d").format("F, d")]}',
                    '</tpl>',
                    '<tpl if="home_address">',
                        '

Lives in: {home_address}',
                    '</tpl>',
                    '<tpl if="carpooling">',
                        '
 Available for carpooling!',
                    '</tpl>',

                    /*********************************************
                     * START Group description
                     *********************************************/
                    '<tpl if="groups_description">',
                        '

{[window.config.defaultgroupname]}',
                        '
',
                        '',
                            '
',
                            '<tpl for="groups">',
                                '
',
                                    '{[values.description_en ? (values.description_en + \" - \") : (values.description_it ? (values.description_it + \" - \") : \"\")]}{name}',
                                '
',
                            '</tpl>',
                            '
',
                        '',
                    '</tpl>',
                    /*********************************************
                     * END Group description
                     *********************************************/

                    /*********************************************
                     * START Tag cloud
                     *********************************************/

                    // Currently not working!
                    //'{[this.tagCloud(values.tags)]}',

                    /*********************************************
                     * END Tag cloud
                     *********************************************/

                    /**********************************************
                     * START Social Networking
                     *********************************************/
                    '<tpl if="(linkedin) || (twitter) || (facebook)">', // if one of the social network's field is present...
                        '
Social networking on...
',
                        '',
                            '
',
                                '<tpl if="linkedin">',
                                    '
',
                                        'Linkedin',
                                    '
',
                                '</tpl>',
                                '<tpl if="twitter">',
                                    '
',
                                        'Twitter',
                                    '
',
                                '</tpl>',
                                '<tpl if="facebook">',
                                    '
',
                                        'Facebook',
                                    '
',
                                '</tpl>',
                            '
',
                        '',
                    '</tpl>',
                    /**********************************************
                     * END Social Networking
                     *********************************************/
                    '<tpl if="mod_description">',
                        '
About {name}: {this.mod_description}',
                    '</tpl>',
                    '
'
                    ,{
                        reqid: reqid
                        ,mod_description: mod_description
                        ,sourceGroupWindow: Ext.util.Format.htmlEncode(
                            '{\"source\": \"user profile\", \"user_id\": \"'+westPanel.showedUser.id+'\"}'
                        )
                        ,sourceSendMail: Ext.util.Format.htmlEncode(
                            '{\"source\": \"user profile\", \"user_id\": \"'+westPanel.showedUser.id+'\"}'
                        )
                        ,sourceSuggestAs: Ext.util.Format.htmlEncode(
                            '{\"source\": \"suggest as champion\", \"user_id\": \"'+westPanel.showedUser.id+'\"}'
                        )
                        ,getPronoun: function(gender) {
                            //gender = 2 => female
                            if(gender == '1') { //male
                                return 'his';
                            } else {
                                return 'her';
                            }
                        }
                        ,tagCloud: function(tags){

                            if(!tags)
                                return '';

                            var min_font_size = 12;
                            var max_font_size = 22;

                            var max_count;
                            var min_count;

                            var count;
                            var font_size;
                            var tag_cloud = '

Tag cloud
';

                            // Defining minimum and maximum count value
                            for(var i in tags){
                                if((tags[i].length < min_count) || (min_count == null))
                                    min_count = tags[i].length;
                                else if((tags[i].length > max_count) || (max_count == null))
                                    max_count = tags[i].length;
                            }

                            var spread = max_count - min_count;
                            if(spread == 0)
                                spread = 1;

                            for(var key in tags){

                                count = tags[key].length;
                                font_size = min_font_size + (count - min_count) * ((max_font_size - min_font_size) / spread);

                                tag_cloud += '
'+key+'<wbr>
';

                            }

                            return tag_cloud + '

';
                        }
                    }
                    );
                    tpl.overwrite(Ext.get('user_text'), jsondata.user);

                    if(jsondata.user.login)
                        findChatStatus(reqid, jsondata.user.login);
                }
           });
    }

});
<commit_msg>user profile refactored: socialnetworking sites grouped, login removed<commit_after>/**
* This file is part of taolin project (http://taolin.fbk.eu)
* Copyright (C) 2008, 2009 FBK Foundation, (http://www.fbk.eu)
* Authors: SoNet Group (see AUTHORS.txt)
*
* Taolin is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation version 3 of the License.
*
* Taolin is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Taolin. If not, see <http://www.gnu.org/licenses/>.
*
*/

westPanel = new Ext.Panel({
    region:'west',
    id:'west-panel',
    title:'Social Bar',
    split:true,
    width: 220,
    minSize: 220,
    maxSize: 400,
    /* This panel should not be closed, only collapsed */
    tools: toolsnotclose,
    hideCollapseTool:true,
    collapsible: true,
    margins:'5 0 5 5',
    cmargins:'5 5 5 5',
    layout:'accordion',
    layoutConfig:{
        hideCollapseTool:true,
        titleCollapse:true,
        activeOnTop: false
    },
    items: [{
        xtype:'timeline'
        /* Be careful if you want to change this id. It is used several times
         * to access to the timeline and to its methods (in Timeline.js or in
         * reloadTimeline() into functions.js)
         */
        ,id: 'timeline'
    },{
        xtype:'userprofile'
        ,id: 'user_profile'
    },{
        title:'Edit your profile',
        border:false,
        autoScroll:true,
        iconCls:'settings',
        frame:true,
        id:'settings',
        layout: 'fit',
        collapsible:true,
        hideCollapseTool:true,
        tools: toolsnotclose,
        listeners: {
            /* When this accordion panel collapse it expands automatically
             * the other panel
             *
             * not in use
             */
            /*collapse: expandUserPanel,*/
            render: function(t){
                t.add(new Ext.ux.fbk.sonet.Settings());
            }
        }
    }]

    /**
      * @param {String} login requested user's login
      */
    ,showPublik: function(login){
        var tab = Ext.getCmp('wp-publik-tab');

        tab.store.load({params: {login: login}});
    }

    /**
      * @param {Integer} id requested user's id
      *
      */
    ,showPhotos: function(id){
        var tab = Ext.getCmp('wp-photos-tab');

        tab.store.load({params: {id: id}});
    }

    /** showUser function
     * show selected user's profile
     * @param {Integer} reqid requested user's id
     * @param {bool} hidePanel if true the user profile panel has not to be shown
     * @param {String} source for logging porpouse, it records the place where the requests started
     */
    ,showUser: function(reqid, hidePanel, logparams){

        if (!reqid) reqid = '';
        if (!hidePanel) {
            hidePanel = false;
        }

        Ext.Ajax.request({
            url : 'users/getinfo/'+reqid,
            method: 'GET',
            params: {src: logparams},
            success: function ( result, request ) {
                /*
                 * Whenever this function shows user info it shall expand both
                 * western panel and accordion panel containing 'user_image' div
                 */
                westPanel.expand();

                // Show user info (aka first tab of tabpanel)
                Ext.getCmp('user_profile').items.items[1].setActiveTab(0);

                if(!hidePanel) expandUserPanel();
                var jsondata = Ext.util.JSON.decode(result.responseText);
                westPanel.showedUser = jsondata.user;
                var user_text = '';

                if(reqid==='') { //this call always gives access to this user data
                    Ext.get("logged_as_username").update(
                        ''+jsondata.user.login+''
                    );
                    window.thisId = jsondata.user.id;
                    window.thisLogin = jsondata.user.login;
                    if(jsondata.user.email)
                        window.thisEmail = jsondata.user.email;
                }

                westPanel.showPublik(jsondata.user.login);
                westPanel.showPhotos(jsondata.user.id);

                //save in a retrievable place if this photo is user's photo
                //and then show tools
                westPanel.showTools = ((!reqid) || (reqid == window.thisId));
                showText(westPanel.showTools, 'user-profile-edit-div'); // Shows tools and Edit box only if the showed profile belongs to the user

                if (('photo' in jsondata.user) && (jsondata.user.photo)){
                    Ext.get("user_photo").dom.src = jsondata.user.photo;
                } else {
                    Ext.get("user_photo").dom.src = 'img/nophoto.png';
                }

                var mod_description = jsondata.user.mod_description;
                // call the methods urlize and smilize only if the object is not null
                if(mod_description) {
                    mod_description=mod_description.urlize().smilize();
                    //replaces \n with
 for visualization in html
                    mod_description=Ext.util.Format.htmlDecode(mod_description.replace(/(\n)/g,'
'));
                }

                var tpl = new Ext.XTemplate(
                    '
',
                    '
{name} {surname}',
                    /* if own profile, prompt a shortcut to edit the profile */
                    '<tpl if="((this.reqid === \'\') || (this.reqid == window.thisId))">',
                        'Edit',
                    '</tpl>',
                    '
',
                    '',
                    /* check if the user is "chattable" */
                    '<tpl if="((this.reqid !== \'\') && (login) && (jabber.u_n !== login) && (active === \'1\'))">',
                        '
Chat with {name} {surname}
',
                    '</tpl>',
                    /* if s/he is not a champion, suggest as a champion! */
                    '<tpl if="((this.reqid !== \'\') && (active !== \'1\'))">',
                        '
{name} is not a champion. You can suggest {name} as a new {[window.config.appname]} champion!

',
                    '</tpl>',
                    '<tpl if="email">',
                        'E-mail:  {email}',
                    '</tpl>',
                    '<tpl if="((phone) && (phone != \'0\'))">',
                        '
Phone: {phone}',
                    '</tpl>',
                    '<tpl if="((phone2) && (phone2 != \'0\'))">',
                        '
Phone 2: {phone2}',
                    '</tpl>',
                    '<tpl if="((personal_page) && (personal_page != \'null\'))">',
                        '
Home page: {[values.personal_page.substr(0,7)==="http://" ? values.personal_page.substr(7) : values.personal_page]}',
                    '</tpl>',
                    '<tpl if="building_id">',
                        '
Workplace: where\'s {[this.getPronoun(values.gender)]} office?',
                    '</tpl>',
                    '<tpl if="date_of_birth">',
                        '
Date of birth: {[Date.parseDate(values.date_of_birth, "Y-m-d").format("F, d")]}',
                    '</tpl>',
                    '<tpl if="home_address">',
                        '

Lives in: {home_address}',
                    '</tpl>',
                    '<tpl if="carpooling">',
                        '
 Available for carpooling!',
                    '</tpl>',

                    /*********************************************
                     * START Group description
                     *********************************************/
                    '<tpl if="groups_description">',
                        '

{[window.config.defaultgroupname]}',
                        '
',
                        '',
                            '
',
                            '<tpl for="groups">',
                                '
',
                                    '{[values.description_en ? (values.description_en + \" - \") : (values.description_it ? (values.description_it + \" - \") : \"\")]}{name}',
                                '
',
                            '</tpl>',
                            '
',
                        '',
                    '</tpl>',
                    /*********************************************
                     * END Group description
                     *********************************************/

                    /**********************************************
                     * START Social Networking
                     *********************************************/
                    '<tpl if="(linkedin) || (twitter) || (facebook)">', // if one of the social network's field is present...
                        '
Social networking on:
',
                        '',
                            '<tpl if="linkedin">',
                                '',
                            '</tpl>',
                            '<tpl if="twitter">',
                                '',
                            '</tpl>',
                            '<tpl if="facebook">',
                                '',
                            '</tpl>',
                        '
',
                    '</tpl>',
                    /**********************************************
                     * END Social Networking
                     *********************************************/
                    '<tpl if="mod_description">',
                        '
About {name}: {this.mod_description}',
                    '</tpl>',
                    '
'
                    ,{
                        reqid: reqid
                        ,mod_description: mod_description
                        ,sourceGroupWindow: Ext.util.Format.htmlEncode(
                            '{\"source\": \"user profile\", \"user_id\": \"'+westPanel.showedUser.id+'\"}'
                        )
                        ,sourceSendMail: Ext.util.Format.htmlEncode(
                            '{\"source\": \"user profile\", \"user_id\": \"'+westPanel.showedUser.id+'\"}'
                        )
                        ,sourceSuggestAs: Ext.util.Format.htmlEncode(
                            '{\"source\": \"suggest as champion\", \"user_id\": \"'+westPanel.showedUser.id+'\"}'
                        )
                        ,getPronoun: function(gender) {
                            //gender = 2 => female
                            if(gender == '1') { //male
                                return 'his';
                            } else {
                                return 'her';
                            }
                        }
                        ,tagCloud: function(tags){

                            if(!tags)
                                return '';

                            var min_font_size = 12;
                            var max_font_size = 22;

                            var max_count;
                            var min_count;

                            var count;
                            var font_size;
                            var tag_cloud = '

Tag cloud
';

                            // Defining minimum and maximum count value
                            for(var i in tags){
                                if((tags[i].length < min_count) || (min_count == null))
                                    min_count = tags[i].length;
                                else if((tags[i].length > max_count) || (max_count == null))
                                    max_count = tags[i].length;
                            }

                            var spread = max_count - min_count;
                            if(spread == 0)
                                spread = 1;

                            for(var key in tags){

                                count = tags[key].length;
                                font_size = min_font_size + (count - min_count) * ((max_font_size - min_font_size) / spread);

                                tag_cloud += '
'+key+'<wbr>
';

                            }

                            return tag_cloud + '

';
                        }
                    }
                    );
                    tpl.overwrite(Ext.get('user_text'), jsondata.user);

                    if(jsondata.user.login)
                        findChatStatus(reqid, jsondata.user.login);
                }
           });
    }

});
<|endoftext|>


<commit_before>define(['Ti/_/lang'], function(lang) {
	return lang.setObject('Ti.Tizen.Alarm', {

		constants: {
			PERIOD_MINUTE: 60, //unsigned long long
			PERIOD_HOUR: 3600, //unsigned long long
			PERIOD_DAY: 86400, //unsigned long long
			PERIOD_WEEK: 604800, //unsigned long long
		},

		add: function(alarm /*Alarm*/, applicationId /*ApplicationId*/, appControl /*ApplicationControl*/) {
			return tizen.alarm.add(alarm._obj, applicationId, appControl ? appControl._obj : appControl);
		},

		remove: function(id /*AlarmId*/) {
			return tizen.alarm.remove(id);
		},

		removeAll: function() {
			return tizen.alarm.removeAll();
		},

		get: function(id /*AlarmId*/) {
			return this._wrap(tizen.alarm.get(id));
		},

		getAll: function() {
			var objects = tizen.alarm.getAll(),
				i = 0,
				objectsCount = objects.length,
				result = [];
			for(; i < objectsCount; i++) {
				result.push(this._wrap(objects[i]));
			}
			return result;
		},

		_wrap: function(object) {
			var result;
			if (object.toString() === '[object AlarmRelative]') {
				result = this.createAlarmRelative(object);
			}
			if (object.toString() === '[object AlarmAbsolute]') {
				result = this.createAlarmAbsolute(object);
			}
			return result;
		},

		createAlarmRelative: function(args){
			return new (require('Ti/Tizen/Alarm/AlarmRelative'))(args);
		},

		createAlarmAbsolute: function(args){
			return new (require('Ti/Tizen/Alarm/AlarmAbsolute'))(args);
		},
	});
});<commit_msg>Changed creators<commit_after>define(['Ti/_/lang', 'Ti/Tizen/Alarm/AlarmRelative', 'Ti/Tizen/Alarm/AlarmAbsolute'], function(lang, AlarmRelative, AlarmAbsolute) {
	return lang.setObject('Ti.Tizen.Alarm', {

		constants: {
			PERIOD_MINUTE: 60, //unsigned long long
			PERIOD_HOUR: 3600, //unsigned long long
			PERIOD_DAY: 86400, //unsigned long long
			PERIOD_WEEK: 604800, //unsigned long long
		},

		add: function(alarm /*Alarm*/, applicationId /*ApplicationId*/, appControl /*ApplicationControl*/) {
			return tizen.alarm.add(alarm._obj, applicationId, appControl ? appControl._obj : appControl);
		},

		remove: function(id /*AlarmId*/) {
			return tizen.alarm.remove(id);
		},

		removeAll: function() {
			return tizen.alarm.removeAll();
		},

		get: function(id /*AlarmId*/) {
			return this._wrap(tizen.alarm.get(id));
		},

		getAll: function() {
			var objects = tizen.alarm.getAll(),
				i = 0,
				objectsCount = objects.length,
				result = [];
			for(; i < objectsCount; i++) {
				result.push(this._wrap(objects[i]));
			}
			return result;
		},

		_wrap: function(object) {
			var result;
			if (object.toString() === '[object AlarmRelative]') {
				result = this.createAlarmRelative(object);
			}
			if (object.toString() === '[object AlarmAbsolute]') {
				result = this.createAlarmAbsolute(object);
			}
			return result;
		},

		createAlarmRelative: function(args){
			return new AlarmRelative(args);
		},

		createAlarmAbsolute: function(args){
			return new AlarmAbsolute(args);
		},
	});
});<|endoftext|>


<commit_before>var mapArea = document.getElementById("map");
var isGeo = true; //端末が現在地取得に対応しているか
var map;
var lat = 35.709984, lng = 139.810703;
var markers = [];
if(!navigator.geolocation) {
  alert("あなたの端末では、現在地の取得が出来ません。");
  isGeo = false;
}

/**
* 現在地が取得された時
*/
function successFunc(position) {
  lat = position.coords.latitude;
  lng = position.coords.longitude;
  initMap();
};

/**
* 現在地の取得に失敗した時
*/
function errorFunc() {
  alert("現在地の取得に失敗...");
}

/**
* 現在地を取得する
*/
function getLocation() {
  if(!isGeo) return;
  navigator.geolocation.getCurrentPosition(successFunc, errorFunc);
}

/**
* データ取得
*/
function getData() {
  return $.ajax({
    url: "/sumari/",
    type: "get"
  });
}

/**
* マーカー作成
*/
function makeMarker(title, position, message) {
  return new google.maps.Marker({
    map: map,
    title: title,
    position: position,
    message: message,
    animation: google.maps.Animation.DROP
  });
}

/**
* マーカーを取得する
*/
function getMarker() {
  getData().then(function(data) {
    for(var i = 0; i < data.length; i++) {
      var name = data[i]["name"];
      var lat = data[i]["position"]["lat"];
      var lng = data[i]["position"]["lng"];
      var message = data[i]["message"];
      markers[i] = makeMarker(name, {lat: lat,lng: lng}, message);
      markers[i].addListener('click', function() {
        infoWindow = new google.maps.InfoWindow({
          content: "" + this.title + "

" + this.message + "
"
        });
        infoWindow.open(map, this);
      });
    }
  });
};

/**
* マーカーを全て削除する
*/
function removeMarkers() {
  for(var i = 0; i < markers.length; i++) {
    markers[i].setMap(null);
  }
  markers.length = 0;
}

/**
* 現在地を反映する
*/
function initMap() {
  var opts = {
    zoom: 15,
    center: new google.maps.LatLng(lat, lng),
    mapTypeControl: false,
    streetViewControl: false,
    zoomControl: false
  };
  map = new google.maps.Map(mapArea, opts);
  $.getJSON("/static/smap/mapStyles.json", function(mapStyles) {
    map.setOptions({styles:mapStyles});
  });
  var location = new google.maps.Circle({
    strokeColor: '#1e90ff',
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: '#1e90ff',
    fillOpacity: 0.35,
    map: map,
    center: {lat:lat, lng:lng},
    radius: 100
  })

  getMarker();
}
<commit_msg>Add setInterval<commit_after>var mapArea = document.getElementById("map");
var isGeo = true; //端末が現在地取得に対応しているか
var map;
var lat = 35.709984, lng = 139.810703;
var markers = [];
if(!navigator.geolocation) {
  alert("あなたの端末では、現在地の取得が出来ません。");
  isGeo = false;
}

/**
* 現在地が取得された時
*/
function successFunc(position) {
  lat = position.coords.latitude;
  lng = position.coords.longitude;
  initMap();
};

/**
* 現在地の取得に失敗した時
*/
function errorFunc() {
  alert("現在地の取得に失敗...");
}

/**
* 現在地を取得する
*/
function getLocation() {
  if(!isGeo) return;
  navigator.geolocation.getCurrentPosition(successFunc, errorFunc);
}

/**
* データ取得
*/
function getData() {
  return $.ajax({
    url: "/sumari/",
    type: "get"
  });
}

/**
* マーカー作成
*/
function makeMarker(title, position, message) {
  return new google.maps.Marker({
    map: map,
    title: title,
    position: position,
    message: message,
    animation: google.maps.Animation.DROP
  });
}

/**
* マーカーを取得する
*/
function getMarker() {
  getData().then(function(data) {
    for(var i = 0; i < data.length; i++) {
      var name = data[i]["name"];
      var lat = data[i]["position"]["lat"];
      var lng = data[i]["position"]["lng"];
      var message = data[i]["message"];
      markers[i] = makeMarker(name, {lat: lat,lng: lng}, message);
      markers[i].addListener('click', function() {
        infoWindow = new google.maps.InfoWindow({
          content: "" + this.title + "

" + this.message + "
"
        });
        infoWindow.open(map, this);
      });
    }
  });
};

/**
* マーカーを全て削除する
*/
function removeMarkers() {
  for(var i = 0; i < markers.length; i++) {
    markers[i].setMap(null);
  }
  markers.length = 0;
}

/**
* 現在地を反映する
*/
function initMap() {
  var opts = {
    zoom: 15,
    center: new google.maps.LatLng(lat, lng),
    mapTypeControl: false,
    streetViewControl: false,
    zoomControl: false
  };
  map = new google.maps.Map(mapArea, opts);
  $.getJSON("/static/smap/mapStyles.json", function(mapStyles) {
    map.setOptions({styles:mapStyles});
  });
  var location = new google.maps.Circle({
    strokeColor: '#1e90ff',
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: '#1e90ff',
    fillOpacity: 0.35,
    map: map,
    center: {lat:lat, lng:lng},
    radius: 100
  });

  setInterval(getLocation, 1000);

  getMarker();
}
<|endoftext|>


<commit_before>Router.map(function () {
	this.route('calendar', {
		path: 'calendar',
		template: 'calendar',
		data: function() { return this.params; },
		onAfterAction: function() {
			document.title = webpagename + 'Calendar';
		}
	});
});

var updateUrl = function(event, instance) {
	var filterParams = instance.filter.toParams();
	delete filterParams['region']; // HACK region is kept in the session (for bad reasons)
	var queryString = UrlTools.paramsToQueryString(filterParams);

	var options = {};
	if (queryString.length) {
		options.query = queryString;
	}

	Router.go('calendar', {}, options);
	event.preventDefault();
};

Template.calendar.helpers({
	weekday: function(day) {
		return day.format('dddd Do MMMM');
	},
	past: function() {
		return moment().isAfter(this.end);
	},
	days: function() {
		var start = Template.instance().filter.get('start');
		var i = 0;
		var days = [];
		for (; i < 7; i++) {
			days.push({
				start: moment(start).add(i, 'days'),
				end: moment(start).add(i+1, 'days')
			});
		}
		return days;
	},
	filter: function() {
		return Template.instance().filter;
	},
	startDate: function() {
		Session.get('timeLocale');
		return moment(Template.instance().filter.get('start'));
	}
});

Template.calendarDay.helpers({
	hasEvents: function() {
		var filterQuery = this.filter.toQuery();
		filterQuery.period = [this.day.start.toDate(), this.day.end.toDate()];

		return eventsFind(filterQuery).count() > 0;
	},
	events: function() {
		var filterQuery = this.filter.toQuery();
		filterQuery.period = [this.day.start.toDate(), this.day.end.toDate()];

		return eventsFind(filterQuery);
	},
	calendarDay: function(day) {
		Session.get('timeLocale');
		return moment(day.toDate()).format('dddd Do MMMM');
	}
});

Template.calendar.onCreated(function() {
	var instance = this;

	var filter = Filtering(EventPredicates);
	instance.filter = filter;

	// Read URL state
	instance.autorun(function() {
		var data = Template.currentData();
		var query = data.query || {};

		filter
			.clear()
			.add('start', moment().startOf('week'))
			.add('region', Session.get('region'))
			.read(query)
			.done();
	});

	// Keep old subscriptions around until the new ones are ready
	var eventSub = false;
	var oldSubs = [];
	var stopOldSubs = function() {
		if (eventSub.ready()) {
			_.map(oldSubs, function(sub) { sub.stop(); });
			oldSubs = [];
		}
	};

	instance.autorun(function() {
		var filterQuery = filter.toQuery();

		var start = filter.get('start').toDate();
		var limit = filter.get('start').add(1, 'week').toDate();

		filterQuery.period = [start, limit];
		if (eventSub) oldSubs.push(eventSub);
		eventSub = instance.subscribe('eventsFind', filterQuery, stopOldSubs);

	});
});

Template.calendar.rendered = function() {
	var currentPath = Router.current().route.path(this);
	$('a[href!="' + currentPath + '"].nav_link').removeClass('active');
	$('a[href="' + currentPath + '"].nav_link').addClass('active');
};

Template.calendar_event.rendered = function() {
	this.$('.ellipsis').dotdotdot({});
};

var mvDateHandler = function(amount, unit) {
	return function(event, instance) {
		var start = instance.filter.get('start');
		if (amount < 0) {
			start.add(amount, unit).startOf('week');
		} else {
			start.add(amount, unit).add(1, 'week').startOf('week');
		}
		instance.filter.add('start', start).done();
		updateUrl(event, instance);
		return false;
	};
};

Template.calendar.events({
	'click .nextWeek': mvDateHandler(1, 'week'),
	'click .prevWeek': mvDateHandler(-1, 'week'),
	'click .nextMonth': mvDateHandler(1, 'month'),
	'click .prevMonth': mvDateHandler(-1, 'month'),
	'click .nextYear': mvDateHandler(1, 'year'),
	'click .prevYear': mvDateHandler(-1, 'year'),
});
<commit_msg>bugfix: calendar: don't add a week-Corrention when switching back just one week<commit_after>Router.map(function () {
	this.route('calendar', {
		path: 'calendar',
		template: 'calendar',
		data: function() { return this.params; },
		onAfterAction: function() {
			document.title = webpagename + 'Calendar';
		}
	});
});

var updateUrl = function(event, instance) {
	var filterParams = instance.filter.toParams();
	delete filterParams['region']; // HACK region is kept in the session (for bad reasons)
	var queryString = UrlTools.paramsToQueryString(filterParams);

	var options = {};
	if (queryString.length) {
		options.query = queryString;
	}

	Router.go('calendar', {}, options);
	event.preventDefault();
};

Template.calendar.helpers({
	weekday: function(day) {
		return day.format('dddd Do MMMM');
	},
	past: function() {
		return moment().isAfter(this.end);
	},
	days: function() {
		var start = Template.instance().filter.get('start');
		var i = 0;
		var days = [];
		for (; i < 7; i++) {
			days.push({
				start: moment(start).add(i, 'days'),
				end: moment(start).add(i+1, 'days')
			});
		}
		return days;
	},
	filter: function() {
		return Template.instance().filter;
	},
	startDate: function() {
		Session.get('timeLocale');
		return moment(Template.instance().filter.get('start'));
	}
});

Template.calendarDay.helpers({
	hasEvents: function() {
		var filterQuery = this.filter.toQuery();
		filterQuery.period = [this.day.start.toDate(), this.day.end.toDate()];

		return eventsFind(filterQuery).count() > 0;
	},
	events: function() {
		var filterQuery = this.filter.toQuery();
		filterQuery.period = [this.day.start.toDate(), this.day.end.toDate()];

		return eventsFind(filterQuery);
	},
	calendarDay: function(day) {
		Session.get('timeLocale');
		return moment(day.toDate()).format('dddd Do MMMM');
	}
});

Template.calendar.onCreated(function() {
	var instance = this;

	var filter = Filtering(EventPredicates);
	instance.filter = filter;

	// Read URL state
	instance.autorun(function() {
		var data = Template.currentData();
		var query = data.query || {};

		filter
			.clear()
			.add('start', moment().startOf('week'))
			.add('region', Session.get('region'))
			.read(query)
			.done();
	});

	// Keep old subscriptions around until the new ones are ready
	var eventSub = false;
	var oldSubs = [];
	var stopOldSubs = function() {
		if (eventSub.ready()) {
			_.map(oldSubs, function(sub) { sub.stop(); });
			oldSubs = [];
		}
	};

	instance.autorun(function() {
		var filterQuery = filter.toQuery();

		var start = filter.get('start').toDate();
		var limit = filter.get('start').add(1, 'week').toDate();

		filterQuery.period = [start, limit];
		if (eventSub) oldSubs.push(eventSub);
		eventSub = instance.subscribe('eventsFind', filterQuery, stopOldSubs);

	});
});

Template.calendar.rendered = function() {
	var currentPath = Router.current().route.path(this);
	$('a[href!="' + currentPath + '"].nav_link').removeClass('active');
	$('a[href="' + currentPath + '"].nav_link').addClass('active');
};

Template.calendar_event.rendered = function() {
	this.$('.ellipsis').dotdotdot({});
};

var mvDateHandler = function(amount, unit) {
	return function(event, instance) {
		var start = instance.filter.get('start');
		var weekCorrection = unit == "week"? 0 : 1;
		if (amount < 0) {
			start.add(amount, unit).startOf('week');
		} else {
			start.add(amount, unit).add(weekCorrection, 'week').startOf('week');
		}
		instance.filter.add('start', start).done();
		updateUrl(event, instance);
		return false;
	};
};

Template.calendar.events({
	'click .nextWeek': mvDateHandler(1, 'week'),
	'click .prevWeek': mvDateHandler(-1, 'week'),
	'click .nextMonth': mvDateHandler(1, 'month'),
	'click .prevMonth': mvDateHandler(-1, 'month'),
	'click .nextYear': mvDateHandler(1, 'year'),
	'click .prevYear': mvDateHandler(-1, 'year'),
});
<|endoftext|>