<commit_before>angular.module('huntEdu.services')
    .factory('JobPost', function JobPostFactory() {
        var forEach = angular.forEach,
            isObject = angular.isObject,
            copy = angular.copy;

        var copyNonNull = function(src, dest) {
            if(dest) {
                copy(src, dest);
            } else {
                dest = copy(src);
            }

            if(isObject(dest)) {
                forEach(dest, function(value, key) {
                    if(!value) {
                        delete dest[key];
                    }
                });
            }
            return dest;
        };

        var JOB_POST_DATA_FIELDS = ['meta','specifics', 'location',
                            'date', 'media', 'tags'];

        function JobPost(data) {
           var self = this;
           forEach(data, function(value, key) {
                if(JOB_POST_DATA_FIELDS.indexOf(key) !== -1) {
                   self[key] = copyNonNull(value);
                }
            });
        }

        JobPost.prototype = {
            'meta': {
                'id': null
            },
            'specifics': {
                'jobTitle': null,
                'description': null,
                'requirements': null,
                'salary': null,
                'companyName': null,
                'department': null,
                'jobType': null
            },
            'location': {
                'city': null,
                'state': null
            },
            'date': {
                'postedOn': null,
                'endsOn': null
            },
            'media': {
                'image': null,
                'video': null
            },
            'tags': []
        };

        JobPost.prototype.getId = function() {
            return this.meta.id;
        };

        JobPost.getJobPostDataFields = function() {
            return JOB_POST_DATA_FIELDS;
        };

        JobPost.prototype.getImage = function() {
            return this.media.image;
        };

        JobPost.prototype.hasImage = function() {
            return !!this.media.image;
        };

        JobPost.prototype.getVideo = function() {
            return this.media.video;
        };

        JobPost.prototype.hasVideo = function() {
            return !!this.media.video;
        };

        JobPost.prototype.setJobPostData = function(data) {
            var self = this;
            forEach(data, function(value, key) {
                if(JOB_POST_DATA_FIELDS.indexOf(key) !== -1) {
                   self[key] = copyNonNull(value);
                }
            });
        };

        JobPost.prototype.getJobPostData = function() {
            var info = {};
            forEach(this, function(value, key) {
                forEach(JOB_POST_DATA_FIELDS, function(jobPostDataField) {
                    if(value && (key === jobPostDataField)) {
                        info[jobPostDataField] =
                            copyNonNull(value);
                    }
                });
            });
            return info;
        };

         return JobPost;
    });
<commit_msg>Added some comments to jobPost.js<commit_after>angular.module('huntEdu.services')
    .factory('JobPost', function JobPostFactory() {
        var forEach = angular.forEach,
            isObject = angular.isObject,
            copy = angular.copy;

        /**
         * Wrapper around angular.copy. Copies src
         * to dest. If src is an object, dest will
         * not have any null valued fields.
         * @param src {Object, Array} Source
         * @param dest {Object, Array} Destination
         */

        var copyNonNull = function(src, dest) {
            if(dest) {
                copy(src, dest);
            } else {
                dest = copy(src);
            }

            if(isObject(dest)) {
                forEach(dest, function(value, key) {
                    if(!value) {
                        delete dest[key];
                    }
                });
            }
            return dest;
        };

        var JOB_POST_DATA_FIELDS = ['meta','specifics', 'location',
                            'date', 'media', 'tags'];

        /**
         * Constructor for Job Post. Initializes Job Post given
         * data.
         * @param data {Object}
         */

        function JobPost(data) {
           var self = this;
           // Copy each value in data whose key exists in our job post
           // schema
           forEach(data, function(value, key) {
                if(JOB_POST_DATA_FIELDS.indexOf(key) !== -1) {
                   self[key] = copyNonNull(value);
                }
            });
        }

        JobPost.prototype = {
            'meta': {
                'id': null
            },
            'specifics': {
                'jobTitle': null,
                'description': null,
                'requirements': null,
                'salary': null,
                'companyName': null,
                'department': null,
                'jobType': null
            },
            'location': {
                'city': null,
                'state': null
            },
            'date': {
                'postedOn': null,
                'endsOn': null
            },
            'media': {
                'image': null,
                'video': null
            },
            'tags': []
        };

        JobPost.prototype.getId = function() {
            return this.meta.id;
        };

        JobPost.getJobPostDataFields = function() {
            return JOB_POST_DATA_FIELDS;
        };

        JobPost.prototype.getImage = function() {
            return this.media.image;
        };

        JobPost.prototype.hasImage = function() {
            return !!this.media.image;
        };

        JobPost.prototype.getVideo = function() {
            return this.media.video;
        };

        JobPost.prototype.hasVideo = function() {
            return !!this.media.video;
        };

        JobPost.prototype.setJobPostData = function(data) {
            var self = this;
            forEach(data, function(value, key) {
                if(JOB_POST_DATA_FIELDS.indexOf(key) !== -1) {
                   self[key] = copyNonNull(value);
                }
            });
        };

        JobPost.prototype.getJobPostData = function() {
            var info = {};
            forEach(this, function(value, key) {
                forEach(JOB_POST_DATA_FIELDS, function(jobPostDataField) {
                    if(value && (key === jobPostDataField)) {
                        info[jobPostDataField] =
                            copyNonNull(value);
                    }
                });
            });
            return info;
        };

         return JobPost;
    });
<|endoftext|>


<commit_before>export default {
  title: `Transitioning from REST to GraphQL`,
  guests: [
    {
      name: 'Lee Byron',
      twitter: 'leeb',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      name: 'Steven Luscher',
      twitter: 'gozala',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
  ],
  description: `
    We've heard about [GraphQL](https://facebook.github.io/react/blog/2015/05/01/graphql-introduction.html) [quite](https://www.youtube.com/watch?v=cr4QB3j8qFc) [a](https://www.youtube.com/watch?v=gY48GW87Feo) [bit](https://www.youtube.com/watch?v=S0s935RKKB4). We know that there are problems with REST and GraphQL solves many of those problems. But now we have a new problem: Transitioning from REST to GraphQL. Let's talk about what it takes to do that well and how services need to adapt to this new way of thinking about data access.
  `,
  hangoutId: 'csvotlp55dohetinq6k4cmrnhcg',
  youTubeId: 'ENqDNIp1Nd8',
  podbeanId: '',
  shortUrl: 'http://jsair.io/rest-graphql',
  host: {
    links: [
    ],
    tips: [
    ],
    picks: [
    ],
  },
  panelists: [
    {
      twitter: 'dan_abramov',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'drboolean',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'getify',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'kwuchu',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'linclark',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'mzabriskie',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'pamasaur',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'tylermcginnis33',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
  ],
}
<commit_msg>Updating @steveluscher's twitter...<commit_after>export default {
  title: `Transitioning from REST to GraphQL`,
  guests: [
    {
      name: 'Lee Byron',
      twitter: 'leeb',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      name: 'Steven Luscher',
      twitter: 'steveluscher',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
  ],
  description: `
    We've heard about [GraphQL](https://facebook.github.io/react/blog/2015/05/01/graphql-introduction.html) [quite](https://www.youtube.com/watch?v=cr4QB3j8qFc) [a](https://www.youtube.com/watch?v=gY48GW87Feo) [bit](https://www.youtube.com/watch?v=S0s935RKKB4). We know that there are problems with REST and GraphQL solves many of those problems. But now we have a new problem: Transitioning from REST to GraphQL. Let's talk about what it takes to do that well and how services need to adapt to this new way of thinking about data access.
  `,
  hangoutId: 'csvotlp55dohetinq6k4cmrnhcg',
  youTubeId: 'ENqDNIp1Nd8',
  podbeanId: '',
  shortUrl: 'http://jsair.io/rest-graphql',
  host: {
    links: [
    ],
    tips: [
    ],
    picks: [
    ],
  },
  panelists: [
    {
      twitter: 'dan_abramov',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'drboolean',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'getify',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'kwuchu',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'linclark',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'mzabriskie',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'pamasaur',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'tylermcginnis33',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
  ],
}
<|endoftext|>


<commit_before>odoo.define('point_of_sale.BaseWidget', function (require) {
"use strict";

var formats = require('web.formats');
var utils = require('web.utils');
var Widget = require('web.Widget');

var round_di = utils.round_decimals;
var round_pr = utils.round_precision;

// This is a base class for all Widgets in the POS. It exposes relevant data to the
// templates :
// - widget.currency : { symbol: '$' | '€' | ..., position: 'before' | 'after }
// - widget.format_currency(amount) : this method returns a formatted string based on the
//   symbol, the position, and the amount of money.
// if the PoS is not fully loaded when you instanciate the widget, the currency might not
// yet have been initialized. Use __build_currency_template() to recompute with correct values
// before rendering.
var PosBaseWidget = Widget.extend({
    init:function(parent,options){
        this._super(parent);
        options = options || {};
        this.pos    = options.pos    || (parent ? parent.pos : undefined);
        this.chrome = options.chrome || (parent ? parent.chrome : undefined);
        this.gui    = options.gui    || (parent ? parent.gui : undefined);
    },
    format_currency: function(amount,precision){
        var currency = (this.pos && this.pos.currency) ? this.pos.currency : {symbol:'$', position: 'after', rounding: 0.01, decimals: 2};

        amount = this.format_currency_no_symbol(amount,precision);

        if (currency.position === 'after') {
            return amount + ' ' + (currency.symbol || '');
        } else {
            return (currency.symbol || '') + ' ' + amount;
        }
    },
    format_currency_no_symbol: function(amount, precision) {
        var currency = (this.pos && this.pos.currency) ? this.pos.currency : {symbol:'$', position: 'after', rounding: 0.01, decimals: 2};
        var decimals = currency.decimals;

        if (precision && (typeof this.pos.dp[precision]) !== undefined) {
            decimals = this.pos.dp[precision];
        }

        this.format_currency_no_symbol = function(amount){
            amount = round_pr(amount,currency.rounding);
            amount = amount.toFixed(decimals);
            return amount;
        };
        if (typeof amount === 'number') {
            amount = round_di(amount,decimals).toFixed(decimals);
            amount = formats.format_value(round_di(amount, decimals), { type: 'float', digits: [69, decimals]});
        }

        return amount;
    },
    show: function(){
        this.$el.removeClass('oe_hidden');
    },
    hide: function(){
        this.$el.addClass('oe_hidden');
    },
    format_pr: function(value,precision){
        var decimals = precision > 0 ? Math.max(0,Math.ceil(Math.log(1.0/precision) / Math.log(10))) : 0;
        return value.toFixed(decimals);
    },
    format_fixed: function(value,integer_width,decimal_width){
        value = value.toFixed(decimal_width || 0);
        var width = value.indexOf('.');
        if (width < 0 ) {
            width = value.length;
        }
        var missing = integer_width - width;
        while (missing > 0) {
            value = '0' + value;
            missing--;
        }
        return value;
    },
});

return PosBaseWidget;

});
<commit_msg>[FIX] point_of_sale: fix forward port of currency displaying<commit_after>odoo.define('point_of_sale.BaseWidget', function (require) {
"use strict";

var formats = require('web.formats');
var utils = require('web.utils');
var Widget = require('web.Widget');

var round_di = utils.round_decimals;

// This is a base class for all Widgets in the POS. It exposes relevant data to the
// templates :
// - widget.currency : { symbol: '$' | '€' | ..., position: 'before' | 'after }
// - widget.format_currency(amount) : this method returns a formatted string based on the
//   symbol, the position, and the amount of money.
// if the PoS is not fully loaded when you instanciate the widget, the currency might not
// yet have been initialized. Use __build_currency_template() to recompute with correct values
// before rendering.
var PosBaseWidget = Widget.extend({
    init:function(parent,options){
        this._super(parent);
        options = options || {};
        this.pos    = options.pos    || (parent ? parent.pos : undefined);
        this.chrome = options.chrome || (parent ? parent.chrome : undefined);
        this.gui    = options.gui    || (parent ? parent.gui : undefined);
    },
    format_currency: function(amount,precision){
        var currency = (this.pos && this.pos.currency) ? this.pos.currency : {symbol:'$', position: 'after', rounding: 0.01, decimals: 2};

        amount = this.format_currency_no_symbol(amount,precision);

        if (currency.position === 'after') {
            return amount + ' ' + (currency.symbol || '');
        } else {
            return (currency.symbol || '') + ' ' + amount;
        }
    },
    format_currency_no_symbol: function(amount, precision) {
        var currency = (this.pos && this.pos.currency) ? this.pos.currency : {symbol:'$', position: 'after', rounding: 0.01, decimals: 2};
        var decimals = currency.decimals;

        if (precision && (typeof this.pos.dp[precision]) !== undefined) {
            decimals = this.pos.dp[precision];
        }

        if (typeof amount === 'number') {
            amount = round_di(amount,decimals).toFixed(decimals);
            amount = formats.format_value(round_di(amount, decimals), { type: 'float', digits: [69, decimals]});
        }

        return amount;
    },
    show: function(){
        this.$el.removeClass('oe_hidden');
    },
    hide: function(){
        this.$el.addClass('oe_hidden');
    },
    format_pr: function(value,precision){
        var decimals = precision > 0 ? Math.max(0,Math.ceil(Math.log(1.0/precision) / Math.log(10))) : 0;
        return value.toFixed(decimals);
    },
    format_fixed: function(value,integer_width,decimal_width){
        value = value.toFixed(decimal_width || 0);
        var width = value.indexOf('.');
        if (width < 0 ) {
            width = value.length;
        }
        var missing = integer_width - width;
        while (missing > 0) {
            value = '0' + value;
            missing--;
        }
        return value;
    },
});

return PosBaseWidget;

});
<|endoftext|>


<commit_before>// Generated by CoffeeScript 1.12.7
(function() {
  var CNode, CNodePtr, Dictionary, LinkGrammar, Linkage, ParseOptions, Sentence, Struct, _, apiTemplate, defaultConfig, defaultDataPath, ffi, getNodePtrFromPtr, int, lib, libPath, pointerType, ref, string;

  ffi = require('ffi');

  ref = require('ref');

  Struct = require('ref-struct');

  _ = require('underscore');

  pointerType = 'pointer';

  string = ref.types.CString;

  int = ref.types.int;

  ParseOptions = pointerType;

  Dictionary = pointerType;

  Sentence = pointerType;

  Linkage = pointerType;

  CNode = Struct({
    label: ref.types.CString,
    child: pointerType,
    next: pointerType,
    start: ref.types.int,
    end: ref.types.int
  });

  CNodePtr = ref.refType(CNode);

  apiTemplate = {
    parse_options_create: [ParseOptions, []],
    parse_options_set_null_block: [ref.types["void"], [ParseOptions, int]],
    parse_options_set_islands_ok: [ref.types["void"], [ParseOptions, int]],
    parse_options_set_verbosity: [ref.types["void"], [ParseOptions, int]],
    parse_options_set_allow_null: [ref.types["void"], [ParseOptions, int]],
    parse_options_set_max_null_count: [ref.types["void"], [ParseOptions, int]],
    dictionary_create: [Dictionary, [string, string, string, string]],
    sentence_create: [Sentence, [string, Dictionary]],
    sentence_parse: [int, [Sentence, ParseOptions]],
    sentence_length: [int, [Sentence]],
    sentence_get_word: [string, [Sentence, int]],
    linkage_create: [Linkage, [int, Sentence, ParseOptions]],
    linkage_print_diagram: [string, [Linkage]],
    linkage_constituent_tree: [CNodePtr, [Linkage]],
    linkage_print_constituent_tree: [string, [Linkage, int]],
    linkage_get_num_links: [int, [Linkage]],
    linkage_get_link_label: [string, [Linkage, int]],
    linkage_get_link_llabel: [string, [Linkage, int]],
    linkage_get_link_rlabel: [string, [Linkage, int]],
    linkage_get_word: [string, [Linkage, int]],
    linkage_get_link_lword: [int, [Linkage, int]],
    linkage_get_link_rword: [int, [Linkage, int]]
  };

  libPath = __dirname + '/../lib/libparser';

  lib = ffi.Library(libPath, apiTemplate);

  defaultDataPath = __dirname + '/../data/';

  getNodePtrFromPtr = function(ptr) {
    var tempPtr;
    tempPtr = ref.alloc(CNodePtr);
    ref.writePointer(tempPtr, 0, ptr);
    return tempPtr.deref();
  };

  defaultConfig = {
    dictPath: defaultDataPath + '4.0.dict',
    ppPath: defaultDataPath + '4.0.knowledge',
    consPath: defaultDataPath + '4.0.constituent-knowledge',
    affixPath: defaultDataPath + '4.0.affix',
    verbose: false
  };

  LinkGrammar = (function() {
    function LinkGrammar(config) {
      this.config = _.extend(config || {}, defaultConfig);
      this.options = lib.parse_options_create();
      lib.parse_options_set_verbosity(this.options, (this.config.verbose ? 1 : 0));
      lib.parse_options_set_allow_null(this.options, 1);
      lib.parse_options_set_max_null_count(this.options, 3);
      this.dictionary = lib.dictionary_create(this.config.dictPath, this.config.ppPath, this.config.consPath, this.config.affixPath);
    }

    LinkGrammar.prototype.parse = function(input, index) {
      var numLinkages, sentence;
      sentence = lib.sentence_create(input, this.dictionary);
      numLinkages = lib.sentence_parse(sentence, this.options);
      if (numLinkages > 0) {
        return new Linkage(lib.linkage_create(index || 0, sentence, this.options));
      } else {
        throw new Error('No links found');
      }
    };

    return LinkGrammar;

  })();

  Linkage = (function() {
    function Linkage(linkage) {
      this.linkage = linkage;
      this.links = this.getLinks();
      this.tree = this.getTree();
      this.words = this.getWords();
    }

    Linkage.prototype.buildNode = function(node) {
      var n;
      n = {
        label: node.label
      };
      if (!ref.isNull(node.child)) {
        n.child = this.buildNode(getNodePtrFromPtr(node.child).deref());
      }
      if (!ref.isNull(node.next)) {
        n.next = this.buildNode(getNodePtrFromPtr(node.next).deref());
      }
      return n;
    };

    Linkage.prototype.getTree = function() {
      var rootPtr;
      rootPtr = lib.linkage_constituent_tree(this.linkage);
      return this.buildNode(rootPtr.deref(), this.linkage);
    };

    Linkage.prototype.getLinks = function() {
      return _(lib.linkage_get_num_links(this.linkage)).times((function(index) {
        var leftIndex, link, rightIndex, temp;
        leftIndex = lib.linkage_get_link_lword(this.linkage, index);
        rightIndex = lib.linkage_get_link_rword(this.linkage, index);
        link = {
          label: lib.linkage_get_link_label(this.linkage, index),
          left: {
            label: lib.linkage_get_link_llabel(this.linkage, index),
            word: lib.linkage_get_word(this.linkage, leftIndex),
            index: leftIndex
          },
          right: {
            label: lib.linkage_get_link_rlabel(this.linkage, index),
            word: lib.linkage_get_word(this.linkage, rightIndex),
            index: rightIndex
          }
        };
        if (link.left.word.indexOf('.' !== -1)) {
          temp = link.left.word.split('.');
          link.left.word = temp[0];
          link.left.type = temp[1];
        }
        if (link.right.word.indexOf('.' !== -1)) {
          temp = link.right.word.split('.');
          link.right.word = temp[0];
          link.right.type = temp[1];
        }
        return link;
      }), this);
    };

    Linkage.prototype.getWords = function() {
      return _.chain(this.links).map(function(link) {
        return [link.left, link.right];
      }).flatten().uniq(function(link) {
        return link.word;
      }).value();
    };

    Linkage.prototype.linksByLabel = function(labelPattern) {
      if (typeof labelPattern === 'string') {
        labelPattern = new RegExp(labelPattern);
      }
      return this.links.filter(function(link) {
        return labelPattern.test(link.left.label || labelPattern.test(link.right.label));
      });
    };

    Linkage.prototype.getConnectorWords = function(common) {
      var words;
      words = [];
      this.links.forEach(function(link) {
        if (link.left.word === common) {
          words.push({
            source: link.left,
            target: link.right
          });
        }
        if (link.right.word === common) {
          return words.push({
            source: link.right,
            target: link.left
          });
        }
      });
      return words;
    };

    return Linkage;

  })();

  module.exports = LinkGrammar;

}).call(this);
<commit_msg>Do not commite autogened build files<commit_after><|endoftext|>


<commit_before>/**
 * Created by zarges on 23/06/15.
 */
'use strict';
angular.module('mwResponseToastHandler', ['mwResponseHandler', 'mwI18n', 'mwToast'])

  .provider('ResponseToastHandler', function ($provide, ResponseHandlerProvider) {
    var _registeredIds = [],
      _registeredToastOptions = {
        DEFAULT: {
          type: 'default',
          autoHide: false
        }
      };

    var _getNotificationCallback = function (messages, id, options) {
      options = options || {};
      var factoryName = _.uniqueId('notification_factory');
      $provide.factory(factoryName, ['Toast', 'i18n', function (Toast, i18n) {
        return function ($httpResponse) {
          if(!messages){
            return;
          }

          var prevToast = Toast.findToast(id),
            data = {},
            messageStr = prevToast ? messages.plural : messages.singular,
            message,
            toastOptions = {
              id: id
            };

          if (!!prevToast && messages.plural) {
            messageStr = messages.plural;
          } else if (messages.singular) {
            messageStr = messages.singular;
          }

          data.$count = prevToast ? prevToast.replaceCount + 1 : 0;
          data.$count++;

          if (options.preProcess && typeof options.preProcess === 'function') {
            _.extend(data, $httpResponse.data);
            message = options.preProcess.call(this, messageStr, data, i18n, $httpResponse);
            if(!message){
              return;
            }
          } else {
            var resp = $httpResponse.data;

            if (resp.results && !_.isObject(resp.results)) {
              data = {message: resp.results};
            } else if (resp.results && resp.results.length > 0) {
              _.extend(data, resp.results[0]);
            }

            if ($httpResponse.config.instance && typeof $httpResponse.config.instance.toJSON === 'function') {
              var json = $httpResponse.config.instance.toJSON();
              _.extend(json, data);
              data = json;
            }

            message = i18n.get(messageStr, data);
          }

          if (options.toastType) {
            var opts = _registeredToastOptions[options.toastType];
            if (opts) {
              _.extend(toastOptions, opts);
            } else {
              throw new Error('Type ' + options.toastType + ' is not available. Make sure you have configured it first');
            }
          } else {
            _.extend(toastOptions, _registeredToastOptions.DEFAULT);
          }

          Toast.addToast(message, toastOptions);
        };
      }]);
      return factoryName;
    };

    this.registerToastType = function (typeId, toastOptions) {
      if (_registeredToastOptions[typeId]) {
        throw new Error('The toast type ' + typeId + ' is already defined. You can configure a toast type only once');
      } else {
        _registeredToastOptions[typeId] = toastOptions;
      }
    };

    this.registerToast = function (route, messages, options) {
      options = options || {};
      var codes = options.statusCodes || [options.onSuccess ? 'SUCCESS' : 'ERROR'];

      if (_.isUndefined(messages) || _.isObject(messages) && !messages.singular) {
        throw new Error('You have to pass a messages object and define at least the singular message {singular:"Mandatory", plural:"Optional"}');
      }

      codes.forEach(function (code) {
        var msgId = options.id || route + '_' + options.method + '_' + code,
          callbackFactory = _getNotificationCallback(messages, msgId, options);

        if (_registeredIds.indexOf(msgId) > -1) {
          throw new Error('You can not define a second message for the route ' + route + ' and method ' + options.method + ' because you have already registered one!');
        } else {
          if(code==='SUCCESS' || code ==='ERROR'){
            delete options.statusCodes;
          } else {
            options.statusCodes = [code];
          }
          ResponseHandlerProvider.registerAction(route, callbackFactory, options);
          _registeredIds.push(msgId);
        }
      });

    };

    this.registerSuccessToast = function (route, messages, method, toastType, preProcessFn) {
      this.registerToast(route, messages, {
        method: method,
        toastType: toastType,
        onSuccess: true,
        preProcess: preProcessFn
      });
    };

    this.registerErrorToast = function (route, messages, method, toastType, preProcessFn) {
      this.registerToast(route, messages, {
        method: method,
        toastType: toastType,
        onError: true,
        preProcess: preProcessFn
      });
    };

    this.registerDefaultSuccessToast = function (messages, method, toastType, preProcessFn) {
      return this.registerToast('*', messages, {
        method: method,
        toastType: toastType,
        onSuccess: true,
        preProcess: preProcessFn
      });
    };

    this.registerDefaultErrorToast = function (messages, method, toastType, preProcessFn) {
      return this.registerToast('*', messages, {
        method: method,
        toastType: toastType,
        onError: true,
        preProcess: preProcessFn
      });
    };

    this.$get = function () {
    };

  });<commit_msg>fixes bug when response data is null<commit_after>/**
 * Created by zarges on 23/06/15.
 */
'use strict';
angular.module('mwResponseToastHandler', ['mwResponseHandler', 'mwI18n', 'mwToast'])

  .provider('ResponseToastHandler', function ($provide, ResponseHandlerProvider) {
    var _registeredIds = [],
      _registeredToastOptions = {
        DEFAULT: {
          type: 'default',
          autoHide: false
        }
      };

    var _getNotificationCallback = function (messages, id, options) {
      options = options || {};
      var factoryName = _.uniqueId('notification_factory');
      $provide.factory(factoryName, ['Toast', 'i18n', function (Toast, i18n) {
        return function ($httpResponse) {
          if(!messages){
            return;
          }

          var prevToast = Toast.findToast(id),
            data = {},
            messageStr = prevToast ? messages.plural : messages.singular,
            message,
            toastOptions = {
              id: id
            };

          if (!!prevToast && messages.plural) {
            messageStr = messages.plural;
          } else if (messages.singular) {
            messageStr = messages.singular;
          }

          data.$count = prevToast ? prevToast.replaceCount + 1 : 0;
          data.$count++;

          if (options.preProcess && typeof options.preProcess === 'function') {
            _.extend(data, $httpResponse.data);
            message = options.preProcess.call(this, messageStr, data, i18n, $httpResponse);
            if(!message){
              return;
            }
          } else {
            var resp = $httpResponse.data || {};

            if (resp.results && !_.isObject(resp.results)) {
              data = {message: resp.results};
            } else if (resp.results && resp.results.length > 0) {
              _.extend(data, resp.results[0]);
            }

            if ($httpResponse.config.instance && typeof $httpResponse.config.instance.toJSON === 'function') {
              var json = $httpResponse.config.instance.toJSON();
              _.extend(json, data);
              data = json;
            }

            message = i18n.get(messageStr, data);
          }

          if (options.toastType) {
            var opts = _registeredToastOptions[options.toastType];
            if (opts) {
              _.extend(toastOptions, opts);
            } else {
              throw new Error('Type ' + options.toastType + ' is not available. Make sure you have configured it first');
            }
          } else {
            _.extend(toastOptions, _registeredToastOptions.DEFAULT);
          }

          Toast.addToast(message, toastOptions);
        };
      }]);
      return factoryName;
    };

    this.registerToastType = function (typeId, toastOptions) {
      if (_registeredToastOptions[typeId]) {
        throw new Error('The toast type ' + typeId + ' is already defined. You can configure a toast type only once');
      } else {
        _registeredToastOptions[typeId] = toastOptions;
      }
    };

    this.registerToast = function (route, messages, options) {
      options = options || {};
      var codes = options.statusCodes || [options.onSuccess ? 'SUCCESS' : 'ERROR'];

      if (_.isUndefined(messages) || _.isObject(messages) && !messages.singular) {
        throw new Error('You have to pass a messages object and define at least the singular message {singular:"Mandatory", plural:"Optional"}');
      }

      codes.forEach(function (code) {
        var msgId = options.id || route + '_' + options.method + '_' + code,
          callbackFactory = _getNotificationCallback(messages, msgId, options);

        if (_registeredIds.indexOf(msgId) > -1) {
          throw new Error('You can not define a second message for the route ' + route + ' and method ' + options.method + ' because you have already registered one!');
        } else {
          if(code==='SUCCESS' || code ==='ERROR'){
            delete options.statusCodes;
          } else {
            options.statusCodes = [code];
          }
          ResponseHandlerProvider.registerAction(route, callbackFactory, options);
          _registeredIds.push(msgId);
        }
      });

    };

    this.registerSuccessToast = function (route, messages, method, toastType, preProcessFn) {
      this.registerToast(route, messages, {
        method: method,
        toastType: toastType,
        onSuccess: true,
        preProcess: preProcessFn
      });
    };

    this.registerErrorToast = function (route, messages, method, toastType, preProcessFn) {
      this.registerToast(route, messages, {
        method: method,
        toastType: toastType,
        onError: true,
        preProcess: preProcessFn
      });
    };

    this.registerDefaultSuccessToast = function (messages, method, toastType, preProcessFn) {
      return this.registerToast('*', messages, {
        method: method,
        toastType: toastType,
        onSuccess: true,
        preProcess: preProcessFn
      });
    };

    this.registerDefaultErrorToast = function (messages, method, toastType, preProcessFn) {
      return this.registerToast('*', messages, {
        method: method,
        toastType: toastType,
        onError: true,
        preProcess: preProcessFn
      });
    };

    this.$get = function () {
    };

  });<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014-2016 SAP SE
 */

'use strict';

var path = require('path');
var moment = require('moment');
var semver = require('semver');

module.exports = function(grunt) {

	// Force unix linefeeds (see https://github.com/gruntjs/grunt/issues/1123)
	// (grunt uses grunt.util.normalizelf when processing templates)
	grunt.util.linefeed = '\n';

	// Log time how long tasks take
	require('grunt-timer').init(grunt, {
		deferLogs: true,
		color: 'cyan'
	});

	// Check for valid required Node.js version from package.json
	// npm does not validate this within the project itself; only if this project would be installed as a dependency (which is not the case as of now)
	var pkg = grunt.file.readJSON(__dirname + "/package.json");
	if (pkg.engines && pkg.engines.node && !semver.satisfies(process.version, pkg.engines.node)) {
		grunt.log.error('!!! WARNING !!!');
		grunt.log.error('Unsupported Node.js version: wanted "' + pkg.engines.node + '" (current: "' + process.version + '")');
		grunt.log.error('Please update your Node.js installation!');
	}

	// Load all custom tasks from grunt/tasks dir
	grunt.loadTasks(path.join(process.cwd(), 'grunt/tasks'));

	// set default options
	grunt.option('production', grunt.option('production') || false);
	if (typeof grunt.option('minify-css') === 'undefined') {
		grunt.option('minify-css', grunt.option('production'));
	}
	if (typeof grunt.option('include-test-resources') === 'undefined') {
		grunt.option('include-test-resources', grunt.option('no-production'));
	}

	// set of libraries to use (e.g. --libs=sap.ui.core)
	var libsOption = grunt.option('libs');
	var libs = libsOption ? libsOption.split(',') : null;

	// the gruntdata contains the configuration for the build part
	// we distinguish here between a testsuite which is an application
	// and the libraries which are the re-use modules
	var gruntData = {

		buildtime: moment().utc().format('YYYYMMDDHHmmss'),
		lastchange: '',

		testsuite: {
			name: 'testsuite',
			path: 'src/testsuite'
		},
		allLibraries: [
			{
					name: 'sap.ui.core',
					path: 'src/sap.ui.core',
					preload: {
						src: [

							'*.js',

							// files are already part of sap-ui-core.js
							'!sap/ui/thirdparty/es6-promise.js',
							'!jquery.sap.global.js',
							'!sap-ui-*.js',

							'sap/ui/core/**',
							'!sap/ui/core/cldr/**',
							'!sap/ui/core/messagebundle*',

							'sap/ui/base/**',
							'sap/ui/model/**',
							'sap/ui/Global.js'
						]
					}
			},
			{
					name: 'sap.ui.unified',
					path: 'src/sap.ui.unified'
			},
			{
					name: 'sap.ui.layout',
					path: 'src/sap.ui.layout'
			},
			{
					name: 'sap.m',
					path: 'src/sap.m'
			},
			{
					name: 'sap.tnt',
					path: 'src/sap.tnt'
			},
			{
					name: 'sap.f',
					path: 'src/sap.f'
			},
			{
					name: 'sap.ui.commons',
					path: 'src/sap.ui.commons'
			},
			{
					name: 'sap.ui.table',
					path: 'src/sap.ui.table'
			},
			{
					name: 'sap.ui.ux3',
					path: 'src/sap.ui.ux3'
			},
			{
					name: 'sap.ui.suite',
					path: 'src/sap.ui.suite'
			},
			{
					name: 'sap.ui.dt',
					path: 'src/sap.ui.dt'
			},
			{
					name: 'sap.uxap',
					path: 'src/sap.uxap'
			},
			{
					name: 'sap.ui.fl',
					path: 'src/sap.ui.fl'
			},
			{
					name: 'themelib_sap_bluecrystal',
					path: 'src/themelib_sap_bluecrystal',
					type: 'theme'
			},
			{
					name: 'themelib_sap_goldreflection',
					path: 'src/themelib_sap_goldreflection',
					type: 'theme'
			},
			{
					name: 'themelib_sap_belize',
					path: 'src/themelib_sap_belize',
					type: 'theme'
			},
			{
					name: 'sap.ui.demokit',
					path: 'src/sap.ui.demokit',
					bower: false // exclude from bower publish
			}
		]

	};

	// Load config extension script to allow overrides to "grunt" and "gruntData"
	var configExtensionFile = grunt.option("config-extension");
	if (configExtensionFile) {
		require(__dirname + "/" + configExtensionFile)(grunt, gruntData);
	}

	// determine set of libraries to use (specified by --libs option)
	gruntData.libraries = !libs ? gruntData.allLibraries : gruntData.allLibraries.filter(function(library) {
		return libs.indexOf(library.name) > -1;
	});

	// Load all grunt config files (in grunt subfolder) and all tasks installed via npm
	require('load-grunt-config')(grunt, {

		configPath: path.join(process.cwd(), 'grunt/config'),

		// loads grunt plugins just-in-time (faster than using load-grunt-tasks)
		jitGrunt: {
			staticMappings: {
				'replace': 'grunt-text-replace',
				'openui5_connect': 'grunt-openui5',
				'openui5_theme': 'grunt-openui5',
				'openui5_preload': 'grunt-openui5',
				'gitclone': 'grunt-git',
				'gitadd': 'grunt-git',
				'gitcommit': 'grunt-git',
				'gittag': 'grunt-git',
				'gitpush': 'grunt-git'
			}
		},

		data: gruntData

	});

};
<commit_msg>[INTERNAL] Proper path determination for custom Grunt configs<commit_after>/*
 * Copyright (c) 2014-2016 SAP SE
 */

'use strict';

var path = require('path');
var moment = require('moment');
var semver = require('semver');

module.exports = function(grunt) {

	// Force unix linefeeds (see https://github.com/gruntjs/grunt/issues/1123)
	// (grunt uses grunt.util.normalizelf when processing templates)
	grunt.util.linefeed = '\n';

	// Log time how long tasks take
	require('grunt-timer').init(grunt, {
		deferLogs: true,
		color: 'cyan'
	});

	// Check for valid required Node.js version from package.json
	// npm does not validate this within the project itself; only if this project would be installed as a dependency (which is not the case as of now)
	var pkg = grunt.file.readJSON(__dirname + "/package.json");
	if (pkg.engines && pkg.engines.node && !semver.satisfies(process.version, pkg.engines.node)) {
		grunt.log.error('!!! WARNING !!!');
		grunt.log.error('Unsupported Node.js version: wanted "' + pkg.engines.node + '" (current: "' + process.version + '")');
		grunt.log.error('Please update your Node.js installation!');
	}

	// Load all custom tasks from grunt/tasks dir
	grunt.loadTasks(path.join(process.cwd(), 'grunt/tasks'));

	// set default options
	grunt.option('production', grunt.option('production') || false);
	if (typeof grunt.option('minify-css') === 'undefined') {
		grunt.option('minify-css', grunt.option('production'));
	}
	if (typeof grunt.option('include-test-resources') === 'undefined') {
		grunt.option('include-test-resources', grunt.option('no-production'));
	}

	// set of libraries to use (e.g. --libs=sap.ui.core)
	var libsOption = grunt.option('libs');
	var libs = libsOption ? libsOption.split(',') : null;

	// the gruntdata contains the configuration for the build part
	// we distinguish here between a testsuite which is an application
	// and the libraries which are the re-use modules
	var gruntData = {

		buildtime: moment().utc().format('YYYYMMDDHHmmss'),
		lastchange: '',

		testsuite: {
			name: 'testsuite',
			path: 'src/testsuite'
		},
		allLibraries: [
			{
					name: 'sap.ui.core',
					path: 'src/sap.ui.core',
					preload: {
						src: [

							'*.js',

							// files are already part of sap-ui-core.js
							'!sap/ui/thirdparty/es6-promise.js',
							'!jquery.sap.global.js',
							'!sap-ui-*.js',

							'sap/ui/core/**',
							'!sap/ui/core/cldr/**',
							'!sap/ui/core/messagebundle*',

							'sap/ui/base/**',
							'sap/ui/model/**',
							'sap/ui/Global.js'
						]
					}
			},
			{
					name: 'sap.ui.unified',
					path: 'src/sap.ui.unified'
			},
			{
					name: 'sap.ui.layout',
					path: 'src/sap.ui.layout'
			},
			{
					name: 'sap.m',
					path: 'src/sap.m'
			},
			{
					name: 'sap.tnt',
					path: 'src/sap.tnt'
			},
			{
					name: 'sap.f',
					path: 'src/sap.f'
			},
			{
					name: 'sap.ui.commons',
					path: 'src/sap.ui.commons'
			},
			{
					name: 'sap.ui.table',
					path: 'src/sap.ui.table'
			},
			{
					name: 'sap.ui.ux3',
					path: 'src/sap.ui.ux3'
			},
			{
					name: 'sap.ui.suite',
					path: 'src/sap.ui.suite'
			},
			{
					name: 'sap.ui.dt',
					path: 'src/sap.ui.dt'
			},
			{
					name: 'sap.uxap',
					path: 'src/sap.uxap'
			},
			{
					name: 'sap.ui.fl',
					path: 'src/sap.ui.fl'
			},
			{
					name: 'themelib_sap_bluecrystal',
					path: 'src/themelib_sap_bluecrystal',
					type: 'theme'
			},
			{
					name: 'themelib_sap_goldreflection',
					path: 'src/themelib_sap_goldreflection',
					type: 'theme'
			},
			{
					name: 'themelib_sap_belize',
					path: 'src/themelib_sap_belize',
					type: 'theme'
			},
			{
					name: 'sap.ui.demokit',
					path: 'src/sap.ui.demokit',
					bower: false // exclude from bower publish
			}
		]

	};

	// Load config extension script to allow overrides to "grunt" and "gruntData"
	var configExtensionFile = grunt.option("config-extension");
	if (configExtensionFile) {
		require(path.resolve(configExtensionFile))(grunt, gruntData);
	}

	// determine set of libraries to use (specified by --libs option)
	gruntData.libraries = !libs ? gruntData.allLibraries : gruntData.allLibraries.filter(function(library) {
		return libs.indexOf(library.name) > -1;
	});

	// Load all grunt config files (in grunt subfolder) and all tasks installed via npm
	require('load-grunt-config')(grunt, {

		configPath: path.join(process.cwd(), 'grunt/config'),

		// loads grunt plugins just-in-time (faster than using load-grunt-tasks)
		jitGrunt: {
			staticMappings: {
				'replace': 'grunt-text-replace',
				'openui5_connect': 'grunt-openui5',
				'openui5_theme': 'grunt-openui5',
				'openui5_preload': 'grunt-openui5',
				'gitclone': 'grunt-git',
				'gitadd': 'grunt-git',
				'gitcommit': 'grunt-git',
				'gittag': 'grunt-git',
				'gitpush': 'grunt-git'
			}
		},

		data: gruntData

	});

};
<|endoftext|>


<commit_before>/**
 * @class Navy.View.View
 * @eventNames link, sizeChanged, posChanged
 */
Navy.Class('Navy.View.View', Navy.EventTarget, {
  SIZE_POLICY_FIXED: 'fixed',
  SIZE_POLICY_WRAP_CONTENT: 'wrapContent',
  SIZE_POLICY_MATCH_PARENT: 'matchParent',

  _id: null,
  _page: null,
  _scene: null,
  _layout: null,
  _element: null,
  _parentView: null,

  _linkGesture: null,

  /**
   *
   * @param {function} $super
   * @param {function} callback
   * @param {ViewLayout} layout
   */
  initialize: function($super, layout, callback) {
    $super();

    this._preventDOMEvent = this._preventDOMEvent.bind(this);

    if (layout) {
      this._id = layout.id;
    }

    this._layout = layout;

    this._createElement(layout);
    this._createExtraElement(layout);

    this.setLayout(layout, callback);
  },

  setLayout: function(layout, callback) {
    if (!layout) {
      return;
    }

    function onLoadResource() {
      var notify = new Navy.Notify(2, onApplyLayout.bind(this));
      var pass = notify.pass.bind(notify);
      this._applyLayout(layout, pass);
      this._applyExtraLayout(layout, pass);
    }

    function onApplyLayout() {
      this._updateSizeWithWrapContentSize();
      callback && callback(this);
    }

    this._layout = layout;
    var notify = new Navy.Notify(2, onLoadResource.bind(this));
    var pass = notify.pass.bind(notify);
    this._loadResource(layout, pass);
    this._loadExtraResource(layout, pass);
  },

  getLayout: function() {
    return this._cloneObject(this._layout);
  },

  lockView: function() {
    this._element.addEventListener('touchstart', this._preventDOMEvent, true);
  },

  unlockView: function() {
    this._element.removeEventListener('touchstart', this._preventDOMEvent, true);
  },

  _preventDOMEvent: function(ev) {
    ev.stopPropagation();
    ev.preventDefault();
  },

  _createElement: function(layout) {
    this._element = document.createElement('div');
    this._element.style.visibility = 'hidden';

    this._linkGesture = new Navy.Gesture.Tap(this._element, this._onLink.bind(this));
  },

  _applyLayout: function(layout, callback) {
    this._element.style.position = 'absolute';

    this.setVisible(layout.visible);
    this.setPos(layout.pos);
    this.setSizePolicy(layout.sizePolicy, true);
    this.setSize(layout.size);
    this.setBackgroundColor(layout.backgroundColor);
    this.setBorder(layout.border);
    this.setPadding(layout.padding);
    this.setLink(layout.link);

    this._setRawStyle({overflow:'hidden'});

    callback && setTimeout(callback, 0);
  },

  _loadResource: function(layout, callback) {
    callback && setTimeout(callback, 0);
  },

  /**
   * @forOverride
   * @param layout
   * @private
   */
  _createExtraElement: function(layout) {
  },

  /**
   * @forOverride
   * @param layout
   * @param callback
   * @private
   */
  _applyExtraLayout: function(layout, callback) {
    callback && setTimeout(callback, 0);
  },

  /**
   * @forOverride
   * @param layout
   * @param callback
   * @private
   */
  _loadExtraResource: function(layout, callback) {
    callback && setTimeout(callback, 0);
  },

  /**
   * @forOverride
   * @private
   */
  _calcWrapContentSize: function() {
    return {width: 0, height: 0};
  },

  _updateSizeWithWrapContentSize: function() {
    var changed = false;
    var size;

    if (this._layout.sizePolicy.width === this.SIZE_POLICY_WRAP_CONTENT || this._layout.sizePolicy.height === this.SIZE_POLICY_WRAP_CONTENT) {
      size = this._calcWrapContentSize();
    }

    if (this._layout.sizePolicy.width === this.SIZE_POLICY_WRAP_CONTENT) {
      this._element.style.width = size.width + 'px';
      changed = true;
    }

    if (this._layout.sizePolicy.height === this.SIZE_POLICY_WRAP_CONTENT) {
      this._element.style.height = size.height + 'px';
      changed = true
    }

    if (changed) {
      this.trigger('SizeChanged');
    }
  },

  _setRawStyle: function(style) {
    var cssText = '';
    for (var key in style) {
      var value = style[key];
      if (value !== undefined) {
        var propertyName = key.replace(/([A-Z])/g, '-$1').toLowerCase();
        if (propertyName.indexOf('webkit') === 0) {
          propertyName = '-' + propertyName;
        }

        if (value === '') {
          this._element.style[key] = '';
        } else {
          cssText += propertyName + ':' + value + ';';
        }
      }
    }

    this._element.style.cssText += cssText;
  },

  _onLink: function(ev) {
    // TODO: Navy.Eventオブジェクトを作る.
    this.trigger('Link');

    // TODO: evがpreventDefault的なことをされていれば遷移しないようにする.
    var tmp = this._layout.link.id.split('/');
    var type = tmp[0];
    var id = tmp[1];

    switch (type) {
    case 'page':
      this.getScene().linkPage(id);
      break;
    case 'scene':
      Navy.Root.linkScene(id);
      break;
    }
  },

  addRawEventListener: function(eventName, callback) {
    this._element.addEventListener(eventName, callback);
  },

  removeRawEventListener: function(eventName, callback) {
    this._element.removeEventListener(eventName, callback);
  },

  getId: function(){
    return this._id;
  },

  setPage: function(page) {
    this._page = page;
  },

  getPage: function() {
    return this._page;
  },

  setScene: function(scene) {
    this._scene = scene;
  },

  getScene: function() {
    return this._scene;
  },

  getElement: function(){
    return this._element;
  },

  setParent: function(parentView) {
    this._parentView = parentView;
  },

  getParent: function() {
    return this._parentView;
  },

  destroy: function() {
    this._parentView.removeView(this);

    var names = Object.getOwnPropertyNames(this);
    for (var i = 0; i < names.length; i++) {
      this[names[i]] = null;
    }
  },

  toJSON: function() {
    return this._layout;
  },

  _cloneObject: function(obj) {
    return JSON.parse(JSON.stringify(obj));
  },

  /*
   * Viewのレイアウトに関するメソッド群
   */

  isVisible: function() {
    if (!this._layout.visible) {
      return false;
    }

    for (var parent = this.getParent(); parent; parent = parent.getParent()) {
      if (!parent.isVisible()) {
        return false;
      }
    }

    return true;
  },

  setVisible: function(visible) {
    this._layout.visible = visible;

    if (visible) {
      this._element.style.visibility = '';
    } else {
      this._element.style.visibility = 'hidden';
    }
  },

  setBackgroundColor: function(backgroundColor) {
    this._layout.backgroundColor = backgroundColor;
    this._element.style.backgroundColor = backgroundColor;
  },

  getBackgroundColor: function() {
    return this._layout.backgroundColor;
  },

  setBorder: function(border) {
    this._layout.border = border;
    this._element.style.border = border;
  },

  getBorder: function() {
    return this._layout.border;
  },

  getBorderSize: function() {
    var size = {left: 0, top: 0, right: 0, bottom: 0};
    var style = this._element.style;

    if (style.borderLeftStyle !== 'hidden' && style.borderLeftStyle !== 'none') {
      size.left = parseInt(style.borderLeftWidth, 10) || 0;
    }

    if (style.borderRightStyle !== 'hidden' && style.borderRightStyle !== 'none') {
      size.right = parseInt(style.borderRightWidth, 10) || 0;
    }

    if (style.borderTopStyle !== 'hidden' && style.borderTopStyle !== 'none') {
      size.top = parseInt(style.borderTopWidth, 10) || 0;
    }

    if (style.borderBottomStyle !== 'hidden' && style.borderBottomStyle !== 'none') {
      size.bottom = parseInt(style.borderBottomWidth, 10) || 0;
    }

    return size;
  },

  setPadding: function(padding) {
    this._layout.padding = padding;
    this._element.style.padding = padding;
  },

  getPadding: function() {
    return this._layout.padding;
  },

  getPaddingSize: function() {
    var size = {};
    var style = this._element.style;
    size.left = parseInt(style.paddingLeft, 10) || 0;
    size.top = parseInt(style.paddingTop, 10) || 0;
    size.right = parseInt(style.paddingRight, 10) || 0;
    size.bottom = parseInt(style.paddingBottom, 10) || 0;

    return size;
  },

  setSizePolicy: function(sizePolicy, disableUpdateSizeWithWrapContentSize) {
    this._layout.sizePolicy = sizePolicy;

    switch (sizePolicy.width) {
    case this.SIZE_POLICY_FIXED:
      break;
    case this.SIZE_POLICY_WRAP_CONTENT:
      if (!disableUpdateSizeWithWrapContentSize) {
        this._updateSizeWithWrapContentSize();
      }
      break;
    case this.SIZE_POLICY_MATCH_PARENT:
      this._element.style.width = '100%';
      break;
    default:
      throw new Error('unknown size policy width. ' + this._layout.sizePolicy.width);
    }

    switch (sizePolicy.height) {
    case this.SIZE_POLICY_FIXED:
      break;
    case this.SIZE_POLICY_WRAP_CONTENT:
      if (!disableUpdateSizeWithWrapContentSize) {
        this._updateSizeWithWrapContentSize();
      }
      break;
    case this.SIZE_POLICY_MATCH_PARENT:
      this._element.style.height = '100%';
      break;
    default:
      throw new Error('unknown size policy height. ' + this._layout.sizePolicy.height);
    }
  },

  getSizePolicy: function() {
    return this._cloneObject(this._layout.sizePolicy);
  },

  getSize: function() {
    var width, height;

    switch (this._layout.sizePolicy.width) {
    case this.SIZE_POLICY_FIXED:
      width = this._layout.size.width;
      break;
    case this.SIZE_POLICY_WRAP_CONTENT:
      width = this._element.offsetWidth;
      break;
    case this.SIZE_POLICY_MATCH_PARENT:
      width = this._element.offsetWidth;
      break;
    default:
      throw new Error('unknown size policy width. ' + this._layout.sizePolicy.width);
    }

    switch (this._layout.sizePolicy.height) {
    case this.SIZE_POLICY_FIXED:
      height = this._layout.size.height;
      break;
    case this.SIZE_POLICY_WRAP_CONTENT:
      height = this._element.offsetHeight;
      break;
    case this.SIZE_POLICY_MATCH_PARENT:
      height = this._element.offsetHeight;
      break;
    default:
      throw new Error('unknown size policy height. ' + this._layout.sizePolicy.height);
    }

    return {width: width, height: height};
  },

  setSize: function(size) {
    if (!size) {
      return;
    }

    if (!this._layout.size) {
      this._layout.size = {};
    }

    if (this._layout.sizePolicy.width === this.SIZE_POLICY_FIXED) {
      if (typeof size.width === 'number') {
        this._layout.size.width = size.width;
        this._element.style.width = size.width + 'px';
      }
    }

    if (this._layout.sizePolicy.height === this.SIZE_POLICY_FIXED) {
      if (typeof size.height === 'number') {
        this._layout.size.height = size.height;
        this._element.style.height = size.height + 'px';
      }
    }

    // TODO: Eventオブジェクト作る.
    this.trigger('SizeChanged');
  },

  setPos: function(pos) {
    var cssText = '';

    if (typeof pos.x === 'number') {
      var x = parseInt(pos.x, 10);
      this._layout.pos.x = x;
      cssText += 'left:' + x + 'px;';
    }

    if (typeof pos.y === 'number') {
      var y = parseInt(pos.y, 10);
      this._layout.pos.y = y;
      cssText += 'top:' + y + 'px;';
    }

    if (typeof pos.z === 'number') {
      var z = parseInt(pos.z, 10);
      this._layout.pos.z = z;
      cssText += 'z-index:' + z + ';';
    }

    this._element.style.cssText += cssText;

    // TODO: Eventオブジェクト作る.
    this.trigger('PosChanged');
  },

  addPos: function(deltaPos) {
    var x = this._layout.pos.x + (deltaPos.x || 0);
    var y = this._layout.pos.y + (deltaPos.y || 0);
    this.setPos({x: x, y: y});
  },

  getPos: function() {
    return this._cloneObject(this._layout.pos);
  },

  setLink: function(link) {
    this._layout.link = link;

    if (link) {
      this._linkGesture.start();
    } else {
      this._linkGesture.stop();
    }
  },

  getLink: function() {
    return this._cloneObject(this._layout.link);
  }
});
<commit_msg>遷移時をふっくできるようにした.<commit_after>/**
 * @class Navy.View.View
 * @eventNames link, sizeChanged, posChanged
 */
Navy.Class('Navy.View.View', Navy.EventTarget, {
  SIZE_POLICY_FIXED: 'fixed',
  SIZE_POLICY_WRAP_CONTENT: 'wrapContent',
  SIZE_POLICY_MATCH_PARENT: 'matchParent',

  _id: null,
  _page: null,
  _scene: null,
  _layout: null,
  _element: null,
  _parentView: null,

  _linkGesture: null,

  /**
   *
   * @param {function} $super
   * @param {function} callback
   * @param {ViewLayout} layout
   */
  initialize: function($super, layout, callback) {
    $super();

    this._preventDOMEvent = this._preventDOMEvent.bind(this);

    if (layout) {
      this._id = layout.id;
    }

    this._layout = layout;

    this._createElement(layout);
    this._createExtraElement(layout);

    this.setLayout(layout, callback);
  },

  setLayout: function(layout, callback) {
    if (!layout) {
      return;
    }

    function onLoadResource() {
      var notify = new Navy.Notify(2, onApplyLayout.bind(this));
      var pass = notify.pass.bind(notify);
      this._applyLayout(layout, pass);
      this._applyExtraLayout(layout, pass);
    }

    function onApplyLayout() {
      this._updateSizeWithWrapContentSize();
      callback && callback(this);
    }

    this._layout = layout;
    var notify = new Navy.Notify(2, onLoadResource.bind(this));
    var pass = notify.pass.bind(notify);
    this._loadResource(layout, pass);
    this._loadExtraResource(layout, pass);
  },

  getLayout: function() {
    return this._cloneObject(this._layout);
  },

  lockView: function() {
    this._element.addEventListener('touchstart', this._preventDOMEvent, true);
  },

  unlockView: function() {
    this._element.removeEventListener('touchstart', this._preventDOMEvent, true);
  },

  _preventDOMEvent: function(ev) {
    ev.stopPropagation();
    ev.preventDefault();
  },

  _createElement: function(layout) {
    this._element = document.createElement('div');
    this._element.style.visibility = 'hidden';

    this._linkGesture = new Navy.Gesture.Tap(this._element, this._onLink.bind(this));
  },

  _applyLayout: function(layout, callback) {
    this._element.style.position = 'absolute';

    this.setVisible(layout.visible);
    this.setPos(layout.pos);
    this.setSizePolicy(layout.sizePolicy, true);
    this.setSize(layout.size);
    this.setBackgroundColor(layout.backgroundColor);
    this.setBorder(layout.border);
    this.setPadding(layout.padding);
    this.setLink(layout.link);

    this._setRawStyle({overflow:'hidden'});

    callback && setTimeout(callback, 0);
  },

  _loadResource: function(layout, callback) {
    callback && setTimeout(callback, 0);
  },

  /**
   * @forOverride
   * @param layout
   * @private
   */
  _createExtraElement: function(layout) {
  },

  /**
   * @forOverride
   * @param layout
   * @param callback
   * @private
   */
  _applyExtraLayout: function(layout, callback) {
    callback && setTimeout(callback, 0);
  },

  /**
   * @forOverride
   * @param layout
   * @param callback
   * @private
   */
  _loadExtraResource: function(layout, callback) {
    callback && setTimeout(callback, 0);
  },

  /**
   * @forOverride
   * @private
   */
  _calcWrapContentSize: function() {
    return {width: 0, height: 0};
  },

  _updateSizeWithWrapContentSize: function() {
    var changed = false;
    var size;

    if (this._layout.sizePolicy.width === this.SIZE_POLICY_WRAP_CONTENT || this._layout.sizePolicy.height === this.SIZE_POLICY_WRAP_CONTENT) {
      size = this._calcWrapContentSize();
    }

    if (this._layout.sizePolicy.width === this.SIZE_POLICY_WRAP_CONTENT) {
      this._element.style.width = size.width + 'px';
      changed = true;
    }

    if (this._layout.sizePolicy.height === this.SIZE_POLICY_WRAP_CONTENT) {
      this._element.style.height = size.height + 'px';
      changed = true
    }

    if (changed) {
      this.trigger('SizeChanged');
    }
  },

  _setRawStyle: function(style) {
    var cssText = '';
    for (var key in style) {
      var value = style[key];
      if (value !== undefined) {
        var propertyName = key.replace(/([A-Z])/g, '-$1').toLowerCase();
        if (propertyName.indexOf('webkit') === 0) {
          propertyName = '-' + propertyName;
        }

        if (value === '') {
          this._element.style[key] = '';
        } else {
          cssText += propertyName + ':' + value + ';';
        }
      }
    }

    this._element.style.cssText += cssText;
  },

  _onLink: function(/* domEvent */) {
    var linkId = this._layout.link.id;

    var defaultCallback = function() {
      var tmp = linkId.split('/');
      var type = tmp[0];
      var id = tmp[1];

      switch (type) {
      case 'page':
        this.getScene().linkPage(id);
        break;
      case 'scene':
        Navy.Root.linkScene(id);
        break;
      }
    }.bind(this);

    this.trigger('Link', {linkId: linkId}, null, defaultCallback);
  },

  addRawEventListener: function(eventName, callback) {
    this._element.addEventListener(eventName, callback);
  },

  removeRawEventListener: function(eventName, callback) {
    this._element.removeEventListener(eventName, callback);
  },

  getId: function(){
    return this._id;
  },

  setPage: function(page) {
    this._page = page;
  },

  getPage: function() {
    return this._page;
  },

  setScene: function(scene) {
    this._scene = scene;
  },

  getScene: function() {
    return this._scene;
  },

  getElement: function(){
    return this._element;
  },

  setParent: function(parentView) {
    this._parentView = parentView;
  },

  getParent: function() {
    return this._parentView;
  },

  destroy: function() {
    this._parentView.removeView(this);

    var names = Object.getOwnPropertyNames(this);
    for (var i = 0; i < names.length; i++) {
      this[names[i]] = null;
    }
  },

  toJSON: function() {
    return this._layout;
  },

  _cloneObject: function(obj) {
    return JSON.parse(JSON.stringify(obj));
  },

  /*
   * Viewのレイアウトに関するメソッド群
   */

  isVisible: function() {
    if (!this._layout.visible) {
      return false;
    }

    for (var parent = this.getParent(); parent; parent = parent.getParent()) {
      if (!parent.isVisible()) {
        return false;
      }
    }

    return true;
  },

  setVisible: function(visible) {
    this._layout.visible = visible;

    if (visible) {
      this._element.style.visibility = '';
    } else {
      this._element.style.visibility = 'hidden';
    }
  },

  setBackgroundColor: function(backgroundColor) {
    this._layout.backgroundColor = backgroundColor;
    this._element.style.backgroundColor = backgroundColor;
  },

  getBackgroundColor: function() {
    return this._layout.backgroundColor;
  },

  setBorder: function(border) {
    this._layout.border = border;
    this._element.style.border = border;
  },

  getBorder: function() {
    return this._layout.border;
  },

  getBorderSize: function() {
    var size = {left: 0, top: 0, right: 0, bottom: 0};
    var style = this._element.style;

    if (style.borderLeftStyle !== 'hidden' && style.borderLeftStyle !== 'none') {
      size.left = parseInt(style.borderLeftWidth, 10) || 0;
    }

    if (style.borderRightStyle !== 'hidden' && style.borderRightStyle !== 'none') {
      size.right = parseInt(style.borderRightWidth, 10) || 0;
    }

    if (style.borderTopStyle !== 'hidden' && style.borderTopStyle !== 'none') {
      size.top = parseInt(style.borderTopWidth, 10) || 0;
    }

    if (style.borderBottomStyle !== 'hidden' && style.borderBottomStyle !== 'none') {
      size.bottom = parseInt(style.borderBottomWidth, 10) || 0;
    }

    return size;
  },

  setPadding: function(padding) {
    this._layout.padding = padding;
    this._element.style.padding = padding;
  },

  getPadding: function() {
    return this._layout.padding;
  },

  getPaddingSize: function() {
    var size = {};
    var style = this._element.style;
    size.left = parseInt(style.paddingLeft, 10) || 0;
    size.top = parseInt(style.paddingTop, 10) || 0;
    size.right = parseInt(style.paddingRight, 10) || 0;
    size.bottom = parseInt(style.paddingBottom, 10) || 0;

    return size;
  },

  setSizePolicy: function(sizePolicy, disableUpdateSizeWithWrapContentSize) {
    this._layout.sizePolicy = sizePolicy;

    switch (sizePolicy.width) {
    case this.SIZE_POLICY_FIXED:
      break;
    case this.SIZE_POLICY_WRAP_CONTENT:
      if (!disableUpdateSizeWithWrapContentSize) {
        this._updateSizeWithWrapContentSize();
      }
      break;
    case this.SIZE_POLICY_MATCH_PARENT:
      this._element.style.width = '100%';
      break;
    default:
      throw new Error('unknown size policy width. ' + this._layout.sizePolicy.width);
    }

    switch (sizePolicy.height) {
    case this.SIZE_POLICY_FIXED:
      break;
    case this.SIZE_POLICY_WRAP_CONTENT:
      if (!disableUpdateSizeWithWrapContentSize) {
        this._updateSizeWithWrapContentSize();
      }
      break;
    case this.SIZE_POLICY_MATCH_PARENT:
      this._element.style.height = '100%';
      break;
    default:
      throw new Error('unknown size policy height. ' + this._layout.sizePolicy.height);
    }
  },

  getSizePolicy: function() {
    return this._cloneObject(this._layout.sizePolicy);
  },

  getSize: function() {
    var width, height;

    switch (this._layout.sizePolicy.width) {
    case this.SIZE_POLICY_FIXED:
      width = this._layout.size.width;
      break;
    case this.SIZE_POLICY_WRAP_CONTENT:
      width = this._element.offsetWidth;
      break;
    case this.SIZE_POLICY_MATCH_PARENT:
      width = this._element.offsetWidth;
      break;
    default:
      throw new Error('unknown size policy width. ' + this._layout.sizePolicy.width);
    }

    switch (this._layout.sizePolicy.height) {
    case this.SIZE_POLICY_FIXED:
      height = this._layout.size.height;
      break;
    case this.SIZE_POLICY_WRAP_CONTENT:
      height = this._element.offsetHeight;
      break;
    case this.SIZE_POLICY_MATCH_PARENT:
      height = this._element.offsetHeight;
      break;
    default:
      throw new Error('unknown size policy height. ' + this._layout.sizePolicy.height);
    }

    return {width: width, height: height};
  },

  setSize: function(size) {
    if (!size) {
      return;
    }

    if (!this._layout.size) {
      this._layout.size = {};
    }

    if (this._layout.sizePolicy.width === this.SIZE_POLICY_FIXED) {
      if (typeof size.width === 'number') {
        this._layout.size.width = size.width;
        this._element.style.width = size.width + 'px';
      }
    }

    if (this._layout.sizePolicy.height === this.SIZE_POLICY_FIXED) {
      if (typeof size.height === 'number') {
        this._layout.size.height = size.height;
        this._element.style.height = size.height + 'px';
      }
    }

    // TODO: Eventオブジェクト作る.
    this.trigger('SizeChanged');
  },

  setPos: function(pos) {
    var cssText = '';

    if (typeof pos.x === 'number') {
      var x = parseInt(pos.x, 10);
      this._layout.pos.x = x;
      cssText += 'left:' + x + 'px;';
    }

    if (typeof pos.y === 'number') {
      var y = parseInt(pos.y, 10);
      this._layout.pos.y = y;
      cssText += 'top:' + y + 'px;';
    }

    if (typeof pos.z === 'number') {
      var z = parseInt(pos.z, 10);
      this._layout.pos.z = z;
      cssText += 'z-index:' + z + ';';
    }

    this._element.style.cssText += cssText;

    // TODO: Eventオブジェクト作る.
    this.trigger('PosChanged');
  },

  addPos: function(deltaPos) {
    var x = this._layout.pos.x + (deltaPos.x || 0);
    var y = this._layout.pos.y + (deltaPos.y || 0);
    this.setPos({x: x, y: y});
  },

  getPos: function() {
    return this._cloneObject(this._layout.pos);
  },

  setLink: function(link) {
    this._layout.link = link;

    if (link) {
      this._linkGesture.start();
    } else {
      this._linkGesture.stop();
    }
  },

  getLink: function() {
    return this._cloneObject(this._layout.link);
  }
});
<|endoftext|>


<commit_before>var _ = require('lodash');

var getRequirejsConfig = function () {
  var requirejsConfig;
  // Define a temporary function so that we can 'read' in the application settings.
  // The settings file assumes the existence of a function called 'define'.
  global.define = function (config) {
    requirejsConfig = config({ isBuild: true });
  };
  // Read the settings
  require('./app/config');
  // Remove the function
  delete global.define;

  return _.extend(requirejsConfig, {
    baseUrl: 'app',
    name: 'client',
    waitSeconds: 60,
    include: ['vendor/almond'],
    deps: [
      'client',
      'client/client_bootstrap',
      'client/logger'
    ],
    wrap: true,
    optimize: 'uglify'
  });
};

var addArgs = function (cmd) {
  return function () {
    return [cmd].concat([].slice.apply(arguments)).join(' ');
  };
};

var requirejsConfig = getRequirejsConfig();

module.exports = function (grunt) {
  'use strict';

  grunt.initConfig({
    // Removes the contents of the public directory
    clean: ['public/'],
    // Builds Sass in development and production
    sass: {
      development: {
        files: {
          'public/stylesheets/spotlight.css': 'styles/index.scss'
        },
        options: {
          includePaths: [
            'node_modules/govuk_frontend_toolkit/stylesheets'
          ],
          style: 'nested',
          sourceComments: 'map'
        }
      },
      production: {
        files: [
          { 'public/stylesheets/spotlight.css': 'styles/index.scss' },
          {
            expand: true,
            cwd: 'node_modules/govuk_template_mustache/assets/stylesheets',
            src: ['*.css'],
            dest: 'public/stylesheets',
            ext: '.css'
          }
        ],
        options: {
          includePaths: [
            'node_modules/govuk_frontend_toolkit/stylesheets'
          ],
          outputStyle: 'compressed'
        }
      }
    },
    // Sets up Jasmine tests
    jasmine: {
      spotlight: {
        src: ['app/**/*.js'],
        options: {
          helpers: ['spec/helpers/*.js'],
          specs: [
            'spec/shared/**/spec.*.js',
            'spec/client/**/spec.*.js'
          ],
          template: 'spec/index.html',
          keepRunner: true
        }
      }
    },
    // Sets up server-side Jasmine node tests
    jasmine_node: {
      legacy: {
        verbose: false,
        src: './spec/helpers',
        options: {
          specFolders: [
            './spec/shared',
            './spec/server'
          ],
          useHelpers: true,
          specNameMatcher: 'spec.*', // load only specs containing specNameMatcher
          match: '.*',
          useRequireJs: 'spec/requirejs-setup.js',
          verbose: false,
          jUnit: {
            report: false,
            savePath : './build/reports/jasmine/',
            useDotNotation: true,
            consolidate: true
          }
        }
      },
      server: {
        verbose: false,
        src: './spec/server-pure',
        options: {
          specFolders: [
            './spec/server-pure'
          ],
          useHelpers: true,
          specNameMatcher: 'spec.*', // load only specs containing specNameMatcher
          match: '.*',
          verbose: false,
          jUnit: {
            report: false,
            savePath : './build/reports/jasmine/',
            useDotNotation: true,
            consolidate: true
          }
        }
      }
    },
    // Sets up server-side Jasmine node tests
    // Lints our JavaScript
    jshint: {
      browser: {
        src: ['app/client/**/*.js', 'spec/client/**/*.js'],
        options: {
          reporter: require('jshint-stylish'),
          reporterOutput: "",
          jshintrc: true,
          config: './node_modules/performanceplatform-js-style-configs/.jshintrc-browser.json'
        }
      },
      node: {
        src: ['app/**/*.js', 'app/**/*.json', 'spec/**/*.js',
          '!app/client/**/*.js', '!spec/client/**/*.js'],
        options: {
          reporter: require('jshint-stylish'),
          reporterOutput: "",
          jshintrc: true,
          config: './node_modules/performanceplatform-js-style-configs/.jshintrc-node.json'
        }
      }
    },
    // Creates a single big JS file
    requirejs: {
      production: {
        options: _.extend({}, requirejsConfig, {
          out: 'public/javascripts/spotlight.js',
          d3: true
        })
      },
      'production-no-d3': {
        options: _.extend({}, requirejsConfig, {
          out: 'public/javascripts/spotlight-no-d3.js',
          d3: false
        })
      }
    },
    concat: {
      options: {
        separator: ';'
      },
      dist: {
        src: [
          'node_modules/govuk_frontend_toolkit/javascripts/govuk/analytics/google-analytics-universal-tracker.js',
          'node_modules/govuk_frontend_toolkit/javascripts/govuk/analytics/analytics.js',
          'node_modules/govuk_frontend_toolkit/javascripts/govuk/analytics/download-link-tracker.js',
          'app/client/analytics.js'
        ],
        dest: 'public/javascripts/analytics.js'
      }
    },
    // Copies templates and assets from external modules and dirs
    copy: {
      govuk_template: {
        src: 'node_modules/govuk_template_mustache/views/layouts/govuk_template.html',
        dest: 'app/server/templates/page-components/',
        expand: true,
        flatten: true,
        filter: 'isFile'
      },
      govuk_assets: {
        files: [
          {
            expand: true,
            src: '**',
            cwd: 'node_modules/govuk_template_mustache/assets',
            dest: 'public/'
          }
        ]
      },
      spotlight_assets: {
        files: [
          {
            expand: true,
            src: '**',
            cwd: 'assets',
            dest: 'public/'
          }
        ]
      },
      vendor: {
        files: [
          {
            src: 'node_modules/backbone/backbone.js',
            dest: 'app/vendor/',
            flatten: true,
            expand: true
          },
          {
            src: 'node_modules/d3/d3.js',
            dest: 'app/vendor/',
            flatten: true,
            expand: true
          },
          {
            src: 'node_modules/moment-timezone/moment-timezone.js',
            dest: 'app/vendor/',
            flatten: true,
            expand: true
          },
          {
            src: 'node_modules/lodash/dist/lodash.js',
            dest: 'app/vendor/',
            flatten: true,
            expand: true
          }
        ]
      }
    },
    // Watches styles and specs for changes
    watch: {
      css: {
        files: ['styles/**/*.scss'],
        tasks: ['sass:development'],
        options: { nospawn: true }
      },
      spec: {
        files: ['spec/**/spec.*.js'],
        tasks: ['jasmine:spotlight:build']
      }
    },
    shell: {
      // Runs subset of cheapseats tests
      cheapseats: {
        options: {
          failOnError: true,
          stderr: true,
          stdout: true
        },
        command: addArgs('node ./node_modules/cheapseats/index.js --reporter spec-retry --standalone --path --quickrun ./')
      },
      // Runs all cheapseats tests
      cheapseats_full_run: {
        options: {
          failOnError: true,
          stderr: true,
          stdout: true
        },
        command: addArgs('node ./node_modules/cheapseats/index.js --reporter spec-retry --standalone --path ./')
      },
      nightwatch: {
        command: addArgs('./node_modules/nightwatch/bin/nightwatch')
      },
      // Supervises the node process in development
      supervisor: {
        options: {
          stdout: true,
          stderr: true,
          execOptions: {
            maxBuffer: Infinity
          }
        },
        command: './node_modules/supervisor/lib/cli-wrapper.js -w app -i app/vendor -e "js|html" -n error app/server'
      },
      functional_spotlight: {
        command: 'node ./tests/tools/server_and_test.js'
      }
    },
    // Runs development tasks concurrently
    concurrent: {
      dev: {
        tasks: ['shell:supervisor', 'watch'],
        options: {
          logConcurrentOutput: true
        }
      }
    },
    // Creates an asset digest for cachebusting URLs
    digest: {
      options: {
        out: 'public/asset-digest.json',
        separator: '-',
        algorithm: 'md5'
      },
      files: {
        src: ['public/**/*.*']
      }
    }
  });

  // Load external module tasks
  [
    'grunt-contrib-jasmine',
    'grunt-jasmine-node-new',
    'grunt-contrib-jshint',
    'grunt-contrib-clean',
    'grunt-contrib-requirejs',
    'grunt-contrib-concat',
    'grunt-digest',
    'grunt-sass',
    'grunt-contrib-copy',
    'grunt-contrib-watch',
    'grunt-shell',
    'grunt-concurrent'
  ].forEach(function (task) {
    grunt.loadNpmTasks(task);
  });

  grunt.registerTask('copy:assets', [
    'copy:govuk_assets',
    'copy:spotlight_assets'
  ]);

  grunt.registerTask('build:common', [
    'copy:vendor',
    'copy:govuk_template',
    'clean',
    'copy:assets'
  ]);

  grunt.registerTask('build:development', [
    'build:common',
    'concat',
    'sass:development',
    'digest'
  ]);

  grunt.registerTask('build:production', [
    'build:common',
    'sass:production',
    'requirejs:production',
    'requirejs:production-no-d3',
    'concat',
    'digest'
  ]);

  grunt.registerTask('test:unit', [
    'copy:vendor',
    'copy:govuk_template',
    'clean',
    'copy:assets',
    'sass:development',
    'digest',
    'jasmine_node',
    'jshint'
  ]);

  grunt.registerTask('test:all', [
    'test:unit',
    'shell:cheapseats',
    'test:functional'
  ]);

  grunt.registerTask('cheapseats', [
    'shell:cheapseats'
  ]);

  grunt.registerTask('nightwatch', [
    'shell:nightwatch'
  ]);

  grunt.registerTask('test:functional:ci', [
    'shell:functional_spotlight'
  ]);

  grunt.registerTask('test:functional', [
    'shell:nightwatch:-e phantomjs'
  ]);

  grunt.registerTask('test:functional:ff', [
    'shell:nightwatch'
  ]);

  grunt.registerTask('test:functional:chrome', [
    'shell:nightwatch:-e chrome'
  ]);

  grunt.registerTask('test:functional:all', [
    'shell:nightwatch:-e default,chrome,phantomjs'
  ]);

  grunt.registerTask('cheapseats:unpublished', [
    'shell:cheapseats:--unpublished'
  ]);

  // Default task
  grunt.registerTask('default', [
    'build:development',
    'jasmine:spotlight:build',
    'concurrent'
  ]);

  grunt.registerTask('heroku:development', [
    'build:development'
  ]);

};
<commit_msg>Remove all but one 'spec.*' file<commit_after>var _ = require('lodash');

var getRequirejsConfig = function () {
  var requirejsConfig;
  // Define a temporary function so that we can 'read' in the application settings.
  // The settings file assumes the existence of a function called 'define'.
  global.define = function (config) {
    requirejsConfig = config({ isBuild: true });
  };
  // Read the settings
  require('./app/config');
  // Remove the function
  delete global.define;

  return _.extend(requirejsConfig, {
    baseUrl: 'app',
    name: 'client',
    waitSeconds: 60,
    include: ['vendor/almond'],
    deps: [
      'client',
      'client/client_bootstrap',
      'client/logger'
    ],
    wrap: true,
    optimize: 'uglify'
  });
};

var addArgs = function (cmd) {
  return function () {
    return [cmd].concat([].slice.apply(arguments)).join(' ');
  };
};

var requirejsConfig = getRequirejsConfig();

module.exports = function (grunt) {
  'use strict';

  grunt.initConfig({
    // Removes the contents of the public directory
    clean: ['public/'],
    // Builds Sass in development and production
    sass: {
      development: {
        files: {
          'public/stylesheets/spotlight.css': 'styles/index.scss'
        },
        options: {
          includePaths: [
            'node_modules/govuk_frontend_toolkit/stylesheets'
          ],
          style: 'nested',
          sourceComments: 'map'
        }
      },
      production: {
        files: [
          { 'public/stylesheets/spotlight.css': 'styles/index.scss' },
          {
            expand: true,
            cwd: 'node_modules/govuk_template_mustache/assets/stylesheets',
            src: ['*.css'],
            dest: 'public/stylesheets',
            ext: '.css'
          }
        ],
        options: {
          includePaths: [
            'node_modules/govuk_frontend_toolkit/stylesheets'
          ],
          outputStyle: 'compressed'
        }
      }
    },
    // Sets up Jasmine tests
    jasmine: {
      spotlight: {
        src: ['app/**/*.js'],
        options: {
          helpers: ['spec/helpers/*.js'],
          specs: [
            'spec/client/spec.accessibility.js'
          ],
          template: 'spec/index.html',
          keepRunner: true
        }
      }
    },
    // Sets up server-side Jasmine node tests
    jasmine_node: {
      legacy: {
        verbose: false,
        src: './spec/helpers',
        options: {
          specFolders: [
            './spec/shared',
            './spec/server'
          ],
          useHelpers: true,
          specNameMatcher: 'spec.*', // load only specs containing specNameMatcher
          match: '.*',
          useRequireJs: 'spec/requirejs-setup.js',
          verbose: false,
          jUnit: {
            report: false,
            savePath : './build/reports/jasmine/',
            useDotNotation: true,
            consolidate: true
          }
        }
      },
      server: {
        verbose: false,
        src: './spec/server-pure',
        options: {
          specFolders: [
            './spec/server-pure'
          ],
          useHelpers: true,
          specNameMatcher: 'spec.*', // load only specs containing specNameMatcher
          match: '.*',
          verbose: false,
          jUnit: {
            report: false,
            savePath : './build/reports/jasmine/',
            useDotNotation: true,
            consolidate: true
          }
        }
      }
    },
    // Sets up server-side Jasmine node tests
    // Lints our JavaScript
    jshint: {
      browser: {
        src: ['app/client/**/*.js', 'spec/client/**/*.js'],
        options: {
          reporter: require('jshint-stylish'),
          reporterOutput: "",
          jshintrc: true,
          config: './node_modules/performanceplatform-js-style-configs/.jshintrc-browser.json'
        }
      },
      node: {
        src: ['app/**/*.js', 'app/**/*.json', 'spec/**/*.js',
          '!app/client/**/*.js', '!spec/client/**/*.js'],
        options: {
          reporter: require('jshint-stylish'),
          reporterOutput: "",
          jshintrc: true,
          config: './node_modules/performanceplatform-js-style-configs/.jshintrc-node.json'
        }
      }
    },
    // Creates a single big JS file
    requirejs: {
      production: {
        options: _.extend({}, requirejsConfig, {
          out: 'public/javascripts/spotlight.js',
          d3: true
        })
      },
      'production-no-d3': {
        options: _.extend({}, requirejsConfig, {
          out: 'public/javascripts/spotlight-no-d3.js',
          d3: false
        })
      }
    },
    concat: {
      options: {
        separator: ';'
      },
      dist: {
        src: [
          'node_modules/govuk_frontend_toolkit/javascripts/govuk/analytics/google-analytics-universal-tracker.js',
          'node_modules/govuk_frontend_toolkit/javascripts/govuk/analytics/analytics.js',
          'node_modules/govuk_frontend_toolkit/javascripts/govuk/analytics/download-link-tracker.js',
          'app/client/analytics.js'
        ],
        dest: 'public/javascripts/analytics.js'
      }
    },
    // Copies templates and assets from external modules and dirs
    copy: {
      govuk_template: {
        src: 'node_modules/govuk_template_mustache/views/layouts/govuk_template.html',
        dest: 'app/server/templates/page-components/',
        expand: true,
        flatten: true,
        filter: 'isFile'
      },
      govuk_assets: {
        files: [
          {
            expand: true,
            src: '**',
            cwd: 'node_modules/govuk_template_mustache/assets',
            dest: 'public/'
          }
        ]
      },
      spotlight_assets: {
        files: [
          {
            expand: true,
            src: '**',
            cwd: 'assets',
            dest: 'public/'
          }
        ]
      },
      vendor: {
        files: [
          {
            src: 'node_modules/backbone/backbone.js',
            dest: 'app/vendor/',
            flatten: true,
            expand: true
          },
          {
            src: 'node_modules/d3/d3.js',
            dest: 'app/vendor/',
            flatten: true,
            expand: true
          },
          {
            src: 'node_modules/moment-timezone/moment-timezone.js',
            dest: 'app/vendor/',
            flatten: true,
            expand: true
          },
          {
            src: 'node_modules/lodash/dist/lodash.js',
            dest: 'app/vendor/',
            flatten: true,
            expand: true
          }
        ]
      }
    },
    // Watches styles and specs for changes
    watch: {
      css: {
        files: ['styles/**/*.scss'],
        tasks: ['sass:development'],
        options: { nospawn: true }
      },
      spec: {
        files: ['spec/**/spec.*.js'],
        tasks: ['jasmine:spotlight:build']
      }
    },
    shell: {
      // Runs subset of cheapseats tests
      cheapseats: {
        options: {
          failOnError: true,
          stderr: true,
          stdout: true
        },
        command: addArgs('node ./node_modules/cheapseats/index.js --reporter spec-retry --standalone --path --quickrun ./')
      },
      // Runs all cheapseats tests
      cheapseats_full_run: {
        options: {
          failOnError: true,
          stderr: true,
          stdout: true
        },
        command: addArgs('node ./node_modules/cheapseats/index.js --reporter spec-retry --standalone --path ./')
      },
      nightwatch: {
        command: addArgs('./node_modules/nightwatch/bin/nightwatch')
      },
      // Supervises the node process in development
      supervisor: {
        options: {
          stdout: true,
          stderr: true,
          execOptions: {
            maxBuffer: Infinity
          }
        },
        command: './node_modules/supervisor/lib/cli-wrapper.js -w app -i app/vendor -e "js|html" -n error app/server'
      },
      functional_spotlight: {
        command: 'node ./tests/tools/server_and_test.js'
      }
    },
    // Runs development tasks concurrently
    concurrent: {
      dev: {
        tasks: ['shell:supervisor', 'watch'],
        options: {
          logConcurrentOutput: true
        }
      }
    },
    // Creates an asset digest for cachebusting URLs
    digest: {
      options: {
        out: 'public/asset-digest.json',
        separator: '-',
        algorithm: 'md5'
      },
      files: {
        src: ['public/**/*.*']
      }
    }
  });

  // Load external module tasks
  [
    'grunt-contrib-jasmine',
    'grunt-jasmine-node-new',
    'grunt-contrib-jshint',
    'grunt-contrib-clean',
    'grunt-contrib-requirejs',
    'grunt-contrib-concat',
    'grunt-digest',
    'grunt-sass',
    'grunt-contrib-copy',
    'grunt-contrib-watch',
    'grunt-shell',
    'grunt-concurrent'
  ].forEach(function (task) {
    grunt.loadNpmTasks(task);
  });

  grunt.registerTask('copy:assets', [
    'copy:govuk_assets',
    'copy:spotlight_assets'
  ]);

  grunt.registerTask('build:common', [
    'copy:vendor',
    'copy:govuk_template',
    'clean',
    'copy:assets'
  ]);

  grunt.registerTask('build:development', [
    'build:common',
    'concat',
    'sass:development',
    'digest'
  ]);

  grunt.registerTask('build:production', [
    'build:common',
    'sass:production',
    'requirejs:production',
    'requirejs:production-no-d3',
    'concat',
    'digest'
  ]);

  grunt.registerTask('test:unit', [
    'copy:vendor',
    'copy:govuk_template',
    'clean',
    'copy:assets',
    'sass:development',
    'digest',
    'jasmine_node',
    'jshint'
  ]);

  grunt.registerTask('test:all', [
    'test:unit',
    'shell:cheapseats',
    'test:functional'
  ]);

  grunt.registerTask('cheapseats', [
    'shell:cheapseats'
  ]);

  grunt.registerTask('nightwatch', [
    'shell:nightwatch'
  ]);

  grunt.registerTask('test:functional:ci', [
    'shell:functional_spotlight'
  ]);

  grunt.registerTask('test:functional', [
    'shell:nightwatch:-e phantomjs'
  ]);

  grunt.registerTask('test:functional:ff', [
    'shell:nightwatch'
  ]);

  grunt.registerTask('test:functional:chrome', [
    'shell:nightwatch:-e chrome'
  ]);

  grunt.registerTask('test:functional:all', [
    'shell:nightwatch:-e default,chrome,phantomjs'
  ]);

  grunt.registerTask('cheapseats:unpublished', [
    'shell:cheapseats:--unpublished'
  ]);

  // Default task
  grunt.registerTask('default', [
    'build:development',
    'jasmine:spotlight:build',
    'concurrent'
  ]);

  grunt.registerTask('heroku:development', [
    'build:development'
  ]);

};
<|endoftext|>


<commit_before>"use strict";

import React from "react";

import Icon from "./Icon.js";

import NowPlayingActions from "../actions/NowPlayingActions.js";
import NowPlayingStore from "../stores/NowPlayingStore.js";
import NowPlaying from "./NowPlaying.js";

import PlayProgress from "./PlayProgress.js";
import Volume from "./Volume.js";

import PlaylistStore from "../stores/PlaylistStore.js";
import PlaylistActions from "../actions/PlaylistActions.js";

import PlayingStatusStore from "../stores/PlayingStatusStore.js";

import RightColumnStore from "../stores/RightColumnStore.js";
import RightColumnActions from "../actions/RightColumnActions.js";

var BACKWARD_TIMEOUT = 2000;

export default class Bottom extends React.Component {
  render() {
    return (

        <PlayProgress/>

          <NowPlaying />
          <Controls />

            <Volume />
            <RightColumnToggle />

    );
  }
}

class RightColumnToggle extends React.Component {
  constructor(props) {
    super(props);

    this._onClick = this._onClick.bind(this);
  }

  componentDidMount() {
    RightColumnStore.addChangeListener(this._onChange);
  }

  componentWillUnmount() {
    RightColumnStore.removeChangeListener(this._onChange);
  }

  render() {
    return (

        <Icon icon="queue_music"onClick={this._onClick} />

    );
  }

  _onChange() {
  }

  _onClick() {
    RightColumnActions.toggle();
  }
}

class Controls extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      playing: NowPlayingStore.getPlaying(),
      repeat: NowPlayingStore.getRepeat(),
      canNext: PlaylistStore.canNext(),
      canPrev: PlaylistStore.canPrev(),
    };

    this._onChangePlaylist = this._onChangePlaylist.bind(this);
    this._onChange = this._onChange.bind(this);
    this._togglePlayPause = this._togglePlayPause.bind(this);
    this._onBackward = this._onBackward.bind(this);
    this._onForward = this._onForward.bind(this);
    this._toggleRepeat = this._toggleRepeat.bind(this);
  }

  componentDidMount() {
    NowPlayingStore.addChangeListener(this._onChange);
    PlaylistStore.addChangeListener(this._onChangePlaylist);
  }

  componentWillUnmount() {
    NowPlayingStore.removeChangeListener(this._onChange);
    PlaylistStore.removeChangeListener(this._onChangePlaylist);
  }

  render() {
    var prevClasses = {"skip": true, "enabled": this.state.canPrev};
    var nextClasses = {"skip": true, "enabled": this.state.canNext};
    var repeatClasses = {"skip": true, "enabled": this.state.playing, "active": this.state.repeat};
    var repeatName = (this.state.repeat) ? "repeat_one" : "repeat";
    return (

        <Icon icon="skip_previous" extraClasses={prevClasses} onClick={this._onBackward} />
        <Icon icon={this.state.playing ? "pause_circle_filled" : "play_circle_filled"}extraClasses={{"play-pause": true}} onClick={this._togglePlayPause} />
        <Icon icon="skip_next" extraClasses={nextClasses} onClick={this._onForward} />
        <Icon icon={repeatName} extraClasses={repeatClasses} onClick={this._toggleRepeat} />

    );
  }

  _onChangePlaylist() {
    this.setState({
      canNext: PlaylistStore.canNext(),
      canPrev: PlaylistStore.canPrev(),
    });
  }

  _onChange() {
    this.setState({
      playing: NowPlayingStore.getPlaying(),
      repeat: NowPlayingStore.getRepeat(),
    });

    var favicon = document.querySelector("head link[rel=\"shortcut icon\"]");
    var currentTrack = NowPlayingStore.getTrack();
    if (currentTrack === null) {
      document.title = "tchaik";
      return;
    }
    document.title = currentTrack.Name;
    favicon.href = `/icon/${currentTrack.ID}`;
  }

  _togglePlayPause() {
    NowPlayingActions.playing(!this.state.playing);
    this.setState({
      playing: !this.state.playing,
    });
  }

  _backButtonTimerRunning() {
    if (this._backButtonTimer) {
      return true;
    }
    return false;
  }

  _backButtonTimerStart() {
    if (this._backButtonTimer) {
      clearTimeout(this._backButtonTimer);
    }
    this._backButtonTimer = setTimeout(this._backButtonTimerTimeout, BACKWARD_TIMEOUT);
  }

  _backButtonTimerTimeout() {
    this._backButtonTimer = null;
  }

  _prev() {
    PlaylistActions.prev();
  }

  _onBackward() {
    if (this._backButtonTimerRunning()) {
      PlaylistActions.prev();
    } else if (this.state.playing || PlayingStatusStore.getTime() > 0) {
      NowPlayingActions.setCurrentTime(0);
    } else {
      PlaylistActions.prev();
    }
    this._backButtonTimerStart();
    return;
  }

  _onForward() {
    PlaylistActions.next();
  }

  _toggleRepeat() {
    NowPlayingActions.repeat(!this.state.repeat);
    this.setState({
      repeat: !this.state.repeat,
    });
  }

}
<commit_msg>Enable repeat icon if there is a set.<commit_after>"use strict";

import React from "react";

import Icon from "./Icon.js";

import NowPlayingActions from "../actions/NowPlayingActions.js";
import NowPlayingStore from "../stores/NowPlayingStore.js";
import NowPlaying from "./NowPlaying.js";

import PlayProgress from "./PlayProgress.js";
import Volume from "./Volume.js";

import PlaylistStore from "../stores/PlaylistStore.js";
import PlaylistActions from "../actions/PlaylistActions.js";

import PlayingStatusStore from "../stores/PlayingStatusStore.js";

import RightColumnStore from "../stores/RightColumnStore.js";
import RightColumnActions from "../actions/RightColumnActions.js";

var BACKWARD_TIMEOUT = 2000;

export default class Bottom extends React.Component {
  render() {
    return (

        <PlayProgress/>

          <NowPlaying />
          <Controls />

            <Volume />
            <RightColumnToggle />

    );
  }
}

class RightColumnToggle extends React.Component {
  constructor(props) {
    super(props);

    this._onClick = this._onClick.bind(this);
  }

  componentDidMount() {
    RightColumnStore.addChangeListener(this._onChange);
  }

  componentWillUnmount() {
    RightColumnStore.removeChangeListener(this._onChange);
  }

  render() {
    return (

        <Icon icon="queue_music"onClick={this._onClick} />

    );
  }

  _onChange() {
  }

  _onClick() {
    RightColumnActions.toggle();
  }
}

class Controls extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      playing: NowPlayingStore.getPlaying(),
      repeat: NowPlayingStore.getRepeat(),
      track: NowPlayingStore.getTrack(),
      canNext: PlaylistStore.canNext(),
      canPrev: PlaylistStore.canPrev(),
    };

    this._onChangePlaylist = this._onChangePlaylist.bind(this);
    this._onChange = this._onChange.bind(this);
    this._togglePlayPause = this._togglePlayPause.bind(this);
    this._onBackward = this._onBackward.bind(this);
    this._onForward = this._onForward.bind(this);
    this._toggleRepeat = this._toggleRepeat.bind(this);
  }

  componentDidMount() {
    NowPlayingStore.addChangeListener(this._onChange);
    PlaylistStore.addChangeListener(this._onChangePlaylist);
  }

  componentWillUnmount() {
    NowPlayingStore.removeChangeListener(this._onChange);
    PlaylistStore.removeChangeListener(this._onChangePlaylist);
  }

  render() {
    var prevClasses = {"skip": true, "enabled": this.state.canPrev};
    var nextClasses = {"skip": true, "enabled": this.state.canNext};
    var repeatClasses = {"skip": true, "enabled": (this.state.track !== null), "active": this.state.repeat};
    var repeatName = (this.state.repeat) ? "repeat_one" : "repeat";
    return (

        <Icon icon="skip_previous" extraClasses={prevClasses} onClick={this._onBackward} />
        <Icon icon={this.state.playing ? "pause_circle_filled" : "play_circle_filled"}extraClasses={{"play-pause": true}} onClick={this._togglePlayPause} />
        <Icon icon="skip_next" extraClasses={nextClasses} onClick={this._onForward} />
        <Icon icon={repeatName} extraClasses={repeatClasses} onClick={this._toggleRepeat} />

    );
  }

  _onChangePlaylist() {
    this.setState({
      canNext: PlaylistStore.canNext(),
      canPrev: PlaylistStore.canPrev(),
    });
  }

  _onChange() {
    this.setState({
      playing: NowPlayingStore.getPlaying(),
      repeat: NowPlayingStore.getRepeat(),
      track: NowPlayingStore.getTrack(),
    });

    var favicon = document.querySelector("head link[rel=\"shortcut icon\"]");
    var currentTrack = NowPlayingStore.getTrack();
    if (currentTrack === null) {
      document.title = "tchaik";
      return;
    }
    document.title = currentTrack.Name;
    favicon.href = `/icon/${currentTrack.ID}`;
  }

  _togglePlayPause() {
    NowPlayingActions.playing(!this.state.playing);
    this.setState({
      playing: !this.state.playing,
    });
  }

  _backButtonTimerRunning() {
    if (this._backButtonTimer) {
      return true;
    }
    return false;
  }

  _backButtonTimerStart() {
    if (this._backButtonTimer) {
      clearTimeout(this._backButtonTimer);
    }
    this._backButtonTimer = setTimeout(this._backButtonTimerTimeout, BACKWARD_TIMEOUT);
  }

  _backButtonTimerTimeout() {
    this._backButtonTimer = null;
  }

  _prev() {
    PlaylistActions.prev();
  }

  _onBackward() {
    if (this._backButtonTimerRunning()) {
      PlaylistActions.prev();
    } else if (this.state.playing || PlayingStatusStore.getTime() > 0) {
      NowPlayingActions.setCurrentTime(0);
    } else {
      PlaylistActions.prev();
    }
    this._backButtonTimerStart();
    return;
  }

  _onForward() {
    PlaylistActions.next();
  }

  _toggleRepeat() {
    NowPlayingActions.repeat(!this.state.repeat);
    this.setState({
      repeat: !this.state.repeat,
    });
  }

}
<|endoftext|>