<commit_before>/*
 * Copyright 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
 * Please see distribution for license.
 */
$.register_module({
    name: 'og.analytics.form',
    dependencies: ['og.common.util.ui.AutoCombo', 'og.views.common.layout'],
    obj: function () {
        return function (selector) {
            var FormCombo = function (selector, module, data) {
                var $popdiv, menu = this, $title;
                $.when(og.api.text({module: module})).then(function (template) {
                    var html = $((Handlebars.compile(template))(data));
                    $title = $(selector).html(html).find('.og-option-title').on('click', function (event) {
                        event.stopPropagation();
                        menu.state === 'open' ? menu.close() : menu.open().focus();
                    });
                    menu.state = 'closed';
                    menu.focus = function () {return $popdiv.find('select').first().focus() && menu};
                    menu.open = function () {
                        $popdiv = $(selector + ' .OG-analytics-form-menu').show()
                            .blurkill(menu.close).trigger('open', $title);
                        $title.addClass('og-active');
                        menu.state = 'open';
                        return menu;
                    };
                    menu.close = function () {
                        if ($popdiv) $popdiv.hide();
                        $title.removeClass('og-active');
                        menu.state = 'closed';
                    };
                });
            };
            var Status = function (selector) {
                var status = this, interval, init = false;
                $(selector + ' button').on('click', function () {
                    if (!status.status || status.status === 'paused') return status.play();
                    if (status.status === 'playing') return status.pause();
                });
                status.pause = function () {
                    $(selector + ' em').html('paused').removeClass('live').addClass('paused');
                    $(selector + ' button').removeClass('og-icon-play').addClass('og-icon-pause');
                    status.message('');
                    clearInterval(interval);
                    status.status = 'paused';
                };
                status.play = function () {
                    if (!init) init = !!$(selector + ' button').removeClass('og-disabled');
                    $(selector + ' em').html('live').removeClass('paused').addClass('live');
                    $(selector + ' button').removeClass('og-icon-pause').addClass('og-icon-play');
                    status.message('starting...');
                    interval = setInterval(function () {
                        status.message('updated ' + (Math.random() + 1).toFixed(2) + ' seconds ago');
                    }, 1000);
                    status.status = 'playing';
                };
                status.message = function (message) {$(selector + ' .og-message').html(message);};
                status.status = null;
                return status;
            };
            $.when(
                og.api.text({module: 'og.analytics.form_tash'}),
                og.api.rest.viewdefinitions.get({}),
                og.api.rest.aggregators.get()
            ).then(function (template, search, aggregators) {
                var response = { // dummy response
                    view: search.data,
                    aggregation: {
                        aggregators: aggregators.data,
                        row: [
                            {num: 1, label: 'Aggregated by', by: 'Long / Short'},
                            {num: 2, label: 'Then by', by: 'Asset Class', last: true}
                        ]
                    },
                    datasources: {
                        type: ['Live', 'Snapsot', 'Historical', 'Data Type'],
                        live: ['Bloomberg', 'Reuters'],
                        snapshot: ['Alan', 'Alan 2'],
                        historical: ['01 June 2012', '02 June 2012', '03 June 2012'],
                        datatype: ['type 1', 'type 2'],
                        row: [
                            {num: 1, type: 'Live', value: 'Bloomberg'},
                            {num: 2, type: 'Snapshot', value: 'Alan'},
                            {num: 3, type: 'Historical', value: '02 June 2012'},
                            {num: 4, type: 'Data Type', value: 'type 2', last: true}
                        ]
                    }
                };
                $(selector).html(template)
                    /**
                     * Custom tab event, only triggers between top level menu items. e.g. a tab event will trigger
                     * when tab entering or tab leaving the evented element
                     */
                    .on('keydown', 'input, select, button', function (event) {
                        if (event.keyCode !== 9) return;
                        var $aggr = $(selector + ' .og-aggregation').find('input, select, button'),
                            $data = $(selector + ' .og-datasources').find('input, select, button'),
                            $self = $(this), shift_key = event.shiftKey,
                            trigger = function (menu) {$self.trigger('tab', menu);},
                            active_pos = function (elms, pos) {return $self.is(elms[pos]())},
                            view = $self.closest('.og-view').length,
                            aggregation = $self.closest('.og-aggregation').length,
                            datasources = $self.closest('.og-datasources').length,
                            load = $self.hasClass('og-load');
                        if (view && shift_key) return;
                        if (view && !shift_key) return trigger('aggregation');
                        if (aggregation && active_pos($aggr, 'last') && !shift_key) return trigger('datasources');
                        if (datasources && active_pos($data, 'first') && shift_key) return trigger('aggregation');
                        if (datasources && active_pos($data, 'last') && !shift_key) return trigger('load');
                        if (load && shift_key) return trigger('datasources');
                    })
                    .on('tab', function (event, type) {
                        switch (type) {
                            case 'aggregation': aggregation_menu.open(); break;
                            case 'datasources': datasources_menu.open(); break;
                            case 'load': aggregation_menu.close(); datasources_menu.close(); break;
                        }
                    })
                    /**
                     * The "open" event fires everytime a menu item is opened
                     */
                    .on('open', function (event, elm) {
                        if (!aggregation_menu || !datasources_menu) return;
                        if ($(elm).closest('.og-view').length) datasources_menu.close(), aggregation_menu.close();
                        if ($(elm).closest('.og-aggregation').length) datasources_menu.close();
                        if ($(elm).closest('.og-datasources').length) aggregation_menu.close();
                    })
                    .on('click', '.og-menu-aggregation button', function () {
                        var val = $(this).text();
                        if (val === 'OK') $(selector).trigger('tab', 'datasources'), datasources_menu.focus();
                        if (val === 'Cancel') aggregation_menu.close(), auto_combo_menu.select();
                    })
                    .on('click', '.og-menu-datasources button', function () {
                        var val = $(this).text();
                        if (val === 'OK') $(selector).trigger('tab', 'load'), $(selector + ' .og-load').focus();
                        if (val === 'Cancel') datasources_menu.close(), auto_combo_menu.select();
                    });
                var auto_combo_menu = new og.common.util.ui.AutoCombo(
                        '.OG-analytics-form .og-view', 'search...', response.view)
                    .on('input autocompletechange autocompleteselect', function (event, ui) {
                        var $load = $(selector + ' .og-load');
                        if ((ui && ui.item && ui.item.value || $(this).val()) !== '') {
                            $load.removeClass('og-disabled').on('click', function () {
                                status.play();
                            });
                        }
                        else $load.addClass('og-disabled').off('click');
                    });
                var aggregation_menu = new FormCombo(
                    selector + ' .og-aggregation', 'og.analytics.form_aggregation_tash', response.aggregation
                );
                var datasources_menu = new FormCombo(
                    selector + ' .og-datasources', 'og.analytics.form_datasources_tash', response.datasources
                );
                var status = new Status(selector + ' .og-status');
                og.views.common.layout.main.allowOverflow('north');
            });
        }
    }
});<commit_msg>load view from autocombo (temp)<commit_after>/*
 * Copyright 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
 * Please see distribution for license.
 */
$.register_module({
    name: 'og.analytics.form',
    dependencies: ['og.common.util.ui.AutoCombo', 'og.views.common.layout'],
    obj: function () {
        return function (selector) {
            var FormCombo = function (selector, module, data) {
                var $popdiv, menu = this, $title;
                $.when(og.api.text({module: module})).then(function (template) {
                    var html = $((Handlebars.compile(template))(data));
                    $title = $(selector).html(html).find('.og-option-title').on('click', function (event) {
                        event.stopPropagation();
                        menu.state === 'open' ? menu.close() : menu.open().focus();
                    });
                    menu.state = 'closed';
                    menu.focus = function () {return $popdiv.find('select').first().focus() && menu};
                    menu.open = function () {
                        $popdiv = $(selector + ' .OG-analytics-form-menu').show()
                            .blurkill(menu.close).trigger('open', $title);
                        $title.addClass('og-active');
                        menu.state = 'open';
                        return menu;
                    };
                    menu.close = function () {
                        if ($popdiv) $popdiv.hide();
                        $title.removeClass('og-active');
                        menu.state = 'closed';
                    };
                });
            };
            var Status = function (selector) {
                var status = this, interval, init = false;
                $(selector + ' button').on('click', function () {
                    if (!status.status || status.status === 'paused') return status.play();
                    if (status.status === 'playing') return status.pause();
                });
                status.pause = function () {
                    $(selector + ' em').html('paused').removeClass('live').addClass('paused');
                    $(selector + ' button').removeClass('og-icon-play').addClass('og-icon-pause');
                    status.message('');
                    clearInterval(interval);
                    status.status = 'paused';
                };
                status.play = function () {
                    if (!init) init = !!$(selector + ' button').removeClass('og-disabled');
                    $(selector + ' em').html('live').removeClass('paused').addClass('live');
                    $(selector + ' button').removeClass('og-icon-pause').addClass('og-icon-play');
                    status.message('starting...');
                    interval = setInterval(function () {
                        status.message('updated ' + (Math.random() + 1).toFixed(2) + ' seconds ago');
                    }, 1000);
                    status.status = 'playing';
                };
                status.message = function (message) {$(selector + ' .og-message').html(message);};
                status.status = null;
                return status;
            };
            $.when(
                og.api.text({module: 'og.analytics.form_tash'}),
                og.api.rest.viewdefinitions.get({}),
                og.api.rest.aggregators.get()
            ).then(function (template, search, aggregators) {
                var response = { // dummy response
                    view: search.data,
                    aggregation: {
                        aggregators: aggregators.data,
                        row: [
                            {num: 1, label: 'Aggregated by', by: 'Long / Short'},
                            {num: 2, label: 'Then by', by: 'Asset Class', last: true}
                        ]
                    },
                    datasources: {
                        type: ['Live', 'Snapsot', 'Historical', 'Data Type'],
                        live: ['Bloomberg', 'Reuters'],
                        snapshot: ['Alan', 'Alan 2'],
                        historical: ['01 June 2012', '02 June 2012', '03 June 2012'],
                        datatype: ['type 1', 'type 2'],
                        row: [
                            {num: 1, type: 'Live', value: 'Bloomberg'},
                            {num: 2, type: 'Snapshot', value: 'Alan'},
                            {num: 3, type: 'Historical', value: '02 June 2012'},
                            {num: 4, type: 'Data Type', value: 'type 2', last: true}
                        ]
                    }
                };
                $(selector).html(template)
                    /**
                     * Custom tab event, only triggers between top level menu items. e.g. a tab event will trigger
                     * when tab entering or tab leaving the evented element
                     */
                    .on('keydown', 'input, select, button', function (event) {
                        if (event.keyCode !== 9) return;
                        var $aggr = $(selector + ' .og-aggregation').find('input, select, button'),
                            $data = $(selector + ' .og-datasources').find('input, select, button'),
                            $self = $(this), shift_key = event.shiftKey,
                            trigger = function (menu) {$self.trigger('tab', menu);},
                            active_pos = function (elms, pos) {return $self.is(elms[pos]())},
                            view = $self.closest('.og-view').length,
                            aggregation = $self.closest('.og-aggregation').length,
                            datasources = $self.closest('.og-datasources').length,
                            load = $self.hasClass('og-load');
                        if (view && shift_key) return;
                        if (view && !shift_key) return trigger('aggregation');
                        if (aggregation && active_pos($aggr, 'last') && !shift_key) return trigger('datasources');
                        if (datasources && active_pos($data, 'first') && shift_key) return trigger('aggregation');
                        if (datasources && active_pos($data, 'last') && !shift_key) return trigger('load');
                        if (load && shift_key) return trigger('datasources');
                    })
                    .on('tab', function (event, type) {
                        switch (type) {
                            case 'aggregation': aggregation_menu.open(); break;
                            case 'datasources': datasources_menu.open(); break;
                            case 'load': aggregation_menu.close(); datasources_menu.close(); break;
                        }
                    })
                    /**
                     * The "open" event fires everytime a menu item is opened
                     */
                    .on('open', function (event, elm) {
                        if (!aggregation_menu || !datasources_menu) return;
                        if ($(elm).closest('.og-view').length) datasources_menu.close(), aggregation_menu.close();
                        if ($(elm).closest('.og-aggregation').length) datasources_menu.close();
                        if ($(elm).closest('.og-datasources').length) aggregation_menu.close();
                    })
                    .on('click', '.og-menu-aggregation button', function () {
                        var val = $(this).text();
                        if (val === 'OK') $(selector).trigger('tab', 'datasources'), datasources_menu.focus();
                        if (val === 'Cancel') aggregation_menu.close(), auto_combo_menu.select();
                    })
                    .on('click', '.og-menu-datasources button', function () {
                        var val = $(this).text();
                        if (val === 'OK') $(selector).trigger('tab', 'load'), $(selector + ' .og-load').focus();
                        if (val === 'Cancel') datasources_menu.close(), auto_combo_menu.select();
                    });
                var auto_combo_menu = new og.common.util.ui.AutoCombo(
                        '.OG-analytics-form .og-view', 'search...', response.view)
                    .on('input autocompletechange autocompleteselect', function (event, ui) {
                        var $load = $(selector + ' .og-load');
                        if ((ui && ui.item && ui.item.value || $(this).val()) !== '') {
                            $load.removeClass('og-disabled').on('click', function () {
                                og.analytics.url.main({
                                    type: 'portfolio',
                                    depgraph: false,
                                    viewdefinition: ui.item.value,
                                    providers: [{'marketDataType': 'live', 'source': 'Bloomberg'}]
                                });
//                                status.play();
                            });
                        }
                        else $load.addClass('og-disabled').off('click');
                    });
                var aggregation_menu = new FormCombo(
                    selector + ' .og-aggregation', 'og.analytics.form_aggregation_tash', response.aggregation
                );
                var datasources_menu = new FormCombo(
                    selector + ' .og-datasources', 'og.analytics.form_datasources_tash', response.datasources
                );
                var status = new Status(selector + ' .og-status');
                og.views.common.layout.main.allowOverflow('north');
            });
        }
    }
});<|endoftext|>


<commit_before>const functions = require("@google-cloud/functions-framework");
const util = require("util");

// note: isWarm is "undefined" until startup() starts executing
// then isWarm becomes a Promise which is never falsey (more below)
var isWarm = startup();

async function startup() {
  console.log("🥶 i'm a cold start");

  // 10 seconds seems to work best for this demo
  await sleep(10000);

  // when setTimeout is finished, have it resume with "I'm ready now"
  // just like any other real world connection
  console.log("I'm ready now");

  // the issue w returning boolean here is that at this point
  // isWarm = Promise { <pending> }
  // so it is always "truthy"
  // returning a string is a much better way to verify the work has been completed
  // and is closer to a real world scenario (e.g. approximating the data you get from an API)
  return "ready";
}

// simulating a long API call or slow network connection
function sleep(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

functions.http("cold-starts", async (req, res) => {
  // This next line allows you to check whether Promise is pending or is fulfilled
  // if pending, this evaluates to `Promise { <pending> }`
  // if fulfilled, this evaluates to `Promise { 'ready' }`
  // note: isWarm is a Promise, not a string
  var isStatusPending = util.inspect(isWarm).includes("pending");

  // Use stdout to see in Cloud Logging which revision & instanceId is handling the request
  console.log("request received...");

  if (isStatusPending) {
    console.log("I'm still a 🥶 start.");

    // javascript notes:
    // 1) you must use `await isWarm` and not `await isWarm()`
    // because it's a Promise, not a Function.
    // 2) to get the contents "ready" you have to resolve the Promise
    // this next line is the equivalent of calling .then(), so it goes onto "I'm ready now"
    var result = await isWarm;
    console.log("now I'm warmed up 🥰!");
  } else {
    // see note above re javascript
    var result = await isWarm;
    // and you'll see in the logs "I'm awake now" is immediately followed by
    // "I'm a warm instance", where both have the same instanceId
    // All the other "I'm ready now" logs all have different instanceIds
    console.log("🥰 I'm a warm instance.");
  }

  // and either 🥶 or 🥰 our request is completed!
  let message = req.query.message || req.body.message || "Request completed!";
  res.status(200).send(message);
});
<commit_msg>added copyright header<commit_after>/*
 Copyright 2022 Google LLC

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/

const functions = require("@google-cloud/functions-framework");
const util = require("util");

// note: isWarm is "undefined" until startup() starts executing
// then isWarm becomes a Promise which is never falsey (more below)
var isWarm = startup();

async function startup() {
  console.log("🥶 i'm a cold start");

  // 10 seconds seems to work best for this demo
  await sleep(10000);

  // when setTimeout is finished, have it resume with "I'm ready now"
  // just like any other real world connection
  console.log("I'm ready now");

  // the issue w returning boolean here is that at this point
  // isWarm = Promise { <pending> }
  // so it is always "truthy"
  // returning a string is a much better way to verify the work has been completed
  // and is closer to a real world scenario (e.g. approximating the data you get from an API)
  return "ready";
}

// simulating a long API call or slow network connection
function sleep(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

functions.http("cold-starts", async (req, res) => {
  // This next line allows you to check whether Promise is pending or is fulfilled
  // if pending, this evaluates to `Promise { <pending> }`
  // if fulfilled, this evaluates to `Promise { 'ready' }`
  // note: isWarm is a Promise, not a string
  var isStatusPending = util.inspect(isWarm).includes("pending");

  // Use stdout to see in Cloud Logging which revision & instanceId is handling the request
  console.log("request received...");

  if (isStatusPending) {
    console.log("I'm still a 🥶 start.");

    // javascript notes:
    // 1) you must use `await isWarm` and not `await isWarm()`
    // because it's a Promise, not a Function.
    // 2) to get the contents "ready" you have to resolve the Promise
    // this next line is the equivalent of calling .then(), so it goes onto "I'm ready now"
    var result = await isWarm;
    console.log("now I'm warmed up 🥰!");
  } else {
    // see note above re javascript
    var result = await isWarm;
    // and you'll see in the logs "I'm awake now" is immediately followed by
    // "I'm a warm instance", where both have the same instanceId
    // All the other "I'm ready now" logs all have different instanceIds
    console.log("🥰 I'm a warm instance.");
  }

  // and either 🥶 or 🥰 our request is completed!
  let message = req.query.message || req.body.message || "Request completed!";
  res.status(200).send(message);
});
<|endoftext|>


<commit_before>"use strict";

import L from "$APP/localization/localization";

import glyph from "$WIDGETS/glyph";

export default function lemmaActions() {
    return [ glyph({icon:"fav",   title: L.T("actions:favorite:title"), contents: L.T("actions:favorite")}),
             glyph({icon:"share", title: L.T("actions:share:title"),    contents: L.T("actions:share")}),
             glyph({icon:"note",  title: L.T("actions:note:title"),     contents: L.T("actions:note")})];
}
<commit_msg>Add favorite status<commit_after>"use strict";

import L from "$APP/localization/localization";

import glyph from "$WIDGETS/glyph";

export default function lemmaActions({isFavorite = false, hasNote = false} = {}) {
    return [ glyph({icon:"fav", contents: L.T(isFavorite ? "actions:unfavorite"
                                                         : "actions:favorite"),
                   props: { attrs: {"class": "fav-icon", "data-fav": isFavorite ? "yes" : "no",
                                    title: L.T(isFavorite ? "actions:unfavorite:title"
                                                          : "actions:favorite:title") } } }),
             glyph({icon:"share", title: L.T("actions:share:title"),    contents: L.T("actions:share")}),
             glyph({icon:"note",  title: L.T("actions:note:title"),     contents: L.T("actions:note")})];
}
<|endoftext|>


<commit_before>App.views.Project.addChild('ProjectContributions', _.extend({
  el: '#project_contributions',

  activate: function(){

    this.filter = {available_to_count: true};
    this.setupPagination(
      this.$("#contributions-loading img"),
      this.$("#load-more"),
      this.$(".results"),
      this.$el.data('path')
    );
    this.parent.on('selectTab', this.fetchPage);
  },

  events:{
    "click input[type='radio'][name=contribution_state]": "showContributions",
    "click #load-more" : "loadMore"
  },

  showContributions: function(){

    var state = $('input:radio[name=contribution_state]:checked').val();

    this.filter = { page: 1 };

    if(state == 'waiting_confirmation'){

      this.filter.with_state = 'waiting_confirmation';

    }else{

      this.filter.available_to_count: true;

    }

    this.$('.results').empty();

    this.fetchPage();

  }

}, Skull.Pagination));

<commit_msg>Fix typo<commit_after>App.views.Project.addChild('ProjectContributions', _.extend({
  el: '#project_contributions',

  activate: function(){

    this.filter = {available_to_count: true};
    this.setupPagination(
      this.$("#contributions-loading img"),
      this.$("#load-more"),
      this.$(".results"),
      this.$el.data('path')
    );
    this.parent.on('selectTab', this.fetchPage);
  },

  events:{
    "click input[type='radio'][name=contribution_state]": "showContributions",
    "click #load-more" : "loadMore"
  },

  showContributions: function(){

    var state = $('input:radio[name=contribution_state]:checked').val();

    this.filter = { page: 1 };

    if(state == 'waiting_confirmation'){

      this.filter.with_state = 'waiting_confirmation';

    }else{

      this.filter.available_to_count = true;

    }

    this.$('.results').empty();

    this.fetchPage();

  }

}, Skull.Pagination));

<|endoftext|>


<commit_before>"use strict";

if (Settings.get("vimSync") === true) setTimeout(function() { if (!chrome.storage) { return; }
  var Sync = Settings.Sync = {
    storage: chrome.storage.sync,
    to_update: null,
    doNotSync: Object.setPrototypeOf({
      findModeRawQueryList: 1, keyboard: 1
    }, null),
    HandleStorageUpdate: function(changes) {
      var change, key;
      Object.setPrototypeOf(changes, null);
      for (key in changes) {
        change = changes[key];
        Sync.storeAndPropagate(key, change != null ? change.newValue : null);
      }
    },
    storeAndPropagate: function(key, value) {
      var curVal, jsonVal, defaultVal = Settings.defaults[key], notJSON;
      if (!this.shouldSyncKey(key)) { return; }
      if (value == null) {
        if (key in localStorage) {
          Settings.set(key, defaultVal);
        }
        return;
      }
      curVal = Settings.get(key);
      if (notJSON = typeof defaultVal === "string") {
        jsonVal = value;
      } else {
        jsonVal = JSON.stringify(value);
        curVal = JSON.stringify(curVal);
      }
      if (jsonVal === curVal) { return; }
      curVal = notJSON ? defaultVal : JSON.stringify(defaultVal);
      if (jsonVal === curVal) {
        value = defaultVal;
      }
      Settings.set(key, value);
    },
    set: function(key, value) {
      if (!this.shouldSyncKey(key)) { return; }
      var items = this.to_update;
      if (!items) {
        setTimeout(this.DoUpdate, 60000);
        items = this.to_update = Object.create(null);
      }
      items[key] = value;
    },
    DoUpdate: function() {
      var items = Sync.to_update, removed = [], key, left = 0;
      Sync.to_update = null;
      if (!items) { return; }
      for (key in items) {
        if (items[key] != null) {
          ++left;
        } else {
          delete items[key];
          removed.push(key);
        }
      }
      if (removed.length > 0) {
        Sync.storage.remove(removed);
      }
      if (left > 0) {
        Sync.storage.set(items);
      }
    },
    shouldSyncKey: function(key) {
      return (key in Settings.defaults) && !(key in this.doNotSync);
    }
  };
  chrome.storage.onChanged.addListener(Sync.HandleStorageUpdate);
  Sync.storage.get(null, function(items) {
    var key, value;
    if (value = chrome.runtime.lastError) { return value; }
    Object.setPrototypeOf(items, null);
    for (key in items) {
      Sync.storeAndPropagate(key, items[key]);
    }
  });
}, 400);

setTimeout(function() { if (!chrome.browserAction) { return; }
  var func = Settings.updateHooks.showActionIcon, imageData, tabIds;
  function loadImageAndSetIcon(type, path) {
    var img, i, cache = Object.create(null), count = 0,
    onerror = function() {
      console.error('Could not load action icon \'' + this.src + '\'.');
    },
    onload = function() {
      var canvas = document.createElement('canvas'), w = this.width, h = this.h, ctx;
      w = canvas.width = this.width, h = canvas.height = this.height;
      ctx = canvas.getContext('2d');
      ctx.clearRect(0, 0, w, h);
      ctx.drawImage(this, 0, 0, w, h);
      cache[w] = ctx.getImageData(0, 0, w, h);
      if (count++) { return; }
      imageData[type] = cache;
      var arr = tabIds[type];
      delete tabIds[type];
      for (w = 0, h = arr.length; w < h; w++) {
        g_requestHandlers.SetIcon(arr[w], type);
      }
    };
    Object.setPrototypeOf(path, null);
    for (i in path) {
      img = new Image();
      img.onload = onload, img.onerror = onerror;
      img.src = path[i];
    }
  };
  Settings.SetIconBuffer = function(enabled) {
    if (!enabled) { return imageData = tabIds = null; }
    if (imageData) { return; }
    imageData = Object.create(null);
    tabIds = Object.create(null);
  };
  g_requestHandlers.SetIcon = function(tabId, type) {
    var data, path;
    if (data = imageData[type]) {
      chrome.browserAction.setIcon({
        tabId: tabId,
        imageData: data
      });
    } else if (tabIds[type]) {
      tabIds[type].push(tabId);
    } else if (path = Settings.icons[type]) {
      setTimeout(loadImageAndSetIcon, 0, type, path);
      tabIds[type] = [tabId];
    }
  };
  Settings.updateHooks.showActionIcon = function (value) {
    func.call(this, value);
    Settings.SetIconBuffer(value);
    if (value) {
      chrome.browserAction.setTitle({
        title: "Vimium++"
      });
      chrome.browserAction.enable();
    } else {
      chrome.browserAction.disable();
      chrome.browserAction.setTitle({
        title: "Vimium++\nThis icon is not in use"
      });
    }
  };
  Settings.postUpdate("showActionIcon");
}, 150);

setTimeout(function() { if (!chrome.omnibox) { return; }
  var last, firstUrl, lastSuggest, spanRe = /<(\/?)span(?: [^>]+)?>/g,
  tempRequest, timeout = 0, sessionIds, suggestions = null, outTimeout = 0, outTime,
  defaultSug = { description: "<dim>Open: </dim><url>%s</url>" },
  formatSessionId = function(sug) {
    if (sug.sessionId != null) {
      sessionIds[sug.url] = sug.sessionId;
    }
  },
  format = function(sug) {
    var str;
    if (sug.description) {
      str = sug.description;
    } else {
      str = "<url>" + sug.textSplit.replace(spanRe, "<$1match>");
      str += sug.title ? "</url><dim> - " + Utils.escapeText(sug.title) + "</dim>"
        : "</url>";
    }
    return {
      content: sug.url,
      description: str
    }
  },
  clean = function() {
    firstUrl = "";
    last = sessionIds = tempRequest = suggestions = null;
    if (lastSuggest) {
      lastSuggest.isOff = true;
      lastSuggest = null;
    }
    if (outTimeout) {
      clearTimeout(outTimeout);
      outTime = outTimeout = 0;
    }
  },
  outClean = function() {
    if (Date.now() - outTime > 5000) {
      clean();
    } else {
      outTimeout = setTimeout(outClean, 30000);
    }
  },
  onTimer = function() {
    timeout = 0;
    var arr;
    if (arr = tempRequest) {
      tempRequest = null;
      onInput(arr[0], arr[1]);
    }
  },
  onComplete = function(suggest, response, autoSelect) {
    if (!lastSuggest || suggest.isOff) { return; }
    if (suggest === lastSuggest) { lastSuggest = null; }
    var sug = response[0];
    if (sug && "sessionId" in sug) {
      sessionIds = Object.create(null);
      response.forEach(formatSessionId);
    }
    if (autoSelect) {
      firstUrl = sug.url;
      response.shift();
    }
    if (!autoSelect) {
      chrome.omnibox.setDefaultSuggestion(defaultSug);
    } else if (sug.type === "search") {
      var text = sug.titleSplit.replace(spanRe, "");
      text = Utils.escapeText(text.substring(0, text.indexOf(":")));
      text = "<dim>" + text + " - </dim><url>" +
        sug.textSplit.replace(spanRe, "<$1match>") + "</url>";
      chrome.omnibox.setDefaultSuggestion({ description: text });
      if (sug = response[0]) switch (sug.type) {
      case "math":
        sug.description = "<dim>" + sug.textSplit + " = </dim><url><match>" +
          sug.titleSplit + "</match></url>";
        break;
      }
    } else {
      chrome.omnibox.setDefaultSuggestion({ description: format(sug).description });
    }
    response = response.map(format);
    suggest(suggestions = response);
    outTimeout || setTimeout(outClean, 30000);
  },
  onInput = function(key, suggest) {
    key = key.trim();
    if (key === last) { suggestions && suggest(suggestions); return; }
    lastSuggest && (lastSuggest.isOff = true);
    if (timeout) {
      tempRequest = [key, suggest];
      return;
    } else if (suggestions && suggestions.length === 0 && key.startsWith(last)) {
      return suggest([]);
    }
    timeout = setTimeout(onTimer, 300);
    outTime = Date.now();
    firstUrl = "";
    sessionIds = suggestions = null;
    last = key;
    lastSuggest = suggest;
    Completers.omni.filter(key, {
      maxResults: 6
    }, onComplete.bind(null, suggest));
  },
  onEnter = function(text, disposition) {
    text = text.trim();
    if (tempRequest && tempRequest[0] === text) {
      tempRequest = [text, onEnter.bind(null, text, disposition)];
      onTimer();
      return;
    } else if (lastSuggest) {
      return;
    }
    if (firstUrl && text === last) { text = firstUrl; }
    var sessionId = sessionIds && sessionIds[text];
    clean();
    if (sessionId != null) {
      g_requestHandlers.gotoSession({ sessionId: sessionId });
      return;
    }
    g_requestHandlers.openUrl({
      url: text,
      reuse: (disposition === "currentTab" ? 0
        : disposition === "newForegroundTab" ? -1 : -2)
    });
  };
  chrome.omnibox.onInputChanged.addListener(onInput);
  chrome.omnibox.onInputEntered.addListener(onEnter);
  chrome.omnibox.onInputCancelled.addListener(clean);
}, 600);

// According to tests: onInstalled will be executed after 0 ~ 16 ms if needed
chrome.runtime.onInstalled.addListener(window.b = function(details) {
  var reason = details.reason;
  if (reason === "install") { reason = ""; }
  else if (reason === "update") { reason = details.previousVersion; }
  else { return; }

setTimeout(function() {
  chrome.tabs.query({
    status: "complete"
  }, function(tabs) {
    var _i = tabs.length, tabId, _j, _len, callback, url, t = chrome.tabs, ref, contentScripts, js;
    callback = function() { return chrome.runtime.lastError; };
    contentScripts = chrome.runtime.getManifest().content_scripts[0];
    ref = {file: "", allFrames: contentScripts.all_frames};
    js = contentScripts.js;
    _len = js.length - 1;
    for (; 0 <= --_i; ) {
      url = tabs[_i].url;
      if (url.startsWith("chrome") || url.indexOf("://") === -1) continue;
      tabId = tabs[_i].id;
      for (_j = 0; _j < _len; ++_j) {
        ref.file = js[_j];
        t.executeScript(tabId, ref, callback);
      }
    }
    function now() {
      return new Date(Date.now() - new Date().getTimezoneOffset() * 1000 * 60
        ).toJSON().substring(0, 19).replace('T', ' ');
    };
    console.log("%cVimium++%c has %cinstalled%c with %O at %c%s%c .", "color:red", "color:auto"
      , "color:blue", "color:auto;", details, "color:#1c00cf", now(), "color:auto");
  });

  if (!reason) { return; }

  function compareVersion(versionA, versionB) {
    var a, b, i, _ref;
    versionA = versionA.split('.');
    versionB = versionB.split('.');
    for (i = 0, _ref = Math.max(versionA.length, versionB.length); i < _ref; ++i) {
      a = parseInt(versionA[i] || 0, 10);
      b = parseInt(versionB[i] || 0, 10);
      if (a < b) {
        return -1;
      } else if (a > b) {
        return 1;
      }
    }
    return 0;
  };
  if (compareVersion(Settings.CONST.CurrentVersion, reason) <= 0) { return; }

  reason = "vimium++_upgradeNotification";
  chrome.notifications && chrome.notifications.create(reason, {
    type: "basic",
    iconUrl: location.origin + "/icons/icon128.png",
    title: "Vimium++ Upgrade",
    message: "Vimium++ has been upgraded to version " + Settings.CONST.CurrentVersion
      + ". Click here for more information.",
    isClickable: true
  }, function(notificationId) {
    if (chrome.runtime.lastError) {
      chrome.notifications = null;
      return chrome.runtime.lastError;
    }
    reason = notificationId || reason;
    chrome.notifications.onClicked.addListener(function(id) {
      if (id !== reason) { return; }
      g_requestHandlers.focusOrLaunch({
        url: "https://github.com/gdh1995/vimium-plus#release-notes"
      });
    });
    chrome.notifications = null;
  });
}, 500);
});

setTimeout(function() {
  chrome.runtime.onInstalled.removeListener(window.b);
  window.b = null;

  document.head.remove();
  document.body.remove();
}, 200);

//* #if DEBUG
var a, b, c, cb, log;
cb = function(b) { a = b; console.log(b); };
setTimeout(function() {
  a = c = null; b = cb;
  log = console.log.bind(console);
}, 2000); // #endif */
<commit_msg>deduplicate calls to omnibox.setDefaultSuggestion<commit_after>"use strict";

if (Settings.get("vimSync") === true) setTimeout(function() { if (!chrome.storage) { return; }
  var Sync = Settings.Sync = {
    storage: chrome.storage.sync,
    to_update: null,
    doNotSync: Object.setPrototypeOf({
      findModeRawQueryList: 1, keyboard: 1
    }, null),
    HandleStorageUpdate: function(changes) {
      var change, key;
      Object.setPrototypeOf(changes, null);
      for (key in changes) {
        change = changes[key];
        Sync.storeAndPropagate(key, change != null ? change.newValue : null);
      }
    },
    storeAndPropagate: function(key, value) {
      var curVal, jsonVal, defaultVal = Settings.defaults[key], notJSON;
      if (!this.shouldSyncKey(key)) { return; }
      if (value == null) {
        if (key in localStorage) {
          Settings.set(key, defaultVal);
        }
        return;
      }
      curVal = Settings.get(key);
      if (notJSON = typeof defaultVal === "string") {
        jsonVal = value;
      } else {
        jsonVal = JSON.stringify(value);
        curVal = JSON.stringify(curVal);
      }
      if (jsonVal === curVal) { return; }
      curVal = notJSON ? defaultVal : JSON.stringify(defaultVal);
      if (jsonVal === curVal) {
        value = defaultVal;
      }
      Settings.set(key, value);
    },
    set: function(key, value) {
      if (!this.shouldSyncKey(key)) { return; }
      var items = this.to_update;
      if (!items) {
        setTimeout(this.DoUpdate, 60000);
        items = this.to_update = Object.create(null);
      }
      items[key] = value;
    },
    DoUpdate: function() {
      var items = Sync.to_update, removed = [], key, left = 0;
      Sync.to_update = null;
      if (!items) { return; }
      for (key in items) {
        if (items[key] != null) {
          ++left;
        } else {
          delete items[key];
          removed.push(key);
        }
      }
      if (removed.length > 0) {
        Sync.storage.remove(removed);
      }
      if (left > 0) {
        Sync.storage.set(items);
      }
    },
    shouldSyncKey: function(key) {
      return (key in Settings.defaults) && !(key in this.doNotSync);
    }
  };
  chrome.storage.onChanged.addListener(Sync.HandleStorageUpdate);
  Sync.storage.get(null, function(items) {
    var key, value;
    if (value = chrome.runtime.lastError) { return value; }
    Object.setPrototypeOf(items, null);
    for (key in items) {
      Sync.storeAndPropagate(key, items[key]);
    }
  });
}, 400);

setTimeout(function() { if (!chrome.browserAction) { return; }
  var func = Settings.updateHooks.showActionIcon, imageData, tabIds;
  function loadImageAndSetIcon(type, path) {
    var img, i, cache = Object.create(null), count = 0,
    onerror = function() {
      console.error('Could not load action icon \'' + this.src + '\'.');
    },
    onload = function() {
      var canvas = document.createElement('canvas'), w = this.width, h = this.h, ctx;
      w = canvas.width = this.width, h = canvas.height = this.height;
      ctx = canvas.getContext('2d');
      ctx.clearRect(0, 0, w, h);
      ctx.drawImage(this, 0, 0, w, h);
      cache[w] = ctx.getImageData(0, 0, w, h);
      if (count++) { return; }
      imageData[type] = cache;
      var arr = tabIds[type];
      delete tabIds[type];
      for (w = 0, h = arr.length; w < h; w++) {
        g_requestHandlers.SetIcon(arr[w], type);
      }
    };
    Object.setPrototypeOf(path, null);
    for (i in path) {
      img = new Image();
      img.onload = onload, img.onerror = onerror;
      img.src = path[i];
    }
  };
  Settings.SetIconBuffer = function(enabled) {
    if (!enabled) { return imageData = tabIds = null; }
    if (imageData) { return; }
    imageData = Object.create(null);
    tabIds = Object.create(null);
  };
  g_requestHandlers.SetIcon = function(tabId, type) {
    var data, path;
    if (data = imageData[type]) {
      chrome.browserAction.setIcon({
        tabId: tabId,
        imageData: data
      });
    } else if (tabIds[type]) {
      tabIds[type].push(tabId);
    } else if (path = Settings.icons[type]) {
      setTimeout(loadImageAndSetIcon, 0, type, path);
      tabIds[type] = [tabId];
    }
  };
  Settings.updateHooks.showActionIcon = function (value) {
    func.call(this, value);
    Settings.SetIconBuffer(value);
    if (value) {
      chrome.browserAction.setTitle({
        title: "Vimium++"
      });
      chrome.browserAction.enable();
    } else {
      chrome.browserAction.disable();
      chrome.browserAction.setTitle({
        title: "Vimium++\nThis icon is not in use"
      });
    }
  };
  Settings.postUpdate("showActionIcon");
}, 150);

setTimeout(function() { if (!chrome.omnibox) { return; }
  var last, firstUrl, lastSuggest, spanRe = /<(\/?)span(?: [^>]+)?>/g,
  tempRequest, timeout = 0, sessionIds, suggestions = null, outTimeout = 0, outTime,
  defaultSug = { description: "<dim>Open: </dim><url>%s</url>" },
  defaultSuggestionType = 0,
  formatSessionId = function(sug) {
    if (sug.sessionId != null) {
      sessionIds[sug.url] = sug.sessionId;
    }
  },
  format = function(sug) {
    var str;
    if (sug.description) {
      str = sug.description;
    } else {
      str = "<url>" + sug.textSplit.replace(spanRe, "<$1match>");
      str += sug.title ? "</url><dim> - " + Utils.escapeText(sug.title) + "</dim>"
        : "</url>";
    }
    return {
      content: sug.url,
      description: str
    }
  },
  clean = function() {
    firstUrl = "";
    last = sessionIds = tempRequest = suggestions = null;
    if (lastSuggest) {
      lastSuggest.isOff = true;
      lastSuggest = null;
    }
    if (outTimeout) {
      clearTimeout(outTimeout);
      outTime = outTimeout = 0;
    }
  },
  outClean = function() {
    if (Date.now() - outTime > 5000) {
      clean();
    } else {
      outTimeout = setTimeout(outClean, 30000);
    }
  },
  onTimer = function() {
    timeout = 0;
    var arr;
    if (arr = tempRequest) {
      tempRequest = null;
      onInput(arr[0], arr[1]);
    }
  },
  onComplete = function(suggest, response, autoSelect) {
    if (!lastSuggest || suggest.isOff) { return; }
    if (suggest === lastSuggest) { lastSuggest = null; }
    var sug = response[0];
    if (sug && "sessionId" in sug) {
      sessionIds = Object.create(null);
      response.forEach(formatSessionId);
    }
    if (autoSelect) {
      firstUrl = sug.url;
      response.shift();
    }
    if (!autoSelect) {
      if (defaultSuggestionType !== 1) {
        chrome.omnibox.setDefaultSuggestion(defaultSug);
        defaultSuggestionType = 1;
      }
    } else if (sug.type === "search") {
      var text = sug.titleSplit.replace(spanRe, "");
      text = Utils.escapeText(text.substring(0, text.indexOf(":")));
      text = "<dim>" + text + " - </dim><url>" +
        sug.textSplit.replace(spanRe, "<$1match>") + "</url>";
      defaultSuggestionType = 2;
      chrome.omnibox.setDefaultSuggestion({ description: text });
      if (sug = response[0]) switch (sug.type) {
      case "math":
        sug.description = "<dim>" + sug.textSplit + " = </dim><url><match>" +
          sug.titleSplit + "</match></url>";
        break;
      }
    } else {
      defaultSuggestionType = 3;
      chrome.omnibox.setDefaultSuggestion({ description: format(sug).description });
    }
    response = response.map(format);
    suggest(suggestions = response);
    outTimeout || setTimeout(outClean, 30000);
  },
  onInput = function(key, suggest) {
    key = key.trim();
    if (key === last) { suggestions && suggest(suggestions); return; }
    lastSuggest && (lastSuggest.isOff = true);
    if (timeout) {
      tempRequest = [key, suggest];
      return;
    } else if (suggestions && suggestions.length === 0 && key.startsWith(last)) {
      return suggest([]);
    }
    timeout = setTimeout(onTimer, 300);
    outTime = Date.now();
    firstUrl = "";
    sessionIds = suggestions = null;
    last = key;
    lastSuggest = suggest;
    Completers.omni.filter(key, {
      maxResults: 6
    }, onComplete.bind(null, suggest));
  },
  onEnter = function(text, disposition) {
    text = text.trim();
    if (tempRequest && tempRequest[0] === text) {
      tempRequest = [text, onEnter.bind(null, text, disposition)];
      onTimer();
      return;
    } else if (lastSuggest) {
      return;
    }
    if (firstUrl && text === last) { text = firstUrl; }
    var sessionId = sessionIds && sessionIds[text];
    clean();
    if (sessionId != null) {
      g_requestHandlers.gotoSession({ sessionId: sessionId });
      return;
    }
    g_requestHandlers.openUrl({
      url: text,
      reuse: (disposition === "currentTab" ? 0
        : disposition === "newForegroundTab" ? -1 : -2)
    });
  };
  chrome.omnibox.onInputChanged.addListener(onInput);
  chrome.omnibox.onInputEntered.addListener(onEnter);
  chrome.omnibox.onInputCancelled.addListener(clean);
}, 600);

// According to tests: onInstalled will be executed after 0 ~ 16 ms if needed
chrome.runtime.onInstalled.addListener(window.b = function(details) {
  var reason = details.reason;
  if (reason === "install") { reason = ""; }
  else if (reason === "update") { reason = details.previousVersion; }
  else { return; }

setTimeout(function() {
  chrome.tabs.query({
    status: "complete"
  }, function(tabs) {
    var _i = tabs.length, tabId, _j, _len, callback, url, t = chrome.tabs, ref, contentScripts, js;
    callback = function() { return chrome.runtime.lastError; };
    contentScripts = chrome.runtime.getManifest().content_scripts[0];
    ref = {file: "", allFrames: contentScripts.all_frames};
    js = contentScripts.js;
    _len = js.length - 1;
    for (; 0 <= --_i; ) {
      url = tabs[_i].url;
      if (url.startsWith("chrome") || url.indexOf("://") === -1) continue;
      tabId = tabs[_i].id;
      for (_j = 0; _j < _len; ++_j) {
        ref.file = js[_j];
        t.executeScript(tabId, ref, callback);
      }
    }
    function now() {
      return new Date(Date.now() - new Date().getTimezoneOffset() * 1000 * 60
        ).toJSON().substring(0, 19).replace('T', ' ');
    };
    console.log("%cVimium++%c has %cinstalled%c with %O at %c%s%c .", "color:red", "color:auto"
      , "color:blue", "color:auto;", details, "color:#1c00cf", now(), "color:auto");
  });

  if (!reason) { return; }

  function compareVersion(versionA, versionB) {
    var a, b, i, _ref;
    versionA = versionA.split('.');
    versionB = versionB.split('.');
    for (i = 0, _ref = Math.max(versionA.length, versionB.length); i < _ref; ++i) {
      a = parseInt(versionA[i] || 0, 10);
      b = parseInt(versionB[i] || 0, 10);
      if (a < b) {
        return -1;
      } else if (a > b) {
        return 1;
      }
    }
    return 0;
  };
  if (compareVersion(Settings.CONST.CurrentVersion, reason) <= 0) { return; }

  reason = "vimium++_upgradeNotification";
  chrome.notifications && chrome.notifications.create(reason, {
    type: "basic",
    iconUrl: location.origin + "/icons/icon128.png",
    title: "Vimium++ Upgrade",
    message: "Vimium++ has been upgraded to version " + Settings.CONST.CurrentVersion
      + ". Click here for more information.",
    isClickable: true
  }, function(notificationId) {
    if (chrome.runtime.lastError) {
      chrome.notifications = null;
      return chrome.runtime.lastError;
    }
    reason = notificationId || reason;
    chrome.notifications.onClicked.addListener(function(id) {
      if (id !== reason) { return; }
      g_requestHandlers.focusOrLaunch({
        url: "https://github.com/gdh1995/vimium-plus#release-notes"
      });
    });
    chrome.notifications = null;
  });
}, 500);
});

setTimeout(function() {
  chrome.runtime.onInstalled.removeListener(window.b);
  window.b = null;

  document.head.remove();
  document.body.remove();
}, 200);

//* #if DEBUG
var a, b, c, cb, log;
cb = function(b) { a = b; console.log(b); };
setTimeout(function() {
  a = c = null; b = cb;
  log = console.log.bind(console);
}, 2000); // #endif */
<|endoftext|>


<commit_before>function InitialMissionInstruction(compass, mapService, neighborhoodContainer, popUpMessage, taskContainer,
                                   labelContainer) {
    var self = this;
    var initialHeading;
    var lookingAroundInterval;
    var lastHeadingTransformed;
    var viewedCWTransformed = 0, viewedCCWTransformed = 360;
    var initialPanoId;

    this._finishedInstructionToStart = function () {
        if (!svl.isOnboarding()) {
            mapService.bindPositionUpdate(self._instructToCheckSidewalks);
        }
    };

    this._instructToCheckSidewalks = function () {
        if (!svl.isOnboarding()) {
            // Instruct a user to audit both sides of the streets once they have walked for 25 meters.
            var neighborhood = neighborhoodContainer.getCurrentNeighborhood();
            var distance = taskContainer.getCompletedTaskDistance(neighborhood.getProperty("regionId"), "kilometers");
            if (distance >= 0.025) {
                var title = "Please check both sides of the street";
                var message = "Remember, we would like you to check both sides of the street. " +
                    "Please label accessibility issues like sidewalk obstacles and surface problems.";

                popUpMessage.notify(title, message, function() {
                    mapService.unbindPositionUpdate(self._instructToCheckSidewalks);
                    mapService.bindPositionUpdate(self._instructForGSVLabelDisappearing);
                });
            }
        }
    };

    this._finishedInstructionForGSVLabelDisappearing = function () {
        mapService.stopBlinkingGoogleMaps();

        if (!svl.isOnboarding()) {
            mapService.unbindPositionUpdate(self._instructForGSVLabelDisappearing);
        }
    };

    this._instructForGSVLabelDisappearing = function () {
        if (!svl.isOnboarding()) {
            // Instruct the user about GSV labels disappearing when they have labeled and walked for the first time
            var labels = svl.labelContainer.getCurrentLabels();
            var prev_labels = svl.labelContainer.getPreviousLabels();
            if (labels.length == 0) {
                labels = prev_labels;
            }
            if (labels.length > 0) {
                var title = "Labels on the image disappear";
                var message = "If you turn back now to look at your labels, they would not appear on the Street View " +
                    "image after you have taken a step. " +
                    "However, they aren't gone. You can track them on the highlighed map.";

                popUpMessage.notify(title, message, self._finishedInstructionForGSVLabelDisappearing);
                mapService.blinkGoogleMaps();
            }
        }
    };

    this._instructToFollowTheGuidance = function () {
        if (!svl.isOnboarding()) {
            var title = "Let's take a step!";
            var message = "It looks like you've looked around this entire intersection, so it's time to explore " +
                "other areas. Walk in the direction of the red line highlighted on the map.";

            popUpMessage.notify(title, message, function () {
                self._stopBlinkingNavigationComponents();
            });
            compass.blink();
            mapService.blinkGoogleMaps();
        }
    };

    this._transformAngle = function (angle) {
        while ((angle - initialHeading) % 360 < 0)
            angle += 360;
        return (angle - initialHeading) % 360;
    };

    this._pollLookingAroundHasFinished = function () {
        var currentHeadingAngle = mapService.getPov().heading;
        var transformedCurrent = self._transformAngle(currentHeadingAngle);
        var direction;
        var EPS = 30; //the smaller it is the higher the speed of calling this function should be

        if (transformedCurrent > 360 - EPS && lastHeadingTransformed < EPS)
            direction = transformedCurrent - (lastHeadingTransformed + 360);
        else if (currentHeadingAngle < EPS && lastHeadingTransformed > 360 - EPS)
            direction = transformedCurrent - (lastHeadingTransformed - 360);
        else
            direction = transformedCurrent - lastHeadingTransformed;

        if (direction > 0 && transformedCurrent < viewedCWTransformed + EPS) {
            // user is rotating clockwise
            viewedCWTransformed = Math.max(viewedCWTransformed, transformedCurrent);
        } else if (direction < 0 && transformedCurrent > viewedCCWTransformed - EPS) {
            //user is rotating counter clockwise
            viewedCCWTransformed = Math.min(viewedCCWTransformed, transformedCurrent);
        }

        lastHeadingTransformed = transformedCurrent;

        var overallAngleViewed = (360 - viewedCCWTransformed) + viewedCWTransformed;

        if (overallAngleViewed >= 360 - EPS) {
            clearInterval(lookingAroundInterval);

            //check the panoId to make sure the user hasn't walked
            if (mapService.getPanoId() == initialPanoId) {
                self._instructToFollowTheGuidance();
            }
        }
    };

    this._stopBlinkingNavigationComponents = function () {
        compass.stopBlinking();
        mapService.stopBlinkingGoogleMaps();
    };

    this.start = function (neighborhood) {
        if (!svl.isOnboarding()) {
            var title = "Let's get started!";
            var message = "We have moved you to a street in " + neighborhood.getProperty("name") +
                ", DC! You are currently standing at the intersection. Please find and label all the curb ramps and " +
                "accessibility problems at this intersection.";

            popUpMessage.notify(title, message, self._finishedInstructionToStart);

            initialHeading = mapService.getPov().heading;
            lastHeadingTransformed = self._transformAngle(mapService.getPov().heading);
            initialPanoId = mapService.getPanoId();
            lookingAroundInterval = setInterval(self._pollLookingAroundHasFinished, 1);
        }
    };

}<commit_msg>Fixes a bug that causes labels from onboarding mission to show labels not appearing popup<commit_after>function InitialMissionInstruction(compass, mapService, neighborhoodContainer, popUpMessage, taskContainer,
                                   labelContainer) {
    var self = this;
    var initialHeading;
    var lookingAroundInterval;
    var lastHeadingTransformed;
    var viewedCWTransformed = 0, viewedCCWTransformed = 360;
    var initialPanoId;

    this._finishedInstructionToStart = function () {
        if (!svl.isOnboarding()) {
            mapService.bindPositionUpdate(self._instructToCheckSidewalks);
        }
    };

    this._instructToCheckSidewalks = function () {
        if (!svl.isOnboarding()) {
            // Instruct a user to audit both sides of the streets once they have walked for 25 meters.
            var neighborhood = neighborhoodContainer.getCurrentNeighborhood();
            var distance = taskContainer.getCompletedTaskDistance(neighborhood.getProperty("regionId"), "kilometers");
            if (distance >= 0.025) {
                var title = "Please check both sides of the street";
                var message = "Remember, we would like you to check both sides of the street. " +
                    "Please label accessibility issues like sidewalk obstacles and surface problems.";

                popUpMessage.notify(title, message, function() {
                    mapService.unbindPositionUpdate(self._instructToCheckSidewalks);
                    mapService.bindPositionUpdate(self._instructForGSVLabelDisappearing);
                });
            }
        }
    };

    this._finishedInstructionForGSVLabelDisappearing = function () {
        mapService.stopBlinkingGoogleMaps();

        if (!svl.isOnboarding()) {
            mapService.unbindPositionUpdate(self._instructForGSVLabelDisappearing);
        }
    };

    this._instructForGSVLabelDisappearing = function () {
        if (!svl.isOnboarding()) {
            // Instruct the user about GSV labels disappearing when they have labeled and walked for the first time
            var labels = labelContainer.getCurrentLabels();
            var prev_labels = labelContainer.getPreviousLabels();
            if (labels.length == 0) {
                labels = prev_labels;
            }
            var labelCount = labels.length;
            var nOnboardingLabels = 7;
            if (labelCount > 0) {
                if (svl.missionContainer.isTheFirstMission() && labelCount != nOnboardingLabels) {
                    var title = "Labels on the image disappear";
                    var message = "If you turn back now to look at your labels, they would not appear on the Street View " +
                        "image after you have taken a step. " +
                        "However, they aren't gone. You can track them on the highlighed map.";

                    popUpMessage.notify(title, message, self._finishedInstructionForGSVLabelDisappearing);
                    mapService.blinkGoogleMaps();
                }
            }
        }
    };

    this._instructToFollowTheGuidance = function () {
        if (!svl.isOnboarding()) {
            var title = "Let's take a step!";
            var message = "It looks like you've looked around this entire intersection, so it's time to explore " +
                "other areas. Walk in the direction of the red line highlighted on the map.";

            popUpMessage.notify(title, message, function () {
                self._stopBlinkingNavigationComponents();
            });
            compass.blink();
            mapService.blinkGoogleMaps();
        }
    };

    this._transformAngle = function (angle) {
        while ((angle - initialHeading) % 360 < 0)
            angle += 360;
        return (angle - initialHeading) % 360;
    };

    this._pollLookingAroundHasFinished = function () {
        var currentHeadingAngle = mapService.getPov().heading;
        var transformedCurrent = self._transformAngle(currentHeadingAngle);
        var direction;
        var EPS = 30; //the smaller it is the higher the speed of calling this function should be

        if (transformedCurrent > 360 - EPS && lastHeadingTransformed < EPS)
            direction = transformedCurrent - (lastHeadingTransformed + 360);
        else if (currentHeadingAngle < EPS && lastHeadingTransformed > 360 - EPS)
            direction = transformedCurrent - (lastHeadingTransformed - 360);
        else
            direction = transformedCurrent - lastHeadingTransformed;

        if (direction > 0 && transformedCurrent < viewedCWTransformed + EPS) {
            // user is rotating clockwise
            viewedCWTransformed = Math.max(viewedCWTransformed, transformedCurrent);
        } else if (direction < 0 && transformedCurrent > viewedCCWTransformed - EPS) {
            //user is rotating counter clockwise
            viewedCCWTransformed = Math.min(viewedCCWTransformed, transformedCurrent);
        }

        lastHeadingTransformed = transformedCurrent;

        var overallAngleViewed = (360 - viewedCCWTransformed) + viewedCWTransformed;

        if (overallAngleViewed >= 360 - EPS) {
            clearInterval(lookingAroundInterval);

            //check the panoId to make sure the user hasn't walked
            if (mapService.getPanoId() == initialPanoId) {
                self._instructToFollowTheGuidance();
            }
        }
    };

    this._stopBlinkingNavigationComponents = function () {
        compass.stopBlinking();
        mapService.stopBlinkingGoogleMaps();
    };

    this.start = function (neighborhood) {
        if (!svl.isOnboarding()) {
            var title = "Let's get started!";
            var message = "We have moved you to a street in " + neighborhood.getProperty("name") +
                ", DC! You are currently standing at the intersection. Please find and label all the curb ramps and " +
                "accessibility problems at this intersection.";

            popUpMessage.notify(title, message, self._finishedInstructionToStart);

            initialHeading = mapService.getPov().heading;
            lastHeadingTransformed = self._transformAngle(mapService.getPov().heading);
            initialPanoId = mapService.getPanoId();
            lookingAroundInterval = setInterval(self._pollLookingAroundHasFinished, 1);
        }
    };

}<|endoftext|>


<commit_before>/**
	_onyx.DatePicker_ is a group of onyx.Picker
	controls displaying the current date. The user may change the _day_,
	_month_, and _year_ values.

	By default, _DatePicker_ tries to determine the current locale and use its
	rules to format the date (including the month name). In order to do this
	successfully, the _g11n_ library must be loaded; if it is not loaded, the
	control defaults to using standard U.S. date format.

	The _day_ field is automatically populated with the proper number of days
	for the selected month and year.
 */
enyo.kind({
	name: "onyx.DatePicker",
	classes: "onyx-toolbar-inline",
	published: {
		disabled: false,
		/**
			Current locale used for formatting. Can be set after control
			creation, in which case the control will be updated to reflect the
			new value.
		*/
		locale: null,
		//* If true, the day field is hidden
		dayHidden: false,
		//* If true, the month field is hidden
		monthHidden: false,
		//* If true, the year field is hidden
		yearHidden: false,
		//* Optional minimum year value
		minYear: 1900,
		//* Optional maximum year value
		maxYear: 2099,
		/**
			The current Date object. When a Date object is passed to _setValue_,
			the control is updated to reflect the new value. _getValue_ returns
			a Date object.
		*/
		value: null
	},
	events: {
		/**
			Fires when one of the DatePicker's fields is selected.

			_inEvent.name_ contains the name of the DatePicker that generated
			the event.

			_inEvent.value_ contains the current Date value of the control.
		*/
		onSelect: ""
	},
	create: function() {
		this.inherited(arguments);
		if (!this.locale){
			try {
				this.locale = enyo.g11n.currentLocale().getLocale();
			}
			catch(err) {
				this.locale = "en_us";
			}
		}
		this.initDefaults();
	},
	initDefaults: function() {
		var months;
		//Attempt to use the g11n lib (ie assume it is loaded)
		try {
			this._tf = new enyo.g11n.Fmts({locale:this.locale});
			months = this._tf.getMonthFields();
		}
		catch(err) {
			//Fall back to en_us as default
			months = ["Jan", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"];
		}

		this.setupPickers(this._tf ? this._tf.getDateFieldOrder() : 'mdy');

		this.dayHiddenChanged();
		this.monthHiddenChanged();
		this.yearHiddenChanged();

		//Fill month, year & day pickers with values
		var d = this.value = this.value || new Date();
		for (var i=0,m; (m=months[i]); i++) {
			this.$.monthPicker.createComponent({content: m, value:i, active: i==d.getMonth()});
		}

		var y = d.getFullYear();
		this.$.yearPicker.setSelected(y-this.minYear);
		this.$.year.setContent(y);

		for (i=1; i<=this.monthLength(d.getYear(), d.getMonth()); i++) {
			this.$.dayPicker.createComponent({content:i, value:i, active: i==d.getDate()});
		}
	},
	monthLength: function(inYear, inMonth) {
		// determine number of days in a particular month/year
		return 32 - new Date(inYear, inMonth, 32).getDate();
	},
	setupYear: function(inSender, inEvent) {
		this.$.year.setContent(this.minYear+inEvent.index);
	},
	setupPickers: function(ordering) {
		var orderingArr = ordering.split("");
		var o,f,l;
		for(f = 0, l = orderingArr.length; f < l; f++) {
			o = orderingArr[f];
			switch (o){
				case 'd': this.createDay();
				break;
				case 'm': this.createMonth();
				break;
				case 'y': this.createYear();
				break;
				default: break;
			}
		}
	},
	createYear: function() {
		var yearCount = this.maxYear - this.minYear;
		this.createComponent(
			{kind: "onyx.PickerDecorator", onSelect: "updateYear", components: [
				{classes:"onyx-datepicker-year", name: "yearPickerButton",  disabled: this.disabled},
				{name: "yearPicker", kind: "onyx.FlyweightPicker", count: ++yearCount, onSetupItem: "setupYear", components: [
					{name: "year"}
				]}
			]}
		);
	},
	createMonth: function() {
		this.createComponent(
			{kind: "onyx.PickerDecorator", onSelect: "updateMonth", components: [
				{classes:"onyx-datepicker-month", name: "monthPickerButton",  disabled: this.disabled},
				{name: "monthPicker", kind: "onyx.Picker"}
			]}
		);
	},
	createDay: function() {
		this.createComponent(
			{kind: "onyx.PickerDecorator", onSelect: "updateDay", components: [
				{classes:"onyx-datepicker-day", name: "dayPickerButton",  disabled: this.disabled},
				{name: "dayPicker", kind: "onyx.Picker"}
			]}
		);
	},
	localeChanged: function() {
		this.refresh();
	},
	dayHiddenChanged: function() {
		this.$.dayPicker.getParent().setShowing(this.dayHidden ? false : true);
	},
	monthHiddenChanged: function() {
		this.$.monthPicker.getParent().setShowing(this.monthHidden ? false : true);
	},
	yearHiddenChanged: function() {
		this.$.yearPicker.getParent().setShowing(this.yearHidden ? false : true);
	},
	minYearChanged: function() {
		this.refresh();
	},
	maxYearChanged: function() {
		this.refresh();
	},
	valueChanged: function(){
		this.refresh();
	},
	disabledChanged: function() {
		this.yearPickerButton.setDisabled(this.disabled);
		this.monthPickerButton.setDisabled(this.disabled);
		this.dayPickerButton.setDisabled(this.disabled);
	},
	updateDay: function(inSender, inEvent){
		var date = this.calcDate(this.value.getFullYear(),
								this.value.getMonth(),
								inEvent.selected.value);
		this.doSelect({name:this.name, value:date});
		this.setValue(date);
	},
	updateMonth: function(inSender, inEvent){
		var date = this.calcDate(this.value.getFullYear(),
								inEvent.selected.value,
								this.value.getDate());
		this.doSelect({name:this.name, value:date});
		this.setValue(date);
	},
	updateYear: function(inSender, inEvent){
		var date = this.calcDate(this.minYear + inEvent.originator.selected,
								this.value.getMonth(),
								this.value.getDate());
		this.doSelect({name:this.name, value:date});
		this.setValue(date);
	},
	calcDate: function(year, month, day){
		return new Date(year,month,day,
						this.value.getHours(),
						this.value.getMinutes(),
						this.value.getSeconds(),
						this.value.getMilliseconds());
	},
	refresh: function(){
		this.destroyClientControls();
		this.initDefaults();
		this.render();
	}
});
<commit_msg>Added disabled property description<commit_after>/**
	_onyx.DatePicker_ is a group of onyx.Picker
	controls displaying the current date. The user may change the _day_,
	_month_, and _year_ values.

	By default, _DatePicker_ tries to determine the current locale and use its
	rules to format the date (including the month name). In order to do this
	successfully, the _g11n_ library must be loaded; if it is not loaded, the
	control defaults to using standard U.S. date format.

	The _day_ field is automatically populated with the proper number of days
	for the selected month and year.
 */
enyo.kind({
	name: "onyx.DatePicker",
	classes: "onyx-toolbar-inline",
	published: {
		//* If true, control is shown as disabled, and user can't select new values
		disabled: false,
		/**
			Current locale used for formatting. Can be set after control
			creation, in which case the control will be updated to reflect the
			new value.
		*/
		locale: null,
		//* If true, the day field is hidden
		dayHidden: false,
		//* If true, the month field is hidden
		monthHidden: false,
		//* If true, the year field is hidden
		yearHidden: false,
		//* Optional minimum year value
		minYear: 1900,
		//* Optional maximum year value
		maxYear: 2099,
		/**
			The current Date object. When a Date object is passed to _setValue_,
			the control is updated to reflect the new value. _getValue_ returns
			a Date object.
		*/
		value: null
	},
	events: {
		/**
			Fires when one of the DatePicker's fields is selected.

			_inEvent.name_ contains the name of the DatePicker that generated
			the event.

			_inEvent.value_ contains the current Date value of the control.
		*/
		onSelect: ""
	},
	create: function() {
		this.inherited(arguments);
		if (!this.locale){
			try {
				this.locale = enyo.g11n.currentLocale().getLocale();
			}
			catch(err) {
				this.locale = "en_us";
			}
		}
		this.initDefaults();
	},
	initDefaults: function() {
		var months;
		//Attempt to use the g11n lib (ie assume it is loaded)
		try {
			this._tf = new enyo.g11n.Fmts({locale:this.locale});
			months = this._tf.getMonthFields();
		}
		catch(err) {
			//Fall back to en_us as default
			months = ["Jan", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"];
		}

		this.setupPickers(this._tf ? this._tf.getDateFieldOrder() : 'mdy');

		this.dayHiddenChanged();
		this.monthHiddenChanged();
		this.yearHiddenChanged();

		//Fill month, year & day pickers with values
		var d = this.value = this.value || new Date();
		for (var i=0,m; (m=months[i]); i++) {
			this.$.monthPicker.createComponent({content: m, value:i, active: i==d.getMonth()});
		}

		var y = d.getFullYear();
		this.$.yearPicker.setSelected(y-this.minYear);
		this.$.year.setContent(y);

		for (i=1; i<=this.monthLength(d.getYear(), d.getMonth()); i++) {
			this.$.dayPicker.createComponent({content:i, value:i, active: i==d.getDate()});
		}
	},
	monthLength: function(inYear, inMonth) {
		// determine number of days in a particular month/year
		return 32 - new Date(inYear, inMonth, 32).getDate();
	},
	setupYear: function(inSender, inEvent) {
		this.$.year.setContent(this.minYear+inEvent.index);
	},
	setupPickers: function(ordering) {
		var orderingArr = ordering.split("");
		var o,f,l;
		for(f = 0, l = orderingArr.length; f < l; f++) {
			o = orderingArr[f];
			switch (o){
				case 'd': this.createDay();
				break;
				case 'm': this.createMonth();
				break;
				case 'y': this.createYear();
				break;
				default: break;
			}
		}
	},
	createYear: function() {
		var yearCount = this.maxYear - this.minYear;
		this.createComponent(
			{kind: "onyx.PickerDecorator", onSelect: "updateYear", components: [
				{classes:"onyx-datepicker-year", name: "yearPickerButton",  disabled: this.disabled},
				{name: "yearPicker", kind: "onyx.FlyweightPicker", count: ++yearCount, onSetupItem: "setupYear", components: [
					{name: "year"}
				]}
			]}
		);
	},
	createMonth: function() {
		this.createComponent(
			{kind: "onyx.PickerDecorator", onSelect: "updateMonth", components: [
				{classes:"onyx-datepicker-month", name: "monthPickerButton",  disabled: this.disabled},
				{name: "monthPicker", kind: "onyx.Picker"}
			]}
		);
	},
	createDay: function() {
		this.createComponent(
			{kind: "onyx.PickerDecorator", onSelect: "updateDay", components: [
				{classes:"onyx-datepicker-day", name: "dayPickerButton",  disabled: this.disabled},
				{name: "dayPicker", kind: "onyx.Picker"}
			]}
		);
	},
	localeChanged: function() {
		this.refresh();
	},
	dayHiddenChanged: function() {
		this.$.dayPicker.getParent().setShowing(this.dayHidden ? false : true);
	},
	monthHiddenChanged: function() {
		this.$.monthPicker.getParent().setShowing(this.monthHidden ? false : true);
	},
	yearHiddenChanged: function() {
		this.$.yearPicker.getParent().setShowing(this.yearHidden ? false : true);
	},
	minYearChanged: function() {
		this.refresh();
	},
	maxYearChanged: function() {
		this.refresh();
	},
	valueChanged: function(){
		this.refresh();
	},
	disabledChanged: function() {
		this.yearPickerButton.setDisabled(this.disabled);
		this.monthPickerButton.setDisabled(this.disabled);
		this.dayPickerButton.setDisabled(this.disabled);
	},
	updateDay: function(inSender, inEvent){
		var date = this.calcDate(this.value.getFullYear(),
								this.value.getMonth(),
								inEvent.selected.value);
		this.doSelect({name:this.name, value:date});
		this.setValue(date);
	},
	updateMonth: function(inSender, inEvent){
		var date = this.calcDate(this.value.getFullYear(),
								inEvent.selected.value,
								this.value.getDate());
		this.doSelect({name:this.name, value:date});
		this.setValue(date);
	},
	updateYear: function(inSender, inEvent){
		var date = this.calcDate(this.minYear + inEvent.originator.selected,
								this.value.getMonth(),
								this.value.getDate());
		this.doSelect({name:this.name, value:date});
		this.setValue(date);
	},
	calcDate: function(year, month, day){
		return new Date(year,month,day,
						this.value.getHours(),
						this.value.getMinutes(),
						this.value.getSeconds(),
						this.value.getMilliseconds());
	},
	refresh: function(){
		this.destroyClientControls();
		this.initDefaults();
		this.render();
	}
});
<|endoftext|>


<commit_before>(function () {
  'use strict';

  angular.module('exceptionless.stacks')
    .factory('stacksActionsService', ['$ExceptionlessClient', 'dialogService', 'stackService', 'notificationService', function ($ExceptionlessClient, dialogService, stackService, notificationService) {
      var source = 'exceptionless.stacks.stacksActionsService';

      var deleteAction = {
        name: 'Delete',
        run: function (ids) {
          $ExceptionlessClient.createFeatureUsage(source + '.delete').setProperty('count', ids.length).submit();
          return dialogService.confirmDanger('Are you sure you want to delete these stacks?', 'DELETE STACKS').then(function () {
            function onSuccess() {
              notificationService.success('Successfully deleted the stacks.');
            }

            function onFailure() {
              $ExceptionlessClient.createFeatureUsage(source + '.delete.error').setProperty('count', ids.length).submit();
              notificationService.error('An error occurred while deleting the stacks.');
            }

            return stackService.remove(ids.join(',')).then(onSuccess, onFailure);
          });
        }
      };

      var markFixedAction = {
        name: 'Mark Fixed',
        run: function (ids) {
          function onSuccess() {
            notificationService.success('Successfully marked stacks as fixed.');
          }

          function onFailure() {
            $ExceptionlessClient.createFeatureUsage(source + '.mark-fixed.error').setProperty('count', ids.length).submit();
            notificationService.error('An error occurred while marking stacks as fixed.');
          }

          $ExceptionlessClient.createFeatureUsage(source + '.mark-fixed').setProperty('count', ids.length).submit();
          return stackService.markFixed(ids.join(',')).then(onSuccess, onFailure);
        }
      };

      var markNotFixedAction = {
        name: 'Mark Not Fixed',
        run: function (ids) {
          function onSuccess() {
            notificationService.success('Successfully marked stacks as not fixed.');
          }

          function onFailure() {
            $ExceptionlessClient.createFeatureUsage(source + '.mark-not-fixed.error').setProperty('count', ids.length).submit();
            notificationService.error('An error occurred while marking stacks as not fixed.');
          }

          $ExceptionlessClient.createFeatureUsage(source + '.mark-not-fixed').setProperty('count', ids.length).submit();
          return stackService.markNotFixed(ids.join(',')).then(onSuccess, onFailure);
        }
      };

      var markHiddenAction = {
        name: 'Mark Hidden',
        run: function (ids) {
          function onSuccess() {
            notificationService.success('Successfully marked stacks as hidden.');
          }

          function onFailure() {
            $ExceptionlessClient.createFeatureUsage(source + '.mark-hidden.error').setProperty('count', ids.length).submit();
            notificationService.error('An error occurred while marking stacks as hidden.');
          }

          $ExceptionlessClient.createFeatureUsage(source + '.mark-hidden').setProperty('count', ids.length).submit();
          return stackService.markHidden(ids.join(',')).then(onSuccess, onFailure);
        }
      };

      var markNotHiddenAction = {
        name: 'Mark Not Hidden',
        run: function (ids) {
          function onSuccess() {
            notificationService.success('Successfully marked stacks as not hidden.');
          }

          function onFailure() {
            $ExceptionlessClient.createFeatureUsage(source + '.mark-not-hidden.error').setProperty('count', ids.length).submit();
            notificationService.error('An error occurred while marking stacks as not hidden.');
          }

          $ExceptionlessClient.createFeatureUsage(source + '.mark-not-hidden').setProperty('count', ids.length).submit();
          return stackService.markNotHidden(ids.join(',')).then(onSuccess, onFailure);
        }
      };

      function getActions() {
        return [markFixedAction, markNotFixedAction, markHiddenAction, markNotHiddenAction, deleteAction];
      }

      var service = {
        getActions: getActions
      };

      return service;
    }]);
}());
<commit_msg>Fixed #35<commit_after>(function () {
  'use strict';

  angular.module('exceptionless.stacks')
    .factory('stacksActionsService', ['$ExceptionlessClient', 'dialogService', 'stackService', 'notificationService', '$q', function ($ExceptionlessClient, dialogService, stackService, notificationService, $q) {
      var source = 'exceptionless.stacks.stacksActionsService';

      function executeAction(ids, action, onSuccess, onFailure) {
        var deferred = $q.defer();
        var promise = _.chunk(ids, 10).reduce(function (previous, item) {
          return previous.then(action(item.join(',')));
        }, deferred.promise).then(onSuccess, onFailure);

        deferred.resolve();
        return promise;
      }

      var deleteAction = {
        name: 'Delete',
        run: function (ids) {
          $ExceptionlessClient.createFeatureUsage(source + '.delete').setProperty('count', ids.length).submit();
          return dialogService.confirmDanger('Are you sure you want to delete these stacks?', 'DELETE STACKS').then(function () {
            function onSuccess() {
              notificationService.success('Successfully deleted the stacks.');
            }

            function onFailure() {
              $ExceptionlessClient.createFeatureUsage(source + '.delete.error').setProperty('count', ids.length).submit();
              notificationService.error('An error occurred while deleting the stacks.');
            }

            return executeAction(ids, stackService.remove, onSuccess, onFailure);
          });
        }
      };

      var markFixedAction = {
        name: 'Mark Fixed',
        run: function (ids) {
          function onSuccess() {
            notificationService.success('Successfully marked stacks as fixed.');
          }

          function onFailure() {
            $ExceptionlessClient.createFeatureUsage(source + '.mark-fixed.error').setProperty('count', ids.length).submit();
            notificationService.error('An error occurred while marking stacks as fixed.');
          }

          $ExceptionlessClient.createFeatureUsage(source + '.mark-fixed').setProperty('count', ids.length).submit();
          return executeAction(ids, stackService.markFixed, onSuccess, onFailure);
        }
      };

      var markNotFixedAction = {
        name: 'Mark Not Fixed',
        run: function (ids) {
          function onSuccess() {
            notificationService.success('Successfully marked stacks as not fixed.');
          }

          function onFailure() {
            $ExceptionlessClient.createFeatureUsage(source + '.mark-not-fixed.error').setProperty('count', ids.length).submit();
            notificationService.error('An error occurred while marking stacks as not fixed.');
          }

          $ExceptionlessClient.createFeatureUsage(source + '.mark-not-fixed').setProperty('count', ids.length).submit();
          return executeAction(ids, stackService.markNotFixed, onSuccess, onFailure);
        }
      };

      var markHiddenAction = {
        name: 'Mark Hidden',
        run: function (ids) {
          function onSuccess() {
            notificationService.success('Successfully marked stacks as hidden.');
          }

          function onFailure() {
            $ExceptionlessClient.createFeatureUsage(source + '.mark-hidden.error').setProperty('count', ids.length).submit();
            notificationService.error('An error occurred while marking stacks as hidden.');
          }

          $ExceptionlessClient.createFeatureUsage(source + '.mark-hidden').setProperty('count', ids.length).submit();
          return executeAction(ids, stackService.markHidden, onSuccess, onFailure);
        }
      };

      var markNotHiddenAction = {
        name: 'Mark Not Hidden',
        run: function (ids) {
          function onSuccess() {
            notificationService.success('Successfully marked stacks as not hidden.');
          }

          function onFailure() {
            $ExceptionlessClient.createFeatureUsage(source + '.mark-not-hidden.error').setProperty('count', ids.length).submit();
            notificationService.error('An error occurred while marking stacks as not hidden.');
          }

          $ExceptionlessClient.createFeatureUsage(source + '.mark-not-hidden').setProperty('count', ids.length).submit();
          return executeAction(ids, stackService.markNotHidden, onSuccess, onFailure);
        }
      };

      function getActions() {
        return [markFixedAction, markNotFixedAction, markHiddenAction, markNotHiddenAction, deleteAction];
      }

      var service = {
        getActions: getActions
      };

      return service;
    }]);
}());
<|endoftext|>


<commit_before>function runTest()
{
    FBTest.openNewTab(basePath + "console/breakOnError/breakOnError.html", function(win)
    {
        FBTest.enablePanels(["console", "script"], function()
        {
            FBTest.waitForBreakInDebugger(null, 28, false, function(row)
            {
                // Resume debugger.
                FBTest.clickContinueButton();

                // 5) Finish test.
                FBTest.testDone();
            });

            FBTest.progress("activated break on next");

            FBTest.clickBreakOnNextButton(null, function()
            {
                var testButton = win.document.getElementById("testButton");
                testButton.addEventListener("click", function verifyClick()
                {
                    FBTest.progress("testButton was clicked");
                    testButton.removeEventListener("click", verifyClick, true);
                }, true);

                FBTest.progress("now click the testButton");
                FBTest.click(testButton);
            });
        });
    });
}
<commit_msg>FBTest: fix test (line number)<commit_after>function runTest()
{
    FBTest.openNewTab(basePath + "console/breakOnError/breakOnError.html", function(win)
    {
        FBTest.enablePanels(["console", "script"], function()
        {
            FBTest.waitForBreakInDebugger(null, 26, false, function(row)
            {
                // Resume debugger.
                FBTest.clickContinueButton();

                // 5) Finish test.
                FBTest.testDone();
            });

            FBTest.progress("activated break on next");

            FBTest.clickBreakOnNextButton(null, function()
            {
                var testButton = win.document.getElementById("testButton");
                testButton.addEventListener("click", function verifyClick()
                {
                    FBTest.progress("testButton was clicked");
                    testButton.removeEventListener("click", verifyClick, true);
                }, true);

                FBTest.progress("now click the testButton");
                FBTest.click(testButton);
            });
        });
    });
}
<|endoftext|>