<commit_before>//localStorage.clear();

const Todos = Todo.loadAllItems();

function todoAddNew (dom, e) {
    let title = e.target.value.trim();

    if (title==='')
        alert("A reminder to do nothing? I like it! We all need to remember to slow things down from time to time. But, no.")
    else
        Todos.itemsRaw = Todos.itemsRaw.concat( new Todo( {title: title}));

    // constructor will have written Todo to localStorage
    e.target.value = null;
}

function todoMVC() {
    return div({}, c => {
        return [
            section({ class: "todoapp", name: "todoapp"}
                , c => { return [
                        button("Bam", {onclick: 'localStorage.clear();'})
                    , h1("todos3")
                        , header({class: "header"}
                            , c => [input({
                                        class: "new-todo"
                                        , placeholder: "What needs doing?"
                                        , autofocus: true
                                        , onchange: 'todoAddNew'})])

                        , section({class: "main"
                                , name: "mainsection"
                                , hidden: cF( c => Todos.items.length===0)}, c => [
                            labelx( { content: cF( c => c.md.optio)
                                    , optio: cF( c => (Todos.items.length===0) ? "na"
                                                    : (Todos.items.every( i => i.completed) ? "undo" : "done")
                                                , {observer: obsDbg})
                                    , onclick: 'toggleAllCompleted'})
                            /* input({id: "toggle-all"
                                    , class: "toggle-all"
                                    , type: "checkbox"
                                    , onclick: 'toggleAllComplete'})
                                , label("Mark all as completed"
                                        , {for: "toggle-all"
                                        , checked: cF( c => Todo.items && Todo.items.every( i => i.completed)
                                                    , {observer: obsDbg})
                                        , class: cF( c=> c.md.checked? "checked":""
                                                    , {observer: obsDbg})
                                        , onclick: 'toggleAllCompleted'})*/

                            , ul({class: "todo-list", name: "todo-list"}
                                    , c =>  todoLines( c, Todos.items))])
                            , todoFooter(c)]
                })
            , footer({class: "info"}
                , c => [p({}, 'Double-click to edit a todo')
                        , p({}, 'Created by... Kenneth Tilton')
                        , p({}, 'Part of TodoMVC')])]
    })
}

// todo leverage classList handling

function toggleAllCompleted (dom,e) {
    let md = jsDom[dom.id]
        , newCompleted = (md.optio==="done" ? Date.now():null);

    clg('toggle all compl applies ' + md.optio);

    Todos.items.map( td => td.completed = newCompleted);
}

function todoLines( c, items ) {
    let plis = c.pv;
    // todo generalize this optimization
    return items.map( todo => {
        plix = (plis === kUnbound) ? -1 : plis.findIndex(pli => pli.todo === todo);
        if (plix !== -1) {
            return plis[plix];
        } else {
            let selector = c.md.fmUp('filters');
            ast(selector, "Filters not found");

            return li({ todo: todo
                    , class: cF(c => (todo.completed ? "completed" : ""))
                    , display: cF(c => todoMatchesSelect(todo, selector.selection) ? "block" : "none")}
                , c => [div({class: "view"}, c => [
                            input({class: "toggle"
                                    , type: "checkbox", checked: true
                                    , onclick: 'todoToggleComplete'})
                            , labelx({content: cF( c=> { clg('lbl sees title '+ todo.title);
                                                        return todo.title}
                                                        , {observer: obsContentToDom})
                                    , todo: todo
                                    , ondblclick: 'todoStartEditing'})
                            , button(null, {
                                class: "destroy"
                                , onclick: 'todoDelete'})])
                        , input({name: "myEditor"
                            , class: "edit"
                            , todo: todo
                            , value: cF( c => todo.title)
                            , onkeydown: 'todoEdit'
                            , onkeypress: 'todoEdit'})])}})

}

function obsContentToDom ( slot, me, newv, priorv, c) {
    clg('contentto dom!!!! '+newv);
    if (priorv !== kUnbound) {

        me.dom.innerHTML = newv;
    }
}
// stick todo in more places to reduce navigation

function todoStartEditing (dom,e) {
    //clg('start edit!!!!');

    let md = jsDom[dom.id]
        , li = md.fmTag('li', 'myLi');

    // todo resolve redundancy of upp v insidep v mep
    let edt = li.fm('myEditor',{upp: false, insidep: true, mep: false}, 'edt');
    ast(edt);
    edt.dom.li = li;
    li.dom.classList.add("editing");
    edt.dom.focus();
    edt.dom.value = edt.dom.value; // hack to put insertion point at end of text
}
function todoEdit ( edtdom, e) {
    // clg(`edit!!!! ${e.type} key ${e.key} li=${edt.li}`);
    switch (e.key) {
        case 'Escape':
            edtdom.li.dom.classList.remove('editing');
            break;
        case 'Enter':
            clg(`enter val ${edtdom.value} for ${edtdom.li.todo.title}`);
            edtdom.li.todo.title = edtdom.value;
            edtdom.li.dom.classList.remove('editing');
            break;
    }
}

function todoMatchesSelect( todo, selection) {
    return selection==='All'
        || (selection==='Completed' && todo.completed)
        || (selection==='Active' && !todo.completed);
}

function todoToggleComplete (dom, e) {
    let md = jsDom[dom.id] // find the "shadow" JS object matching the event dom
        , li = md.fmTag('li');
    li.todo.completed = (li.todo.completed ? null : Date.now());
}

function todoDelete (dom, e) {
    let md = jsDom[dom.id] // find the "shadow" JS object matching the event dom
        , li = md.fmTag('li'); // now navigate to its containing li
    li.todo.deleted = Date.now(); // Bam!
}

function todosReselect (dom, e) {
    let li = jsDom[dom.id]; // find the "mirroe" JS object matching the actual dom element
    // todo: why the content and not the li?
    li.fmTag('ul').selection = li.content;
}

// --- footer -------------------------------------------------------------

function todoFooter (c) {
    return footer({class: "footer"
                   , hidden: cF( c => Todos.items.length===0)}
        , c => [
            span({ class: "todo-count"
                , content: cF(c => {
                        let remCt = Todos.items.filter(todo => !todo.completed).length;
                        return `<strong>${remCt}</strong> item${remCt === 1 ? '' : 's'} remaining`;})})
            , ul( {class: "filters"
                    , name: "filters"
                    , selection: cI("All")}
                , c => ["All", "Active","Completed"].map( which =>
                    li({}, c=> [a({content: which
                                    , selected: cF( c => c.md.content === c.md.fmTag('ul').selection)
                                    , class: cF( c => c.md.selected ? "selected":"")
                                    , onclick: 'todosReselect'})])))
            , button("Clear completed", {
                class: "clear-completed"
                , disabled: cF(c => Todos.items.filter(todo => todo.completed).length === 0)
                , hidden: cF( c=> c.md.disabled )
                , onclick: 'todoCompletedClear'})])
}

function todoCompletedClear( dom, e) {
    Todos.items.filter( td => td.completed ).map( td => td.deleted = Date.now());
}

<commit_msg>backup<commit_after>//localStorage.clear();

const Todos = Todo.loadAllItems();

function todoAddNew (dom, e) {
    let title = e.target.value.trim();

    if (title==='')
        alert("A reminder to do nothing? I like it! We all need to remember to slow things down from time to time. But, no.")
    else
        Todos.itemsRaw = Todos.itemsRaw.concat( new Todo( {title: title}));

    // constructor will have written Todo to localStorage
    e.target.value = null;
}

function todoMVC() {
    return div({}, c => {
        return [
            section({ class: "todoapp", name: "todoapp"}
                , c => { return [
                        button("Bam", {onclick: 'localStorage.clear();'})
                    , h1("todos3")
                        , header({class: "header"}
                            , c => [input({
                                        class: "new-todo"
                                        , placeholder: "What needs doing?"
                                        , autofocus: true
                                        , onchange: 'todoAddNew'})])

                        , section({class: "main"
                                , name: "mainsection"
                                , hidden: cF( c => Todos.items.length===0)}, c => [
                            labelx( { content: cF( c => c.md.optio)
                                    , optio: cF( c => (Todos.items.length===0) ? "na"
                                                    : (Todos.items.every( i => i.completed) ? "undo" : "done")
                                                , {observer: obsDbg})
                                    , onclick: 'toggleAllCompleted'})
                            /* input({id: "toggle-all"
                                    , class: "toggle-all"
                                    , type: "checkbox"
                                    , onclick: 'toggleAllComplete'})
                                , label("Mark all as completed"
                                        , {for: "toggle-all"
                                        , checked: cF( c => Todo.items && Todo.items.every( i => i.completed)
                                                    , {observer: obsDbg})
                                        , class: cF( c=> c.md.checked? "checked":""
                                                    , {observer: obsDbg})
                                        , onclick: 'toggleAllCompleted'})*/

                            , ul({class: "todo-list", name: "todo-list"}
                                    , c =>  todoLines( c, Todos.items))])
                            , todoFooter(c)]
                })
            , footer({class: "info"}
                , c => [p({}, 'Double-click to edit a todo')
                        , p({}, 'Created by... Kenneth Tilton')
                        , p({}, 'Part of TodoMVC')])]
    })
}

// todo leverage classList handling

function toggleAllCompleted (dom,e) {
    let md = jsDom[dom.id]
        , newCompleted = (md.optio==="done" ? Date.now():null);

    clg('toggle all compl applies ' + md.optio);

    Todos.items.map( td => td.completed = newCompleted);
}

function todoLines( c, items ) {
    let plis = c.pv;
    // todo generalize this optimization
    return items.map( todo => {
        plix = (plis === kUnbound) ? -1 : plis.findIndex(pli => pli.todo === todo);
        if (plix !== -1) {
            return plis[plix];
        } else {
            let selector = c.md.fmUp('filters');
            ast(selector, "Filters not found");

            return li({ todo: todo
                    , class: cF(c => (todo.completed ? "completed" : ""))
                    , display: cF(c => todoMatchesSelect(todo, selector.selection) ? "block" : "none")}
                , c => [div({class: "view"}, c => [
                            input({class: "toggle"
                                    , type: "checkbox", checked: true
                                    , onclick: 'todoToggleComplete'})
                            , labelx({content: cF( c=> { clg('lbl sees title '+ todo.title);
                                                        return todo.title}
                                                        , {observer: obsContentToDom})
                                    , todo: todo
                                    , ondblclick: 'todoStartEditing'})
                            , button(null, {
                                class: "destroy"
                                , onclick: 'todoDelete'})])
                        , input({name: "myEditor"
                            , class: "edit"
                            , todo: todo
                            , value: cF( c => todo.title)
                            , onkeydown: 'todoEdit'
                            , onkeypress: 'todoEdit'})])}})

}

function obsContentToDom ( slot, me, newv, priorv, c) {
    if (priorv !== kUnbound) {
        me.dom.innerHTML = newv;
    }
}
// stick todo in more places to reduce navigation

function todoStartEditing (dom,e) {
    let md = jsDom[dom.id]
        , li = md.fmTag('li', 'myLi');

    // todo resolve redundancy of upp v insidep v mep
    let edt = li.fm('myEditor',{upp: false, insidep: true, mep: false}, 'edt');
    ast(edt);
    edt.dom.li = li;
    li.dom.classList.add("editing");
    edt.dom.focus();
    edt.dom.value = edt.dom.value; // hack to put insertion point at end of text
}
function todoEdit ( edtdom, e) {
    switch (e.key) {
        case 'Escape':
            edtdom.li.dom.classList.remove('editing');
            break;

        case 'Enter':
            edtdom.li.todo.title = edtdom.value;
            edtdom.li.dom.classList.remove('editing');
            break;
    }
}

function todoMatchesSelect( todo, selection) {
    return selection==='All'
        || (selection==='Completed' && todo.completed)
        || (selection==='Active' && !todo.completed);
}

function todoToggleComplete (dom, e) {
    let li = jsDom[dom.id].fmTag('li');
    li.todo.completed = (li.todo.completed ? null : Date.now());
}

function todoDelete (dom, e) {
    let li = jsDom[dom.id].fmTag('li');
    li.todo.deleted = Date.now(); // Bam!
}

function todosReselect (dom, e) {
    let li = jsDom[dom.id]; // find the "mirroe" JS object matching the actual dom element
    // todo: why the content and not the li?
    li.fmTag('ul').selection = li.content;
}

// --- footer -------------------------------------------------------------

function todoFooter (c) {
    return footer({class: "footer"
                   , hidden: cF( c => Todos.items.length===0)}
        , c => [
            span({ class: "todo-count"
                , content: cF(c => {
                        let remCt = Todos.items.filter(todo => !todo.completed).length;
                        return `<strong>${remCt}</strong> item${remCt === 1 ? '' : 's'} remaining`;})})
            , ul( {class: "filters"
                    , name: "filters"
                    , selection: cI("All")}
                , c => ["All", "Active","Completed"].map( which =>
                    li({}, c=> [a({content: which
                                    , selected: cF( c => c.md.content === c.md.fmTag('ul').selection)
                                    , class: cF( c => c.md.selected ? "selected":"")
                                    , onclick: 'todosReselect'})])))
            , button("Clear completed", {
                class: "clear-completed"
                , disabled: cF(c => Todos.items.filter(todo => todo.completed).length === 0)
                , hidden: cF( c=> c.md.disabled )
                , onclick: 'todoCompletedClear'})])
}

function todoCompletedClear( dom, e) {
    Todos.items.filter( td => td.completed ).map( td => td.deleted = Date.now());
}

<|endoftext|>


<commit_before>(function() { // IIFE to avoid exposure in global scope.

  'use strict'

  angular
    .module("bzD3")
    .directive('bzD3Panel', bzD3Panel);

  bzD3Panel.$inject = ['d3Service', '$window'];

  function bzD3Panel(bzD3, $window) {
    return {
      restrict: 'EA',
      template: '

',
      transclude: true,

      scope: {
        content: '=', // Isolated bidirectional binding.
        draw:    '='  // Drawing function from user.
      },

      link: function(scope,element,attrs) {
        bzD3.d3().then(function(d3) {
          var margin  = parseInt(attrs.margin)  || 20;
          var height  = parseInt(attrs.height)  || 50;
          var padding = parseInt(attrs.padding) || 5;

          var svg = d3.select(element[0])
                      .insert('svg',':first-child')
                      .style('height', attrs.height)
                      .style('width', '100%');

          $window.onresize = function() {
            scope.$apply;
          };

          // Redraw when the size changes.
          scope.$watch(function() {
            return element[0].firstElementChild.clientWidth;
            // return angular.element($window)[0].innerWidth;
          }, function() {
            if(scope.content) {
              scope.render(scope.content.data);
            }
          });

          // Redraw when the data changes.
          scope.$watch('content', function(newVals,oldVals) {
            if(scope.content) {
              return scope.render(scope.content.data);
            }
          }, true);

          scope.defaultDraw = function(d3, svg, data, element, attrs) {
            svg.style('stroke-width', '0px')
               .style('background-color', '#bf8ea6')
               .style('height', attrs.height)
               .style('width', '100%');

            var g = svg.selectAll("g")
                       .data(data).enter().append("g");
            g.append("circle")
             .style("fill", "red")
             .style("stroke", "black")
             .style("stroke-width", "2")
             .attr("cx",45)
             .attr("cy",45)
             .attr("r",40);
            g.append("text")
             .attr("x",10)
             .attr("y",40)
             .text("LOL WUT");
          }

          // Rendering function.  The fun happens here.  :)
          scope.render = function(data) {
            if(!scope.draw) {
              var novalue = [0];
              scope.defaultDraw(d3, svg, novalue, element, attrs);
            } else {
              if(data) {
                scope.draw(d3, svg, data, element, attrs);
              }
            }

          };

        });

      }};
  }

})(); // End of IIFE

<commit_msg>calculate width and height from parent element and make available in attrs<commit_after>(function() { // IIFE to avoid exposure in global scope.

  'use strict'

  angular
    .module("bzD3")
    .directive('bzD3Panel', bzD3Panel);

  bzD3Panel.$inject = ['d3Service', '$window'];

  function bzD3Panel(bzD3, $window) {
    return {
      restrict: 'EA',
      template: '

',
      transclude: true,

      scope: {
        content: '=', // Isolated bidirectional binding.
        draw:    '='  // Drawing function from user.
      },

      link: function(scope,element,attrs) {
        bzD3.d3().then(function(d3) {
          var margin  = parseInt(attrs.margin)  || 20;
          var padding = parseInt(attrs.padding) || 5;

          var height;
          if(attrs.height) {
            height  = parseInt(attrs.height);
          } else {
            height = $(element).parent().height();
            attrs.height = height;
          }

          var width;
          if(attrs.width) {
            width = parseInt(attrs.width);
          } else {
            width = $(element).parent().width();
            attrs.width = width;
          }

          var svg = d3.select(element[0])
                      .insert('svg',':first-child')
                      .style('height', height)
                      .style('width', width);

          $window.onresize = function() {
            scope.$apply;
          };

          // Redraw when the size changes.
          scope.$watch(function() {
            return element[0].firstElementChild.clientWidth;
            // return angular.element($window)[0].innerWidth;
          }, function() {
            if(scope.content) {
              scope.render(scope.content);
            }
          });

          // Redraw when the data changes.
          scope.$watchCollection('content', function(newVals,oldVals) {
            if(scope.content) {
              return scope.render(scope.content);
            }
          }, true);

          scope.defaultDraw = function(d3, svg, data, element, attrs) {
            svg.style('stroke-width', '0px')
               .style('background-color', '#bf8ea6');

            var g = svg.selectAll("g")
                       .data(data).enter().append("g");
            g.append("circle")
             .style("fill", "red")
             .style("stroke", "black")
             .style("stroke-width", "2")
             .attr("cx",width/2)
             .attr("cy",height/2)
             .attr("r",40);
            g.append("text")
             .attr("x",(width/2)-30)
             .attr("y",(height/2) - 10)
             .text("LOL WUT");
          }

          // Rendering function.  The fun happens here.  :)
          scope.render = function(data) {
            if(!scope.draw) {
              var novalue = [0];
              scope.defaultDraw(d3, svg, novalue, element, attrs);
            } else {
              if(data) {
                scope.draw(d3, svg, data, element, attrs);
              }
            }

          };

        });

      }};
  }

})(); // End of IIFE

<|endoftext|>


<commit_before>import angular from 'angular'
import uiBootstrap from 'angular-ui-bootstrap'

// ===================================================================

export default angular.module('xoWebApp.genericModal', [
  uiBootstrap
])
  .controller('GenericModalCtrl', function ($scope, $modalInstance, options) {
    $scope.title = options.title
    $scope.message = options.message

    $scope.yesButtonLabel = options.yesButtonLabel || 'Ok'
    $scope.noButtonLabel = options.noButtonLabel
  })
  .service('modal', function ($modal) {
    return {
      confirm: function (opts) {
        const modal = $modal.open({
          controller: 'GenericModalCtrl',
          template: require('./view'),
          resolve: {
            options: function () {
              return {
                title: opts.title,
                message: opts.message,
                noButtonLabel: 'Cancel'
              }
            }
          }
        })

        return modal.result
      }
    }
  })

  // A module exports its name.
  .name
<commit_msg>modal service: new alert() method.<commit_after>import angular from 'angular'
import uiBootstrap from 'angular-ui-bootstrap'

import template from './view'

// ===================================================================

export default angular.module('xoWebApp.genericModal', [
  uiBootstrap
])
  .controller('GenericModalCtrl', function ($scope, $modalInstance, options) {
    $scope.title = options.title
    $scope.message = options.message

    $scope.yesButtonLabel = options.yesButtonLabel || 'Ok'
    $scope.noButtonLabel = options.noButtonLabel
  })
  .service('modal', function ($modal) {
    return {
      alert: ({ title, message }) => $modal.open({
        controller: 'GenericModalCtrl',
        template,
        resolve: {
          title: title,
          message: message
        }
      }).result,
      confirm: function (opts) {
        const modal = $modal.open({
          controller: 'GenericModalCtrl',
          template,
          resolve: {
            options: function () {
              return {
                title: opts.title,
                message: opts.message,
                noButtonLabel: 'Cancel'
              }
            }
          }
        })

        return modal.result
      }
    }
  })

  // A module exports its name.
  .name
<|endoftext|>


<commit_before>'use strict';

var Ractive = require('lib/ractive');
var emitter = require('lib/emitter');
var getWallet = require('lib/wallet').getWallet;
var denomination = require('lib/denomination');
var getTokenNetwork = require('lib/token').getTokenNetwork;
var shapeshift = require('lib/shapeshift');
var qrcode = require('lib/qrcode');
var geo = require('lib/geo');
var showTooltip = require('widgets/modals/tooltip');
var showError = require('widgets/modals/flash').showError;
var showInfo = require('widgets/modals/flash').showInfo;
var _ = require('lodash');
var db = require('lib/db');

module.exports = function(el) {
  var ractive = new Ractive({
    el: el,
    template: require('./index.ract'),
    data: {
      isLoading: true,
      isLogged: shapeshift.isLogged(),
      isLoadingRate: true,
      qrScannerAvailable: qrcode.isScanAvailable,
      isValidating: false,
      fromSymbol: '',
      returnAddress: '',
      toAddress: '',
      toSymbol: '',
      rate: '?',
      coins: [],
      isGeoEnabled: function(symbol) {
        return Object.keys(geo.networks).indexOf(symbol) !== -1;
      }
    },
    partials: {
      loader: require('../loader.ract'),
      footer: require('../footer.ract')
    }
  });

  ractive.on('login', function() {
    shapeshift.login().then(function() {
      ractive.set('isLogged', true);
    }).catch(function(err) {
      if (err.message === 'user_is_not_verified') {
        return showInfo({
          message: 'Your ShapeShift account is not verified.',
          href: 'https://auth.shapeshift.io',
          linkText: 'Complete verification'
        })
      }
    });
  });

  ractive.on('logout', function() {
    shapeshift.logout().then(function() {
      ractive.set('isLogged', false);
    });
  });

  var fromSymbolObserver = ractive.observe('fromSymbol', function(symbol, old) {
    if (!old) return;
    if (symbol === ractive.get('toSymbol')) {
      return ractive.set('toSymbol', old);
    }
    return getRate();
  });

  ractive.observe('toSymbol', function(symbol, old) {
    if (!old) return;
    if (symbol === ractive.get('fromSymbol')) {
      return ractive.set('fromSymbol', old);
    }
    return getRate();
  });

  ractive.on('before-show', function() {
    shapeshift.getCoins().then(function(coins) {
      ractive.set('isLoading', false);
      ractive.set('coins', coins);

      fromSymbolObserver.silence();
      ractive.set('fromSymbol', denomination(getTokenNetwork()));
      fromSymbolObserver.resume();

      var fromSymbol = ractive.get('fromSymbol');
      if (fromSymbol === ractive.get('toSymbol')) {
        var symbol = getFirstEnabledSymbol(coins, fromSymbol);
        ractive.set('toSymbol', symbol);
      } else {
        return getRate();
      }
    }).catch(function(err) {
      console.error(err);
      return showError({message: err.message});
    });
  });

  ractive.on('before-hide', function() {
    ractive.set('isLoading', true);
  });

  ractive.on('clearAddress', function(context) {
    var dataContext = context.node.getAttribute('data-context');
    if (dataContext === 'exchange-to-address') {
      ractive.set('toAddress', '');
      ractive.find('#exchange_to_address').focus();
    } else if (dataContext === 'exchange-return-address') {
      ractive.set('returnAddress', '');
      ractive.find('#exchange_return_address').focus();
    }
  });

  ractive.on('open-geo', function(context) {
    var dataContext = context.node.getAttribute('data-context');
    var data = {
      overlay: 'geo',
      context: dataContext,
    };

    if (dataContext === 'exchange-return-address') {
      data.network = geo.networks[ractive.get('fromSymbol')]
    } else if (dataContext === 'exchange-to-address') {
      data.network = geo.networks[ractive.get('toSymbol')]
    }
    emitter.emit('open-overlay', data);
  });

  ractive.on('open-qr', function(context) {
    qrcode.scan({
      context: context.node.getAttribute('data-context'),
      isEthereum: getTokenNetwork() === 'ethereum'
    });
  });

  emitter.on('prefill-wallet', function(address, context) {
    if (context === 'exchange-return-address') {
      ractive.set('returnAddress', address)
    } else if (context === 'exchange-to-address') {
      ractive.set('toAddress', address)
    }
  })

  ractive.on('help', function() {
    showTooltip({
      message: 'Return address should be an address controlled by you where ' +
      'deposit will be returned in the event of a failed transaction.'
    });
  });

  ractive.on('swap', function() {
    ractive.set('fromSymbol', ractive.get('toSymbol'));
    var returnAddress = ractive.get('returnAddress');
    ractive.set('returnAddress', ractive.get('toAddress'));
    ractive.set('toAddress', returnAddress);

    // Fix safari placeholder bug
    var returnAddressEl = ractive.find('#exchange_return_address');
    returnAddressEl.focus();
    returnAddressEl.blur();
    var toAddressEl = ractive.find('#exchange_to_address');
    toAddressEl.focus();
    toAddressEl.blur();
  });

  ractive.on('confirm', function() {
    if (ractive.get('rate') === '?') return showError({message: 'Exchange is currently unavailable for this pair'});
    var options = {
      fromSymbol: ractive.get('fromSymbol'),
      returnAddress: ractive.get('returnAddress'),
      toAddress: ractive.get('toAddress'),
      toSymbol: ractive.get('toSymbol')
    };
    var fromCoin = _.find(ractive.get('coins'), function(item) {
      return item.symbol === options.fromSymbol;
    });
    return validateAddresses(options).then(function() {
      return shapeshift.shift(options).then(function(data) {
        data.depositCoinName = fromCoin ? fromCoin.name : '';
        db.set('exchangeInfo', data).then(function() {
          ractive.set('isValidating', false);
          emitter.emit('change-exchange-step', 'awaitingDeposit', data);
        }).catch(function(err) {
          ractive.set('isValidating', false);
          console.error(err);
        });
      });
    }).catch(function(err) {
      ractive.set('isValidating', false);
      if (err.message === 'invalid_return_address') {
        return showError({message: 'Please enter a valid return address'});
      }
      if (err.message === 'invalid_to_address') {
        return showError({message: 'Please enter a valid address to send to'});
      }
      if (/Please use the precise/.test(err.message)) {
        return showError({message: 'Exchange is currently unavailable for this pair'});
      }
      if (/Invalid or Expired Authorization Token/.test(err.message)) {
        ractive.set('isLogged', false);
        shapeshift.cleanAccessToken();
        return showError({message: 'Try to sign in again'});
      }
      console.error(err.message);
      return showError({message: err.message});
    });
  });

  function validateAddresses(options) {
    ractive.set('isValidating', true);
    var promises = [];
    if (options.returnAddress) {
      promises.push(shapeshift.validateAddress(options.returnAddress, options.fromSymbol));
    } else {
      promises.push(Promise.resolve(true));
    }
    promises.push(shapeshift.validateAddress(options.toAddress, options.toSymbol));

    return Promise.all(promises).then(function(results) {
      if (!results[0]) throw new Error('invalid_return_address');
      if (!results[1]) throw new Error('invalid_to_address');
    });
  }

  emitter.on('wallet-ready', function() {
    if (!ractive.el.classList.contains('current')) {
      return ractive.set('returnAddress', getWallet().getNextAddress());
    }
    if (ractive.get('fromSymbol') === getWallet().denomination) {
      ractive.set('returnAddress', getWallet().getNextAddress());
    }
  });

  function getFirstEnabledSymbol(coins, ignoreSymbol) {
    var nextCoin = null;
    coins.some(function(coin) {
      if (!coin.disabled && coin.symbol !== ignoreSymbol) {
        nextCoin = coin;
        return true;
      }
    });
    return nextCoin ? nextCoin.symbol : nextCoin;
  }

  function getRate() {
    ractive.set('isLoadingRate', true);
    return shapeshift.marketInfo(ractive.get('fromSymbol'), ractive.get('toSymbol')).then(function(data) {
      var rate = data.rate;
      ractive.set('isLoadingRate', false);
      ractive.set('rate', rate);
    }).catch(function(err) {
      ractive.set('isLoadingRate', false);
      ractive.set('rate', '?');
      if (/Pair (.+) is currently unavailable/.test(err.message)) return // silence
      console.error(err);
      return showError({message: err.message});
    });
  }

  return ractive;
}
<commit_msg>Silence getRate error<commit_after>'use strict';

var Ractive = require('lib/ractive');
var emitter = require('lib/emitter');
var getWallet = require('lib/wallet').getWallet;
var denomination = require('lib/denomination');
var getTokenNetwork = require('lib/token').getTokenNetwork;
var shapeshift = require('lib/shapeshift');
var qrcode = require('lib/qrcode');
var geo = require('lib/geo');
var showTooltip = require('widgets/modals/tooltip');
var showError = require('widgets/modals/flash').showError;
var showInfo = require('widgets/modals/flash').showInfo;
var _ = require('lodash');
var db = require('lib/db');

module.exports = function(el) {
  var ractive = new Ractive({
    el: el,
    template: require('./index.ract'),
    data: {
      isLoading: true,
      isLogged: shapeshift.isLogged(),
      isLoadingRate: true,
      qrScannerAvailable: qrcode.isScanAvailable,
      isValidating: false,
      fromSymbol: '',
      returnAddress: '',
      toAddress: '',
      toSymbol: '',
      rate: '?',
      coins: [],
      isGeoEnabled: function(symbol) {
        return Object.keys(geo.networks).indexOf(symbol) !== -1;
      }
    },
    partials: {
      loader: require('../loader.ract'),
      footer: require('../footer.ract')
    }
  });

  ractive.on('login', function() {
    shapeshift.login().then(function() {
      ractive.set('isLogged', true);
    }).catch(function(err) {
      if (err.message === 'user_is_not_verified') {
        return showInfo({
          message: 'Your ShapeShift account is not verified.',
          href: 'https://auth.shapeshift.io',
          linkText: 'Complete verification'
        })
      }
    });
  });

  ractive.on('logout', function() {
    shapeshift.logout().then(function() {
      ractive.set('isLogged', false);
    });
  });

  var fromSymbolObserver = ractive.observe('fromSymbol', function(symbol, old) {
    if (!old) return;
    if (symbol === ractive.get('toSymbol')) {
      return ractive.set('toSymbol', old);
    }
    return getRate();
  });

  ractive.observe('toSymbol', function(symbol, old) {
    if (!old) return;
    if (symbol === ractive.get('fromSymbol')) {
      return ractive.set('fromSymbol', old);
    }
    return getRate();
  });

  ractive.on('before-show', function() {
    shapeshift.getCoins().then(function(coins) {
      ractive.set('isLoading', false);
      ractive.set('coins', coins);

      fromSymbolObserver.silence();
      ractive.set('fromSymbol', denomination(getTokenNetwork()));
      fromSymbolObserver.resume();

      var fromSymbol = ractive.get('fromSymbol');
      if (fromSymbol === ractive.get('toSymbol')) {
        var symbol = getFirstEnabledSymbol(coins, fromSymbol);
        ractive.set('toSymbol', symbol);
      } else {
        return getRate();
      }
    }).catch(function(err) {
      console.error(err);
      return showError({message: err.message});
    });
  });

  ractive.on('before-hide', function() {
    ractive.set('isLoading', true);
  });

  ractive.on('clearAddress', function(context) {
    var dataContext = context.node.getAttribute('data-context');
    if (dataContext === 'exchange-to-address') {
      ractive.set('toAddress', '');
      ractive.find('#exchange_to_address').focus();
    } else if (dataContext === 'exchange-return-address') {
      ractive.set('returnAddress', '');
      ractive.find('#exchange_return_address').focus();
    }
  });

  ractive.on('open-geo', function(context) {
    var dataContext = context.node.getAttribute('data-context');
    var data = {
      overlay: 'geo',
      context: dataContext,
    };

    if (dataContext === 'exchange-return-address') {
      data.network = geo.networks[ractive.get('fromSymbol')]
    } else if (dataContext === 'exchange-to-address') {
      data.network = geo.networks[ractive.get('toSymbol')]
    }
    emitter.emit('open-overlay', data);
  });

  ractive.on('open-qr', function(context) {
    qrcode.scan({
      context: context.node.getAttribute('data-context'),
      isEthereum: getTokenNetwork() === 'ethereum'
    });
  });

  emitter.on('prefill-wallet', function(address, context) {
    if (context === 'exchange-return-address') {
      ractive.set('returnAddress', address)
    } else if (context === 'exchange-to-address') {
      ractive.set('toAddress', address)
    }
  })

  ractive.on('help', function() {
    showTooltip({
      message: 'Return address should be an address controlled by you where ' +
      'deposit will be returned in the event of a failed transaction.'
    });
  });

  ractive.on('swap', function() {
    ractive.set('fromSymbol', ractive.get('toSymbol'));
    var returnAddress = ractive.get('returnAddress');
    ractive.set('returnAddress', ractive.get('toAddress'));
    ractive.set('toAddress', returnAddress);

    // Fix safari placeholder bug
    var returnAddressEl = ractive.find('#exchange_return_address');
    returnAddressEl.focus();
    returnAddressEl.blur();
    var toAddressEl = ractive.find('#exchange_to_address');
    toAddressEl.focus();
    toAddressEl.blur();
  });

  ractive.on('confirm', function() {
    if (ractive.get('rate') === '?') return showError({message: 'Exchange is currently unavailable for this pair'});
    var options = {
      fromSymbol: ractive.get('fromSymbol'),
      returnAddress: ractive.get('returnAddress'),
      toAddress: ractive.get('toAddress'),
      toSymbol: ractive.get('toSymbol')
    };
    var fromCoin = _.find(ractive.get('coins'), function(item) {
      return item.symbol === options.fromSymbol;
    });
    return validateAddresses(options).then(function() {
      return shapeshift.shift(options).then(function(data) {
        data.depositCoinName = fromCoin ? fromCoin.name : '';
        db.set('exchangeInfo', data).then(function() {
          ractive.set('isValidating', false);
          emitter.emit('change-exchange-step', 'awaitingDeposit', data);
        }).catch(function(err) {
          ractive.set('isValidating', false);
          console.error(err);
        });
      });
    }).catch(function(err) {
      ractive.set('isValidating', false);
      if (err.message === 'invalid_return_address') {
        return showError({message: 'Please enter a valid return address'});
      }
      if (err.message === 'invalid_to_address') {
        return showError({message: 'Please enter a valid address to send to'});
      }
      if (/Please use the precise/.test(err.message)) {
        return showError({message: 'Exchange is currently unavailable for this pair'});
      }
      if (/Invalid or Expired Authorization Token/.test(err.message)) {
        ractive.set('isLogged', false);
        shapeshift.cleanAccessToken();
        return showError({message: 'Try to sign in again'});
      }
      console.error(err.message);
      return showError({message: err.message});
    });
  });

  function validateAddresses(options) {
    ractive.set('isValidating', true);
    var promises = [];
    if (options.returnAddress) {
      promises.push(shapeshift.validateAddress(options.returnAddress, options.fromSymbol));
    } else {
      promises.push(Promise.resolve(true));
    }
    promises.push(shapeshift.validateAddress(options.toAddress, options.toSymbol));

    return Promise.all(promises).then(function(results) {
      if (!results[0]) throw new Error('invalid_return_address');
      if (!results[1]) throw new Error('invalid_to_address');
    });
  }

  emitter.on('wallet-ready', function() {
    if (!ractive.el.classList.contains('current')) {
      return ractive.set('returnAddress', getWallet().getNextAddress());
    }
    if (ractive.get('fromSymbol') === getWallet().denomination) {
      ractive.set('returnAddress', getWallet().getNextAddress());
    }
  });

  function getFirstEnabledSymbol(coins, ignoreSymbol) {
    var nextCoin = null;
    coins.some(function(coin) {
      if (!coin.disabled && coin.symbol !== ignoreSymbol) {
        nextCoin = coin;
        return true;
      }
    });
    return nextCoin ? nextCoin.symbol : nextCoin;
  }

  function getRate() {
    ractive.set('isLoadingRate', true);
    return shapeshift.marketInfo(ractive.get('fromSymbol'), ractive.get('toSymbol')).then(function(data) {
      var rate = data.rate;
      ractive.set('isLoadingRate', false);
      ractive.set('rate', rate);
    }).catch(function(err) {
      ractive.set('isLoadingRate', false);
      ractive.set('rate', '?');
      console.error(err);
    });
  }

  return ractive;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2016 e-UCM (http://www.e-ucm.es/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * This project has received funding from the European Union’s Horizon
 * 2020 research and innovation programme under grant agreement No 644187.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0 (link is external)
 *
 * 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.
 */

'use strict';

angular.module('loginApp', ['ngStorage', 'ngCookies'])
    .controller('LoginCtrl', ['$scope', '$http', '$window', '$timeout', '$localStorage', '$cookies', 'CONSTANTS',
        function ($scope, $http, $window, $timeout, $localStorage, $cookies, CONSTANTS) {
            $scope.$storage = $localStorage;

            $scope.login = function () {
                $http.post(CONSTANTS.APIPATH + '/login', $scope.user).success(function (data) {
                    $localStorage.$reset();
                    $scope.$storage.user = data.user;
                    $cookies.put('rageUserCookie', data.user.token);

                    $http.get(CONSTANTS.APIPATH + '/users/' + data.user._id + '/roles').success(function (data) {
                        $scope.$storage.user.roles = data;
                        // Timeout needed in order to ensure that the
                        // $localStorage changes are persisted, more info. at
                        // https://github.com/gsklee/ngStorage/issues/39
                        $timeout(function () {
                            $window.location.href = 'home';
                        }, 110);
                    }).error(function (data, status) {
                        console.error('Error on get /api/users/:userId/roles: ' + JSON.stringify(data) + ', status: ' + status);

                    });
                }).error(function (data, status) {
                    console.error('Error on post /api/login: ' + JSON.stringify(data) + ', status: ' + status);
                });
            };
        }]);<commit_msg>Minor cookies fix<commit_after>/*
 * Copyright 2016 e-UCM (http://www.e-ucm.es/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * This project has received funding from the European Union’s Horizon
 * 2020 research and innovation programme under grant agreement No 644187.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0 (link is external)
 *
 * 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.
 */

'use strict';

angular.module('loginApp', ['ngStorage', 'ngCookies'])
    .controller('LoginCtrl', ['$scope', '$http', '$window', '$timeout', '$localStorage', '$cookies', 'CONSTANTS',
        function ($scope, $http, $window, $timeout, $localStorage, $cookies, CONSTANTS) {
            $scope.$storage = $localStorage;

            $scope.login = function () {
                $http.post(CONSTANTS.APIPATH + '/login', $scope.user).success(function (data) {
                    $localStorage.$reset();
                    $scope.$storage.user = data.user;
                    $cookies.put('rageUserCookie', data.user.token, {path : '/'});

                    $http.get(CONSTANTS.APIPATH + '/users/' + data.user._id + '/roles').success(function (data) {
                        $scope.$storage.user.roles = data;
                        // Timeout needed in order to ensure that the
                        // $localStorage changes are persisted, more info. at
                        // https://github.com/gsklee/ngStorage/issues/39
                        $timeout(function () {
                            $window.location.href = 'home';
                        }, 110);
                    }).error(function (data, status) {
                        console.error('Error on get /api/users/:userId/roles: ' + JSON.stringify(data) + ', status: ' + status);

                    });
                }).error(function (data, status) {
                    console.error('Error on post /api/login: ' + JSON.stringify(data) + ', status: ' + status);
                });
            };
        }]);<|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc function
 * @name ausEnvApp.controller:DetailsCtrl
 * @description
 * # DetailsCtrl
 * Controller of the ausEnvApp
 */
angular.module('ausEnvApp')
  .controller('DetailsCtrl', function ($scope,selection,details) {

    /*
  var unit_dict = [];
  unit_dict['frequency'] = "occurrences/year";
  unit_dict['percent'] = "%";
  unit_dict['percent'] = "%";
  unit_dict['m2/m2'] = "m" + "2".sup() + "/m" + "2".sup();
  unit_dict['gC/m2'] = "gC/m" + "2".sup();
  */

  var unit_dict = [];
  unit_dict["frequency"] = "occurrences/year";
  unit_dict["percent"] = "%";
  unit_dict["percent"] = "%";
  unit_dict["m2/m2"] = "m^2/m^2";
  unit_dict["gC/m2"] = "gC/m^2";

  var firstYear;
  var currentYearIndex = selection.year - firstYear;

  console.log("current year");
  console.log(currentYearIndex);
  $scope.barOptions =  {
      // Sets the chart to be responsive
      responsive: true,

      //Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
      scaleBeginAtZero : false,

      //Boolean - Whether grid lines are shown across the chart
      scaleShowGridLines : true,

      //String - Colour of the grid lines
      scaleGridLineColor : "rgba(0,0,0,.05)",

      //Number - Width of the grid lines
      scaleGridLineWidth : 1,

      //Boolean - If there is a stroke on each bar
      barShowStroke : true,

      //Number - Pixel width of the bar stroke
      barStrokeWidth : 0.1,

      //Number - Spacing between each of the X value sets
      barValueSpacing : 2,

      //Number - Spacing between data sets within X values
      barDatasetSpacing : 1,
    };

    /*
    $scope.barColors = [{
      fillColor: 'rgba(247,70,74,0.2)',
      strokeColor: 'rgba(247,70,74,1)',
      pointColor: 'rgba(247,70,74,1)',
      pointStrokeColor: '#fff',
      pointHighlightFill: '#fff',
      pointHighlightStroke: 'rgba(247,70,74,0.8)'
    }];
    */

    $scope.selection = selection;
    $scope.viewOptions = [
      {
        style:'bar',

        icon:'fa-bar-chart',
        tooltip:'Annual time series',
      },
      {
        style:'pie',
        icon:'fa-pie-chart',
        tooltip:'Proportion by land cover type',
      },
      {
        style:'timeseries',
        icon:'fa-line-chart',
        tooltip:'Detailed time series'
      }
    ];

    $scope.bar = {
      title:null,
      description:null,
      units: null
    };

    $scope.pie = {
      title:null,
      description:null,
      units: null
    };

    $scope.barChartData = 0;
    $scope.barLabels = [];
    $scope.barSeries = [];
    $scope.barData = [];

    $scope.pieData = [];
    $scope.pieLabels = [];

    $scope.clearData = function(){
      $scope.barChartData = 0;
      $scope.barLabels = [];
      $scope.barSeries = [];
      $scope.barData = [];

      $scope.pieData = [];
      $scope.pieLabels = [];
    };

    $scope.createCharts = function(){
      if(!selection.selectedLayer || !selection.regionType) {
        $scope.clearData();
        return;
      }

      var PlaceId = null;
      var label = null;
      if(selection.selectedRegion && selection.selectedRegion.name) {
        var keyField = selection.regionType.keyField;
        PlaceId = selection.selectedRegion.feature.properties[keyField];
        label = selection.selectedRegion.name;
      } else if(!selection.haveRegion()){
        PlaceId = 9999;
        label = 'National';
      } else {
        return;
      }

      $scope.createBarChart(PlaceId,label);
      $scope.createPieChart(PlaceId);
//      $scope.createLineChart(PlaceId,label);
    };

    $scope.$watch('selection.selectedRegion',$scope.createCharts);
    $scope.$watch('selection.selectedLayer',$scope.createCharts);
    $scope.$watch('selection.regionType',$scope.createCharts);

    $scope.populateLabels = function(chart,data){
        chart.title = data.Title;
        chart.description = data.Description;
        chart.units = (data.Units in unit_dict) ? unit_dict[data.Units] : data.Units;
        if(chart === $scope.bar) {
          $scope.viewOptions[0].description = chart.description;
        } else if(chart === $scope.pie) {
          $scope.viewOptions[1].description = chart.description;
        }
    };

    $scope.createBarChart = function(placeId,label){
      details.getBarChartData().then(function(data){
        $scope.barChartData = data;
        $scope.units = ($scope.barChartData.Units in unit_dict) ? unit_dict[$scope.barChartData.Units] : $scope.barChartData.Units;
        $scope.barLabels = [];
        $scope.barSeries = [];
        $scope.barData = [];
        $scope.populateLabels($scope.bar,data);
        $scope.barLabels = $scope.barChartData.columnNames;
        $scope.barSeries.push(label);
        var indexName = "PlaceIndex" + placeId;
        $scope.barData.push($scope.barChartData[indexName]);
        firstYear = $scope.barLabels[0];

        for (var i=0; i<$scope.barLabels.length; i++) {
          if (selection.year === parseInt($scope.barLabels[i])) {
            currentYearIndex = i;
            break;
          }
        }

        /*
        for (var i=0; i<$scope.barLabels.length; i++) {
          $scope.barColors[0].fillColor[i] = "#66987F";
        }
        */

        $scope.barColors = [{fillColor:["#66987F"]}];
        $scope.barColors[0].fillColor[currentYearIndex] = "#2B5F45";

        if (currentYearIndex < $scope.barLabels.length-1) {
          $scope.barColors[0].fillColor[currentYearIndex+1] = "#66987F";
        }

        console.log("what is the columnNames like is here");
        console.log($scope.barLabels);
      });
    };

    $scope.createPieChart = function(placeId) {
      details.getPieChartData().then(function(data){
        $scope.pieChartData = data;
        $scope.pieData = [];
        $scope.populateLabels($scope.pie,data);

        $scope.pieLabels = $scope.pieChartData.columnNames.map(function(column){
          return $scope.pieChartData.columnPresentation[column].Class_Name;
        });

        var indexName = "PlaceIndex" + placeId;
        $scope.pieData = $scope.pieChartData[indexName];
        $scope.pieChartColours = $scope.pieChartData.columnNames.map(function(col){
          var presentation = $scope.pieChartData.columnPresentation[col];
          return 'rgb('+presentation.Red+','+presentation.Green+','+presentation.Blue+')';
        });
//        $scope.pieData = $scope.pieChartData[indexName].map(function(value,idx){
//          var col = $scope.pieChartData.columnNames[idx];
//          var presentation = $scope.pieChartData.columnPresentation[col];
//          return {
//            value: value,
//            color: 'rgb('+presentation.Red+','+presentation.Green+','+presentation.Blue+')',
//            label: presentation.Class_Name
//          };
//        });
      });
    };

    //<editor-fold desc="pete linegraph">
    $scope.createLineChart = function(/*placeId,label*/){
//      console.log("Trying a line graph");
      $scope.lineLabels = details.makeSimpleLabels(10);
      $scope.lineSeries = ['one','two'];
      $scope.lineData = [];
      $scope.lineData.push(details.randomDataArray(10));
      $scope.lineData.push(details.randomDataArray(10));
      $scope.lineOptions = {

        ///Boolean - Whether grid lines are shown across the chart
        scaleShowGridLines : true,

        //String - Colour of the grid lines
        scaleGridLineColor : "rgba(0,0,0,.05)",

        //Number - Width of the grid lines
        scaleGridLineWidth : 1,

        //Boolean - Whether to show horizontal lines (except X axis)
        scaleShowHorizontalLines: true,

        //Boolean - Whether to show vertical lines (except Y axis)
        scaleShowVerticalLines: true,

        //Boolean - Whether the line is curved between points
        bezierCurve : false,  //true

        //Number - Tension of the bezier curve between points
        bezierCurveTension : 0.4,

        //Boolean - Whether to show a dot for each point
        pointDot : false,  //true

        //Number - Radius of each point dot in pixels
        pointDotRadius : 4,

        //Number - Pixel width of point dot stroke
        pointDotStrokeWidth : 1,

        //Number - amount extra to add to the radius to cater for hit detection outside the drawn point
        pointHitDetectionRadius : 20,

        //Boolean - Whether to show a stroke for datasets
        datasetStroke : true,

        //Number - Pixel width of dataset stroke
        datasetStrokeWidth : 2,

        //Boolean - Whether to fill the dataset with a colour
        datasetFill : true,

        //String - A legend template
        //legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%>
<span style=\"background-color:<%=datasets[i].strokeColor%>\"><%if(datasets[i].label){%><%=datasets[i].label%><%}%>
<%}%>
"

      };

    };

    $scope.onLineClick = function (points, evt) {
      console.log(points, evt);
    };

    $scope.$on('create', function (event, chart) {  //how to limit to just line graph?
      console.log("create");
      console.log(chart);
    });

    $scope.$on('update', function (event, chart) {  //how to limit to just line graph?
      console.log("update");
      console.log(chart);
    });
    //</editor-fold>

    $scope.pieChartOptions = {
      animateRotate: false,
      animationSteps: 1
    };
  });
<commit_msg>whitespace<commit_after>'use strict';

/**
 * @ngdoc function
 * @name ausEnvApp.controller:DetailsCtrl
 * @description
 * # DetailsCtrl
 * Controller of the ausEnvApp
 */
angular.module('ausEnvApp')
  .controller('DetailsCtrl', function ($scope,selection,details) {

    /*
  var unit_dict = [];
  unit_dict['frequency'] = "occurrences/year";
  unit_dict['percent'] = "%";
  unit_dict['percent'] = "%";
  unit_dict['m2/m2'] = "m" + "2".sup() + "/m" + "2".sup();
  unit_dict['gC/m2'] = "gC/m" + "2".sup();
  */

  var unit_dict = [];
  unit_dict["frequency"] = "occurrences/year";
  unit_dict["percent"] = "%";
  unit_dict["percent"] = "%";
  unit_dict["m2/m2"] = "m^2/m^2";
  unit_dict["gC/m2"] = "gC/m^2";
  var firstYear;
  var currentYearIndex = selection.year - firstYear;

  console.log("current year");
  console.log(currentYearIndex);
  $scope.barOptions =  {
      // Sets the chart to be responsive
      responsive: true,

      //Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
      scaleBeginAtZero : false,

      //Boolean - Whether grid lines are shown across the chart
      scaleShowGridLines : true,

      //String - Colour of the grid lines
      scaleGridLineColor : "rgba(0,0,0,.05)",

      //Number - Width of the grid lines
      scaleGridLineWidth : 1,

      //Boolean - If there is a stroke on each bar
      barShowStroke : true,

      //Number - Pixel width of the bar stroke
      barStrokeWidth : 0.1,

      //Number - Spacing between each of the X value sets
      barValueSpacing : 2,

      //Number - Spacing between data sets within X values
      barDatasetSpacing : 1,
    };

    /*
    $scope.barColors = [{
      fillColor: 'rgba(247,70,74,0.2)',
      strokeColor: 'rgba(247,70,74,1)',
      pointColor: 'rgba(247,70,74,1)',
      pointStrokeColor: '#fff',
      pointHighlightFill: '#fff',
      pointHighlightStroke: 'rgba(247,70,74,0.8)'
    }];
    */

    $scope.selection = selection;
    $scope.viewOptions = [
      {
        style:'bar',

        icon:'fa-bar-chart',
        tooltip:'Annual time series',
      },
      {
        style:'pie',
        icon:'fa-pie-chart',
        tooltip:'Proportion by land cover type',
      },
      {
        style:'timeseries',
        icon:'fa-line-chart',
        tooltip:'Detailed time series'
      }
    ];

    $scope.bar = {
      title:null,
      description:null,
      units: null
    };

    $scope.pie = {
      title:null,
      description:null,
      units: null
    };

    $scope.barChartData = 0;
    $scope.barLabels = [];
    $scope.barSeries = [];
    $scope.barData = [];

    $scope.pieData = [];
    $scope.pieLabels = [];

    $scope.clearData = function(){
      $scope.barChartData = 0;
      $scope.barLabels = [];
      $scope.barSeries = [];
      $scope.barData = [];

      $scope.pieData = [];
      $scope.pieLabels = [];
    };

    $scope.createCharts = function(){
      if(!selection.selectedLayer || !selection.regionType) {
        $scope.clearData();
        return;
      }

      var PlaceId = null;
      var label = null;
      if(selection.selectedRegion && selection.selectedRegion.name) {
        var keyField = selection.regionType.keyField;
        PlaceId = selection.selectedRegion.feature.properties[keyField];
        label = selection.selectedRegion.name;
      } else if(!selection.haveRegion()){
        PlaceId = 9999;
        label = 'National';
      } else {
        return;
      }

      $scope.createBarChart(PlaceId,label);
      $scope.createPieChart(PlaceId);
//      $scope.createLineChart(PlaceId,label);
    };

    $scope.$watch('selection.selectedRegion',$scope.createCharts);
    $scope.$watch('selection.selectedLayer',$scope.createCharts);
    $scope.$watch('selection.regionType',$scope.createCharts);

    $scope.populateLabels = function(chart,data){
        chart.title = data.Title;
        chart.description = data.Description;
        chart.units = (data.Units in unit_dict) ? unit_dict[data.Units] : data.Units;
        if(chart === $scope.bar) {
          $scope.viewOptions[0].description = chart.description;
        } else if(chart === $scope.pie) {
          $scope.viewOptions[1].description = chart.description;
        }
    };

    $scope.createBarChart = function(placeId,label){
      details.getBarChartData().then(function(data){
        $scope.barChartData = data;
        $scope.units = ($scope.barChartData.Units in unit_dict) ? unit_dict[$scope.barChartData.Units] : $scope.barChartData.Units;
        $scope.barLabels = [];
        $scope.barSeries = [];
        $scope.barData = [];
        $scope.populateLabels($scope.bar,data);
        $scope.barLabels = $scope.barChartData.columnNames;
        $scope.barSeries.push(label);
        var indexName = "PlaceIndex" + placeId;
        $scope.barData.push($scope.barChartData[indexName]);
        firstYear = $scope.barLabels[0];

        for (var i=0; i<$scope.barLabels.length; i++) {
          if (selection.year === parseInt($scope.barLabels[i])) {
            currentYearIndex = i;
            break;
          }
        }

        /*
        for (var i=0; i<$scope.barLabels.length; i++) {
          $scope.barColors[0].fillColor[i] = "#66987F";
        }
        */

        $scope.barColors = [{fillColor:["#66987F"]}];
        $scope.barColors[0].fillColor[currentYearIndex] = "#2B5F45";

        if (currentYearIndex < $scope.barLabels.length-1) {
          $scope.barColors[0].fillColor[currentYearIndex+1] = "#66987F";
        }

//        console.log("what is the columnNames like is here");
//        console.log($scope.barLabels);
      });
    };

    $scope.createPieChart = function(placeId) {
      details.getPieChartData().then(function(data){
        $scope.pieChartData = data;
        $scope.pieData = [];
        $scope.populateLabels($scope.pie,data);

        $scope.pieLabels = $scope.pieChartData.columnNames.map(function(column){
          return $scope.pieChartData.columnPresentation[column].Class_Name;
        });

        var indexName = "PlaceIndex" + placeId;
        $scope.pieData = $scope.pieChartData[indexName];
        $scope.pieChartColours = $scope.pieChartData.columnNames.map(function(col){
          var presentation = $scope.pieChartData.columnPresentation[col];
          return 'rgb('+presentation.Red+','+presentation.Green+','+presentation.Blue+')';
        });
//        $scope.pieData = $scope.pieChartData[indexName].map(function(value,idx){
//          var col = $scope.pieChartData.columnNames[idx];
//          var presentation = $scope.pieChartData.columnPresentation[col];
//          return {
//            value: value,
//            color: 'rgb('+presentation.Red+','+presentation.Green+','+presentation.Blue+')',
//            label: presentation.Class_Name
//          };
//        });
      });
    };

    //<editor-fold desc="pete linegraph">
    $scope.createLineChart = function(/*placeId,label*/){
//      console.log("Trying a line graph");
      $scope.lineLabels = details.makeSimpleLabels(10);
      $scope.lineSeries = ['one','two'];
      $scope.lineData = [];
      $scope.lineData.push(details.randomDataArray(10));
      $scope.lineData.push(details.randomDataArray(10));
      $scope.lineOptions = {

        ///Boolean - Whether grid lines are shown across the chart
        scaleShowGridLines : true,

        //String - Colour of the grid lines
        scaleGridLineColor : "rgba(0,0,0,.05)",

        //Number - Width of the grid lines
        scaleGridLineWidth : 1,

        //Boolean - Whether to show horizontal lines (except X axis)
        scaleShowHorizontalLines: true,

        //Boolean - Whether to show vertical lines (except Y axis)
        scaleShowVerticalLines: true,

        //Boolean - Whether the line is curved between points
        bezierCurve : false,  //true

        //Number - Tension of the bezier curve between points
        bezierCurveTension : 0.4,

        //Boolean - Whether to show a dot for each point
        pointDot : false,  //true

        //Number - Radius of each point dot in pixels
        pointDotRadius : 4,

        //Number - Pixel width of point dot stroke
        pointDotStrokeWidth : 1,

        //Number - amount extra to add to the radius to cater for hit detection outside the drawn point
        pointHitDetectionRadius : 20,

        //Boolean - Whether to show a stroke for datasets
        datasetStroke : true,

        //Number - Pixel width of dataset stroke
        datasetStrokeWidth : 2,

        //Boolean - Whether to fill the dataset with a colour
        datasetFill : true,

        //String - A legend template
        //legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%>
<span style=\"background-color:<%=datasets[i].strokeColor%>\"><%if(datasets[i].label){%><%=datasets[i].label%><%}%>
<%}%>
"

      };

    };

    $scope.onLineClick = function (points, evt) {
      console.log(points, evt);
    };

    $scope.$on('create', function (event, chart) {  //how to limit to just line graph?
      console.log("create");
      console.log(chart);
    });

    $scope.$on('update', function (event, chart) {  //how to limit to just line graph?
      console.log("update");
      console.log(chart);
    });
    //</editor-fold>

    $scope.pieChartOptions = {
      animateRotate: false,
      animationSteps: 1
    };
  });
<|endoftext|>


<commit_before>'use strict';

angular.module('iamhungryApp')
	.controller('ProfileCtrl', function($scope, fbAuth, $location) {

		 // initialize $scope variables
		 // without initializeing here $scope wont be able to get user details.
		 // need to log out n log in to supply the correct vales to the scope

		$scope.loggedIn = fbAuth.user.loggedIn;
		$scope.user = fbAuth.user.loggedUser;

		var autoToJSON = ['loggedIn', 'user'];

		angular.forEach(autoToJSON, function(varName) {
			$scope.$watch(varName, function(val) {
				$scope[varName + 'JSON'] = JSON.stringify(val, null, 2);
			}, true);
		});

		$scope.$on('updateUser', function() {
			$scope.loggedIn = fbAuth.user.loggedIn;
			$scope.user = fbAuth.user.loggedUser;
		});
	});<commit_msg>Changed line comment to block<commit_after>'use strict';

angular.module('iamhungryApp')
	.controller('ProfileCtrl', function($scope, fbAuth, $location) {

		 /* initialize $scope variables
		  without initializeing here $scope wont be able to get user details.
		  need to log out n log in to supply the correct vales to the scope
		 */

		$scope.loggedIn = fbAuth.user.loggedIn;
		$scope.user = fbAuth.user.loggedUser;

		var autoToJSON = ['loggedIn', 'user'];

		angular.forEach(autoToJSON, function(varName) {
			$scope.$watch(varName, function(val) {
				$scope[varName + 'JSON'] = JSON.stringify(val, null, 2);
			}, true);
		});

		$scope.$on('updateUser', function() {
			$scope.loggedIn = fbAuth.user.loggedIn;
			$scope.user = fbAuth.user.loggedUser;
		});
	});<|endoftext|>


<commit_before>/**
ItemViews
*/

Lizard.views = {};

Lizard.views.Filter = Backbone.Marionette.ItemView.extend({
  _modelBinder: undefined,
  initialize: function(){
    // console.log('FilterView.initialize()');
    this._modelBinder = new Backbone.ModelBinder();
  },
  onRender: function() {
    // console.log('filterview onRender()');
    var bindings = {state: 'span.state'};
    this._modelBinder.bind(this.model, this.el, bindings);
    // console.log(bindings);
  },
  tagName: 'li',
  template: '#filterview-template',
  events: {
    'click input': 'toggle'
  },
  toggle: function(e) {
    if(this.model.get('selected') === false) {
      this.model.set('selected', true);
    } else {
      this.model.set('selected', false);
    }
    console.log('Setting ' + this.model.get('filtername') + ' to ' + this.model.get('selected'));
  },
  modelEvents: {
    'change': 'modelChanged'
  },
  collectionEvents: {
    'add': 'modelAdded'
  },
  modelChanged: function() {

    console.log(this.model.attributes.filtername +' changed to', this.model.attributes.selected);

    var ids = '';
    _.each(filtercollectionview.collection.models, function(data) {
      if(data.attributes.selected === true) {
        ids = ids + data.attributes.filter_id;
        ids = ids + ',';
        // console.log(ids);
      }
    });
    ids = ids.substring(0, ids.length - 1);

    locationcollectionview.collection.url = settings.locations_url + '?filters='+ids;
    locationcollectionview.collection.fetch({
      cache: true,
      success: function() {
        window.graphsView.locationsRegion.show(locationcollectionview.render());
      }
    });

  },
  modelAdded: function() {
    console.log('A model was added to the collection');
  }
});

Lizard.views.Location = Backbone.Marionette.ItemView.extend({

  _modelBinder: undefined,
  initialize: function(){
    // console.log('LocationView.initialize()');
    this._modelBinder = new Backbone.ModelBinder();
  },
  onRender: function() {
    // console.log('locationview onRender()');
    var bindings = {state: 'span.state'};
    this._modelBinder.bind(this.model, this.el, bindings);
    // console.log(bindings);
  },
  tagName: 'li',
  template: '#locationview-template',
  events: {
    'click input': 'toggle'
  },
  toggle: function(e) {
    if(this.model.get('selected') === false) {
      this.model.set('selected', true);
    } else {
      this.model.set('selected', false);
    }
  },
  modelEvents: {
    'change': 'modelChanged'
  },
  collectionEvents: {
    'add': 'modelAdded'
  },
  modelChanged: function() {

    console.log(this.model.attributes.location +' changed to', this.model.attributes.selected);

    var ids = '';
    _.each(locationcollectionview.collection.models, function(data) {
      if(data.attributes.selected === true) {
        ids = ids + data.attributes.location_id;
        ids = ids + ',';
        // console.log(ids);
      }
    });
    ids = ids.substring(0, ids.length - 1);

    parametercollectionview.collection.url = settings.parameters_url + '?locations='+ids;
    parametercollectionview.collection.fetch({
      cache: true,
      success: function() {
        window.graphsView.parametersRegion.show(parametercollectionview.render());
      }
    });
    filtercollectionview.collection.url = settings.filters_url + '?locations='+ids;
    filtercollectionview.collection.fetch({
      cache: true,
      success: function() {
        window.graphsView.filtersRegion.show(filtercollectionview.render());
      }
    });

  },
  modelAdded: function() {
    console.log('I, COLLECTION, HAS CHANGED');
  }

});

Lizard.views.Parameter = Backbone.Marionette.ItemView.extend({

  _modelBinder: undefined,
  initialize: function(){
    // console.log('ParameterView.initialize()');
    this._modelBinder = new Backbone.ModelBinder();
  },
  onRender: function() {
    // console.log('parameterview onRender()');
    var bindings = {state: 'span.state'};
    this._modelBinder.bind(this.model, this.el, bindings);
    // console.log(bindings);
  },
  tagName: 'li',
  template: '#parameterview-template',
  events: {
    'click input': 'toggle'
  },
  toggle: function(e) {
    if(this.model.get('selected') === false) {
      this.model.set('selected', true);
    } else {
      this.model.set('selected', false);
    }
  },
  modelEvents: {
    'change': 'modelChanged'
  },
  collectionEvents: {
    'add': 'modelAdded'
  },
  modelChanged: function() {
    console.log(this.model.attributes.filtername +' changed to', this.model.attributes.selected);
    var ids = '';
    _.each(parametercollectionview.collection.models, function(data) {
      if(data.attributes.selected === true) {
        ids = ids + data.attributes.parameter_id;
        ids = ids + ',';
        console.log('---------->', ids);
      }
    });
    ids = ids.substring(0, ids.length - 1);
    locationcollectionview.collection.url = settings.locations_url + '?parameters='+ids;
    locationcollectionview.collection.fetch({
      cache: true,
      success: function() {
        window.graphsView.locationsRegion.show(locationcollectionview.render());
      }
    });
  },
  modelAdded: function() {
    console.log('modelAdded: ', this.model);
  }
});

/**
CollectionViews
*/

Lizard.views.FilterCollection = Backbone.Marionette.CollectionView.extend({
  collection: new Lizard.collections.Filter(),
  tagName: 'ul',
  itemView: Lizard.views.Filter,

  initialize: function(){
     this.collection.fetch({
        cache: true
      });
      this.listenTo(this.collection, 'reset', this.render, this);
  }
});

Lizard.views.LocationCollection = Backbone.Marionette.CollectionView.extend({
  collection: new Lizard.collections.Location(),
  tagName: 'ul',
  itemView: Lizard.views.Location,

  initialize: function(){
      this.collection.fetch({
        cache: true
      });
      this.listenTo(this.collection, 'reset', this.render, this);
  }
});

Lizard.views.ParameterCollection = Backbone.Marionette.CollectionView.extend({
  collection: new Lizard.collections.Parameter(),
  tagName: 'ul',

  itemView: Lizard.views.Parameter,

  initialize: function(){
      this.collection.fetch({
        cache: true
      });
      this.listenTo(this.collection, 'reset', this.render, this);
  }
});

// Instantiate the views
var filtercollectionview = new Lizard.views.FilterCollection();
var locationcollectionview = new Lizard.views.LocationCollection();
var parametercollectionview = new Lizard.views.ParameterCollection();
<commit_msg>Remove console.log<commit_after>/**
ItemViews
*/

Lizard.views = {};

Lizard.views.Filter = Backbone.Marionette.ItemView.extend({
  _modelBinder: undefined,
  initialize: function(){
    // console.log('FilterView.initialize()');
    this._modelBinder = new Backbone.ModelBinder();
  },
  onRender: function() {
    // console.log('filterview onRender()');
    var bindings = {state: 'span.state'};
    this._modelBinder.bind(this.model, this.el, bindings);
    // console.log(bindings);
  },
  tagName: 'li',
  template: '#filterview-template',
  events: {
    'click input': 'toggle'
  },
  toggle: function(e) {
    if(this.model.get('selected') === false) {
      this.model.set('selected', true);
    } else {
      this.model.set('selected', false);
    }
    console.log('Setting ' + this.model.get('filtername') + ' to ' + this.model.get('selected'));
  },
  modelEvents: {
    'change': 'modelChanged'
  },
  collectionEvents: {
    'add': 'modelAdded'
  },
  modelChanged: function() {

    console.log(this.model.attributes.filtername +' changed to', this.model.attributes.selected);

    var ids = '';
    _.each(filtercollectionview.collection.models, function(data) {
      if(data.attributes.selected === true) {
        ids = ids + data.attributes.filter_id;
        ids = ids + ',';
        // console.log(ids);
      }
    });
    ids = ids.substring(0, ids.length - 1);

    locationcollectionview.collection.url = settings.locations_url + '?filters='+ids;
    locationcollectionview.collection.fetch({
      cache: true,
      success: function() {
        window.graphsView.locationsRegion.show(locationcollectionview.render());
      }
    });

  },
  modelAdded: function() {
    console.log('A model was added to the collection');
  }
});

Lizard.views.Location = Backbone.Marionette.ItemView.extend({

  _modelBinder: undefined,
  initialize: function(){
    // console.log('LocationView.initialize()');
    this._modelBinder = new Backbone.ModelBinder();
  },
  onRender: function() {
    // console.log('locationview onRender()');
    var bindings = {state: 'span.state'};
    this._modelBinder.bind(this.model, this.el, bindings);
    // console.log(bindings);
  },
  tagName: 'li',
  template: '#locationview-template',
  events: {
    'click input': 'toggle'
  },
  toggle: function(e) {
    if(this.model.get('selected') === false) {
      this.model.set('selected', true);
    } else {
      this.model.set('selected', false);
    }
  },
  modelEvents: {
    'change': 'modelChanged'
  },
  collectionEvents: {
    'add': 'modelAdded'
  },
  modelChanged: function() {

    console.log(this.model.attributes.location +' changed to', this.model.attributes.selected);

    var ids = '';
    _.each(locationcollectionview.collection.models, function(data) {
      if(data.attributes.selected === true) {
        ids = ids + data.attributes.location_id;
        ids = ids + ',';
        // console.log(ids);
      }
    });
    ids = ids.substring(0, ids.length - 1);

    parametercollectionview.collection.url = settings.parameters_url + '?locations='+ids;
    parametercollectionview.collection.fetch({
      cache: true,
      success: function() {
        window.graphsView.parametersRegion.show(parametercollectionview.render());
      }
    });
    filtercollectionview.collection.url = settings.filters_url + '?locations='+ids;
    filtercollectionview.collection.fetch({
      cache: true,
      success: function() {
        window.graphsView.filtersRegion.show(filtercollectionview.render());
      }
    });

  },
  modelAdded: function() {
    console.log('I, COLLECTION, HAS CHANGED');
  }

});

Lizard.views.Parameter = Backbone.Marionette.ItemView.extend({

  _modelBinder: undefined,
  initialize: function(){
    // console.log('ParameterView.initialize()');
    this._modelBinder = new Backbone.ModelBinder();
  },
  onRender: function() {
    // console.log('parameterview onRender()');
    var bindings = {state: 'span.state'};
    this._modelBinder.bind(this.model, this.el, bindings);
    // console.log(bindings);
  },
  tagName: 'li',
  template: '#parameterview-template',
  events: {
    'click input': 'toggle'
  },
  toggle: function(e) {
    if(this.model.get('selected') === false) {
      this.model.set('selected', true);
    } else {
      this.model.set('selected', false);
    }
  },
  modelEvents: {
    'change': 'modelChanged'
  },
  collectionEvents: {
    'add': 'modelAdded'
  },
  modelChanged: function() {
    console.log(this.model.attributes.filtername +' changed to', this.model.attributes.selected);
    var ids = '';
    _.each(parametercollectionview.collection.models, function(data) {
      if(data.attributes.selected === true) {
        ids = ids + data.attributes.parameter_id;
        ids = ids + ',';
        // console.log('---------->', ids);
      }
    });
    ids = ids.substring(0, ids.length - 1);
    locationcollectionview.collection.url = settings.locations_url + '?parameters='+ids;
    locationcollectionview.collection.fetch({
      cache: true,
      success: function() {
        window.graphsView.locationsRegion.show(locationcollectionview.render());
      }
    });
  },
  modelAdded: function() {
    console.log('modelAdded: ', this.model);
  }
});

/**
CollectionViews
*/

Lizard.views.FilterCollection = Backbone.Marionette.CollectionView.extend({
  collection: new Lizard.collections.Filter(),
  tagName: 'ul',
  itemView: Lizard.views.Filter,

  initialize: function(){
     this.collection.fetch({
        cache: true
      });
      this.listenTo(this.collection, 'reset', this.render, this);
  }
});

Lizard.views.LocationCollection = Backbone.Marionette.CollectionView.extend({
  collection: new Lizard.collections.Location(),
  tagName: 'ul',
  itemView: Lizard.views.Location,

  initialize: function(){
      this.collection.fetch({
        cache: true
      });
      this.listenTo(this.collection, 'reset', this.render, this);
  }
});

Lizard.views.ParameterCollection = Backbone.Marionette.CollectionView.extend({
  collection: new Lizard.collections.Parameter(),
  tagName: 'ul',

  itemView: Lizard.views.Parameter,

  initialize: function(){
      this.collection.fetch({
        cache: true
      });
      this.listenTo(this.collection, 'reset', this.render, this);
  }
});

// Instantiate the views
var filtercollectionview = new Lizard.views.FilterCollection();
var locationcollectionview = new Lizard.views.LocationCollection();
var parametercollectionview = new Lizard.views.ParameterCollection();
<|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/. */

/**
 * A model to manage displayed Sync engines
 * in the Choose What to Sync screen.
 */

define(function(require, exports, module) {
  'use strict';

  const _ = require('underscore');
  const Backbone = require('backbone');
  const Cocktail = require('cocktail');
  const SearchParamMixin = require('../lib/search-param-mixin');
  const UserAgentMixin = require('../lib/user-agent-mixin');

  const t = msg => msg;

  /**
   * Fields available in each engine:
   * - `checked` whether the item should be checked when CWTS opens.
   * - `id` of the engine, must be the name the browser uses.
   * - `test` if defined, function used to test whether CWTS is available
   *    for the given `userAgent`. Should return `true` or `false`.
   * - `text` to display when CWTS opens
   */
  const AVAILABLE_ENGINES = [
    {
      checked: true,
      id: 'tabs',
      text: t('Open tabs')
    },
    {
      checked: true,
      id: 'bookmarks',
      text: t('Bookmarks')
    },
    {
      checked: true,
      id: 'addons',
      text: t('Add-ons')
    },
    {
      checked: true,
      id: 'passwords',
      text: t('Passwords')
    },
    {
      checked: true,
      id: 'history',
      text: t('History')
    },
    {
      checked: true,
      id: 'prefs',
      text: t('Preferences')
    },
    {
      checked: true,
      id: 'addresses',
      // addresses will only be available via capabilities.
      test: () => false,
      text: t('Addresses')
    },
    {
      checked: true,
      id: 'creditcards',
      // credit cards will only be available via capabilities.
      test: () => false,
      text: t('Credit cards')
    }
  ];

  class SyncEngines extends Backbone.Collection {
    initialize (models, options = {}) {
      this.window = options.window;

      const engines = options.engines || this.getSupportedEngineIds();
      engines.forEach((engineId) => this.addById(engineId));
    }

    /**
     * Get a list of engineIds supported by the user agent.
     *
     * @returns {String[]}
     */
    getSupportedEngineIds () {
      const userAgent = this.getUserAgent();
      const availableEngineIds = AVAILABLE_ENGINES.map((syncEngine) => syncEngine.id);
      return _.filter(availableEngineIds,
        (engineId) => this.isEngineSupportedByUA(engineId, userAgent));
    }

    /**
     * Is engine with `engineId` is supported by `userAgent`
     *
     * @param {String} engineId
     * @param {Object} userAgent
     * @returns {Boolean}
     */
    isEngineSupportedByUA (engineId, userAgent) {
      const syncEngine = SyncEngines.getEngineConfig(engineId);
      return ! syncEngine.test || syncEngine.test(userAgent);
    }

    /**
     * Add a sync engine by `engineId`, if not already
     * in the collection.
     *
     * @param {String} engineId
     */
    addById (engineId) {
      const syncEngine = SyncEngines.getEngineConfig(engineId);
      if (syncEngine && ! this.get(engineId)) {
        this.add(syncEngine);
      }
    }

    /**
     * Use `engineId` to get the configuration for a Sync engine.
     *
     * @static
     * @param {String} engineId
     * @returns {Object}
     */
    static getEngineConfig (engineId) {
      return _.find(AVAILABLE_ENGINES, (syncEngine) => syncEngine.id === engineId);
    }
  }

  Cocktail.mixin(
    SyncEngines,
    SearchParamMixin,
    UserAgentMixin
  );

  module.exports = SyncEngines;
});
<commit_msg>fix(copy): update sync-engines.js (#5769) r=@vladikoff,@ryanfeeley <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/. */

/**
 * A model to manage displayed Sync engines
 * in the Choose What to Sync screen.
 */

define(function(require, exports, module) {
  'use strict';

  const _ = require('underscore');
  const Backbone = require('backbone');
  const Cocktail = require('cocktail');
  const SearchParamMixin = require('../lib/search-param-mixin');
  const UserAgentMixin = require('../lib/user-agent-mixin');

  const t = msg => msg;

  /**
   * Fields available in each engine:
   * - `checked` whether the item should be checked when CWTS opens.
   * - `id` of the engine, must be the name the browser uses.
   * - `test` if defined, function used to test whether CWTS is available
   *    for the given `userAgent`. Should return `true` or `false`.
   * - `text` to display when CWTS opens
   */
  const AVAILABLE_ENGINES = [
    {
      checked: true,
      id: 'tabs',
      text: t('Open tabs')
    },
    {
      checked: true,
      id: 'bookmarks',
      text: t('Bookmarks')
    },
    {
      checked: true,
      id: 'addons',
      text: t('Add-ons')
    },
    {
      checked: true,
      id: 'passwords',
      text: t('Logins')
    },
    {
      checked: true,
      id: 'history',
      text: t('History')
    },
    {
      checked: true,
      id: 'prefs',
      text: t('Preferences')
    },
    {
      checked: true,
      id: 'addresses',
      // addresses will only be available via capabilities.
      test: () => false,
      text: t('Addresses')
    },
    {
      checked: true,
      id: 'creditcards',
      // credit cards will only be available via capabilities.
      test: () => false,
      text: t('Credit cards')
    }
  ];

  class SyncEngines extends Backbone.Collection {
    initialize (models, options = {}) {
      this.window = options.window;

      const engines = options.engines || this.getSupportedEngineIds();
      engines.forEach((engineId) => this.addById(engineId));
    }

    /**
     * Get a list of engineIds supported by the user agent.
     *
     * @returns {String[]}
     */
    getSupportedEngineIds () {
      const userAgent = this.getUserAgent();
      const availableEngineIds = AVAILABLE_ENGINES.map((syncEngine) => syncEngine.id);
      return _.filter(availableEngineIds,
        (engineId) => this.isEngineSupportedByUA(engineId, userAgent));
    }

    /**
     * Is engine with `engineId` is supported by `userAgent`
     *
     * @param {String} engineId
     * @param {Object} userAgent
     * @returns {Boolean}
     */
    isEngineSupportedByUA (engineId, userAgent) {
      const syncEngine = SyncEngines.getEngineConfig(engineId);
      return ! syncEngine.test || syncEngine.test(userAgent);
    }

    /**
     * Add a sync engine by `engineId`, if not already
     * in the collection.
     *
     * @param {String} engineId
     */
    addById (engineId) {
      const syncEngine = SyncEngines.getEngineConfig(engineId);
      if (syncEngine && ! this.get(engineId)) {
        this.add(syncEngine);
      }
    }

    /**
     * Use `engineId` to get the configuration for a Sync engine.
     *
     * @static
     * @param {String} engineId
     * @returns {Object}
     */
    static getEngineConfig (engineId) {
      return _.find(AVAILABLE_ENGINES, (syncEngine) => syncEngine.id === engineId);
    }
  }

  Cocktail.mixin(
    SyncEngines,
    SearchParamMixin,
    UserAgentMixin
  );

  module.exports = SyncEngines;
});
<|endoftext|>