<commit_before>System.register('flarum/likes/addLikeAction', ['flarum/extend', 'flarum/app', 'flarum/components/Button', 'flarum/components/CommentPost'], function (_export) {
  'use strict';

  var extend, app, Button, CommentPost;
  return {
    setters: [function (_flarumExtend) {
      extend = _flarumExtend.extend;
    }, function (_flarumApp) {
      app = _flarumApp['default'];
    }, function (_flarumComponentsButton) {
      Button = _flarumComponentsButton['default'];
    }, function (_flarumComponentsCommentPost) {
      CommentPost = _flarumComponentsCommentPost['default'];
    }],
    execute: function () {
      _export('default', function () {
        extend(CommentPost.prototype, 'actionItems', function (items) {
          var post = this.props.post;

          if (post.isHidden() || !post.canLike()) return;

          var isLiked = app.session.user && post.likes().some(function (user) {
            return user === app.session.user;
          });

          items.add('like', Button.component({
            children: app.translator.trans(isLiked ? 'flarum-likes.forum.unlike_action' : 'flarum-likes.forum.like_action'),
            className: 'Button Button--link',
            onclick: function onclick() {
              isLiked = !isLiked;

              post.save({ isLiked: isLiked });

              // We've saved the fact that we do or don't like the post, but in order
              // to provide instantaneous feedback to the user, we'll need to add or
              // remove the like from the relationship data manually.
              var data = post.data.relationships.likes.data;
              data.some(function (like, i) {
                if (like.id === app.session.user.id()) {
                  data.splice(i, 1);
                  return true;
                }
              });

              if (isLiked) {
                data.unshift({ type: 'users', id: app.session.user.id() });
              }
            }
          }));
        });
      });
    }
  };
});;
System.register('flarum/likes/addLikesList', ['flarum/extend', 'flarum/app', 'flarum/components/CommentPost', 'flarum/helpers/punctuateSeries', 'flarum/helpers/username', 'flarum/helpers/icon', 'flarum/likes/components/PostLikesModal'], function (_export) {
  'use strict';

  var extend, app, CommentPost, punctuateSeries, username, icon, PostLikesModal;
  return {
    setters: [function (_flarumExtend) {
      extend = _flarumExtend.extend;
    }, function (_flarumApp) {
      app = _flarumApp['default'];
    }, function (_flarumComponentsCommentPost) {
      CommentPost = _flarumComponentsCommentPost['default'];
    }, function (_flarumHelpersPunctuateSeries) {
      punctuateSeries = _flarumHelpersPunctuateSeries['default'];
    }, function (_flarumHelpersUsername) {
      username = _flarumHelpersUsername['default'];
    }, function (_flarumHelpersIcon) {
      icon = _flarumHelpersIcon['default'];
    }, function (_flarumLikesComponentsPostLikesModal) {
      PostLikesModal = _flarumLikesComponentsPostLikesModal['default'];
    }],
    execute: function () {
      _export('default', function () {
        extend(CommentPost.prototype, 'footerItems', function (items) {
          var post = this.props.post;
          var likes = post.likes();

          if (likes && likes.length) {
            var limit = 4;
            var overLimit = likes.length > limit;

            // Construct a list of names of users who have liked this post. Make sure the
            // current user is first in the list, and cap a maximum of 4 items.
            var names = likes.sort(function (a) {
              return a === app.session.user ? -1 : 1;
            }).slice(0, overLimit ? limit - 1 : limit).map(function (user) {
              return m(
                'a',
                { href: app.route.user(user), config: m.route },
                user === app.session.user ? app.translator.trans('flarum-likes.forum.you') : username(user)
              );
            });

            // If there are more users that we've run out of room to display, add a "x
            // others" name to the end of the list. Clicking on it will display a modal
            // with a full list of names.
            if (overLimit) {
              var count = likes.length - names.length;

              names.push(m(
                'a',
                { href: '#', onclick: function (e) {
                    e.preventDefault();
                    app.modal.show(new PostLikesModal({ post: post }));
                  } },
                app.translator.transChoice('flarum-likes.forum.others', count, { count: count })
              ));
            }

            items.add('liked', m(
              'div',
              { className: 'Post-likedBy' },
              icon('thumbs-o-up'),
              app.translator.transChoice('flarum-likes.forum.post_liked_by' + (likes[0] === app.session.user ? '_self' : ''), names.length, {
                count: names.length,
                users: punctuateSeries(names)
              })
            ));
          }
        });
      });
    }
  };
});;
System.register('flarum/likes/main', ['flarum/extend', 'flarum/app', 'flarum/models/Post', 'flarum/Model', 'flarum/components/NotificationGrid', 'flarum/likes/addLikeAction', 'flarum/likes/addLikesList', 'flarum/likes/components/PostLikedNotification'], function (_export) {
  'use strict';

  var extend, app, Post, Model, NotificationGrid, addLikeAction, addLikesList, PostLikedNotification;
  return {
    setters: [function (_flarumExtend) {
      extend = _flarumExtend.extend;
    }, function (_flarumApp) {
      app = _flarumApp['default'];
    }, function (_flarumModelsPost) {
      Post = _flarumModelsPost['default'];
    }, function (_flarumModel) {
      Model = _flarumModel['default'];
    }, function (_flarumComponentsNotificationGrid) {
      NotificationGrid = _flarumComponentsNotificationGrid['default'];
    }, function (_flarumLikesAddLikeAction) {
      addLikeAction = _flarumLikesAddLikeAction['default'];
    }, function (_flarumLikesAddLikesList) {
      addLikesList = _flarumLikesAddLikesList['default'];
    }, function (_flarumLikesComponentsPostLikedNotification) {
      PostLikedNotification = _flarumLikesComponentsPostLikedNotification['default'];
    }],
    execute: function () {

      app.initializers.add('flarum-likes', function () {
        app.notificationComponents.postLiked = PostLikedNotification;

        Post.prototype.canLike = Model.attribute('canLike');
        Post.prototype.likes = Model.hasMany('likes');

        addLikeAction();
        addLikesList();

        extend(NotificationGrid.prototype, 'notificationTypes', function (items) {
          items.add('postLiked', {
            name: 'postLiked',
            icon: 'thumbs-o-up',
            label: app.translator.trans('flarum-likes.forum.notify_post_liked')
          });
        });
      });
    }
  };
});;
System.register('flarum/likes/components/PostLikedNotification', ['flarum/components/Notification', 'flarum/helpers/username', 'flarum/helpers/punctuateSeries'], function (_export) {
  'use strict';

  var Notification, username, punctuateSeries, PostLikedNotification;
  return {
    setters: [function (_flarumComponentsNotification) {
      Notification = _flarumComponentsNotification['default'];
    }, function (_flarumHelpersUsername) {
      username = _flarumHelpersUsername['default'];
    }, function (_flarumHelpersPunctuateSeries) {
      punctuateSeries = _flarumHelpersPunctuateSeries['default'];
    }],
    execute: function () {
      PostLikedNotification = (function (_Notification) {
        babelHelpers.inherits(PostLikedNotification, _Notification);

        function PostLikedNotification() {
          babelHelpers.classCallCheck(this, PostLikedNotification);
          babelHelpers.get(Object.getPrototypeOf(PostLikedNotification.prototype), 'constructor', this).apply(this, arguments);
        }

        babelHelpers.createClass(PostLikedNotification, [{
          key: 'icon',
          value: function icon() {
            return 'thumbs-o-up';
          }
        }, {
          key: 'href',
          value: function href() {
            return app.route.post(this.props.notification.subject());
          }
        }, {
          key: 'content',
          value: function content() {
            var notification = this.props.notification;
            var user = notification.sender();
            var auc = notification.additionalUnreadCount();

            return app.translator.trans('flarum-likes.forum.post_liked_notification', {
              user: user,
              username: auc ? punctuateSeries([username(user), app.translator.trans('flarum-likes.forum.others', { count: auc })]) : undefined
            });
          }
        }, {
          key: 'excerpt',
          value: function excerpt() {
            return this.props.notification.subject().contentPlain();
          }
        }]);
        return PostLikedNotification;
      })(Notification);

      _export('default', PostLikedNotification);
    }
  };
});;
System.register('flarum/likes/components/PostLikesModal', ['flarum/components/Modal', 'flarum/helpers/avatar', 'flarum/helpers/username'], function (_export) {
  'use strict';

  var Modal, avatar, username, PostLikesModal;
  return {
    setters: [function (_flarumComponentsModal) {
      Modal = _flarumComponentsModal['default'];
    }, function (_flarumHelpersAvatar) {
      avatar = _flarumHelpersAvatar['default'];
    }, function (_flarumHelpersUsername) {
      username = _flarumHelpersUsername['default'];
    }],
    execute: function () {
      PostLikesModal = (function (_Modal) {
        babelHelpers.inherits(PostLikesModal, _Modal);

        function PostLikesModal() {
          babelHelpers.classCallCheck(this, PostLikesModal);
          babelHelpers.get(Object.getPrototypeOf(PostLikesModal.prototype), 'constructor', this).apply(this, arguments);
        }

        babelHelpers.createClass(PostLikesModal, [{
          key: 'className',
          value: function className() {
            return 'PostLikesModal Modal--small';
          }
        }, {
          key: 'title',
          value: function title() {
            return app.translator.trans('flarum-likes.forum.post_likes_modal_title');
          }
        }, {
          key: 'content',
          value: function content() {
            return m(
              'div',
              { className: 'Modal-body' },
              m(
                'ul',
                { className: 'PostLikesModal-list' },
                this.props.post.likes().map(function (user) {
                  return m(
                    'li',
                    null,
                    m(
                      'a',
                      { href: app.route.user(user), config: m.route },
                      avatar(user),
                      ' ',
                      ' ',
                      username(user)
                    )
                  );
                })
              )
            );
          }
        }]);
        return PostLikesModal;
      })(Modal);

      _export('default', PostLikesModal);
    }
  };
});<commit_msg>Recompile JS<commit_after>System.register('flarum/likes/addLikeAction', ['flarum/extend', 'flarum/app', 'flarum/components/Button', 'flarum/components/CommentPost'], function (_export) {
  'use strict';

  var extend, app, Button, CommentPost;
  return {
    setters: [function (_flarumExtend) {
      extend = _flarumExtend.extend;
    }, function (_flarumApp) {
      app = _flarumApp['default'];
    }, function (_flarumComponentsButton) {
      Button = _flarumComponentsButton['default'];
    }, function (_flarumComponentsCommentPost) {
      CommentPost = _flarumComponentsCommentPost['default'];
    }],
    execute: function () {
      _export('default', function () {
        extend(CommentPost.prototype, 'actionItems', function (items) {
          var post = this.props.post;

          if (post.isHidden() || !post.canLike()) return;

          var isLiked = app.session.user && post.likes().some(function (user) {
            return user === app.session.user;
          });

          items.add('like', Button.component({
            children: app.translator.trans(isLiked ? 'flarum-likes.forum.post.unlike_link' : 'flarum-likes.forum.post.like_link'),
            className: 'Button Button--link',
            onclick: function onclick() {
              isLiked = !isLiked;

              post.save({ isLiked: isLiked });

              // We've saved the fact that we do or don't like the post, but in order
              // to provide instantaneous feedback to the user, we'll need to add or
              // remove the like from the relationship data manually.
              var data = post.data.relationships.likes.data;
              data.some(function (like, i) {
                if (like.id === app.session.user.id()) {
                  data.splice(i, 1);
                  return true;
                }
              });

              if (isLiked) {
                data.unshift({ type: 'users', id: app.session.user.id() });
              }
            }
          }));
        });
      });
    }
  };
});;System.register('flarum/likes/addLikesList', ['flarum/extend', 'flarum/app', 'flarum/components/CommentPost', 'flarum/helpers/punctuateSeries', 'flarum/helpers/username', 'flarum/helpers/icon', 'flarum/likes/components/PostLikesModal'], function (_export) {
  'use strict';

  var extend, app, CommentPost, punctuateSeries, username, icon, PostLikesModal;
  return {
    setters: [function (_flarumExtend) {
      extend = _flarumExtend.extend;
    }, function (_flarumApp) {
      app = _flarumApp['default'];
    }, function (_flarumComponentsCommentPost) {
      CommentPost = _flarumComponentsCommentPost['default'];
    }, function (_flarumHelpersPunctuateSeries) {
      punctuateSeries = _flarumHelpersPunctuateSeries['default'];
    }, function (_flarumHelpersUsername) {
      username = _flarumHelpersUsername['default'];
    }, function (_flarumHelpersIcon) {
      icon = _flarumHelpersIcon['default'];
    }, function (_flarumLikesComponentsPostLikesModal) {
      PostLikesModal = _flarumLikesComponentsPostLikesModal['default'];
    }],
    execute: function () {
      _export('default', function () {
        extend(CommentPost.prototype, 'footerItems', function (items) {
          var post = this.props.post;
          var likes = post.likes();

          if (likes && likes.length) {
            var limit = 4;
            var overLimit = likes.length > limit;

            // Construct a list of names of users who have liked this post. Make sure the
            // current user is first in the list, and cap a maximum of 4 items.
            var names = likes.sort(function (a) {
              return a === app.session.user ? -1 : 1;
            }).slice(0, overLimit ? limit - 1 : limit).map(function (user) {
              return m(
                'a',
                { href: app.route.user(user), config: m.route },
                user === app.session.user ? app.translator.trans('flarum-likes.forum.post.you_text') : username(user)
              );
            });

            // If there are more users that we've run out of room to display, add a "x
            // others" name to the end of the list. Clicking on it will display a modal
            // with a full list of names.
            if (overLimit) {
              var count = likes.length - names.length;

              names.push(m(
                'a',
                { href: '#', onclick: function (e) {
                    e.preventDefault();
                    app.modal.show(new PostLikesModal({ post: post }));
                  } },
                app.translator.transChoice('flarum-likes.forum.post.others_link', count, { count: count })
              ));
            }

            items.add('liked', m(
              'div',
              { className: 'Post-likedBy' },
              icon('thumbs-o-up'),
              app.translator.transChoice('flarum-likes.forum.post.liked_by' + (likes[0] === app.session.user ? '_self' : '') + '_text', names.length, {
                count: names.length,
                users: punctuateSeries(names)
              })
            ));
          }
        });
      });
    }
  };
});;System.register('flarum/likes/main', ['flarum/extend', 'flarum/app', 'flarum/models/Post', 'flarum/Model', 'flarum/components/NotificationGrid', 'flarum/likes/addLikeAction', 'flarum/likes/addLikesList', 'flarum/likes/components/PostLikedNotification'], function (_export) {
  'use strict';

  var extend, app, Post, Model, NotificationGrid, addLikeAction, addLikesList, PostLikedNotification;
  return {
    setters: [function (_flarumExtend) {
      extend = _flarumExtend.extend;
    }, function (_flarumApp) {
      app = _flarumApp['default'];
    }, function (_flarumModelsPost) {
      Post = _flarumModelsPost['default'];
    }, function (_flarumModel) {
      Model = _flarumModel['default'];
    }, function (_flarumComponentsNotificationGrid) {
      NotificationGrid = _flarumComponentsNotificationGrid['default'];
    }, function (_flarumLikesAddLikeAction) {
      addLikeAction = _flarumLikesAddLikeAction['default'];
    }, function (_flarumLikesAddLikesList) {
      addLikesList = _flarumLikesAddLikesList['default'];
    }, function (_flarumLikesComponentsPostLikedNotification) {
      PostLikedNotification = _flarumLikesComponentsPostLikedNotification['default'];
    }],
    execute: function () {

      app.initializers.add('flarum-likes', function () {
        app.notificationComponents.postLiked = PostLikedNotification;

        Post.prototype.canLike = Model.attribute('canLike');
        Post.prototype.likes = Model.hasMany('likes');

        addLikeAction();
        addLikesList();

        extend(NotificationGrid.prototype, 'notificationTypes', function (items) {
          items.add('postLiked', {
            name: 'postLiked',
            icon: 'thumbs-o-up',
            label: app.translator.trans('flarum-likes.forum.settings.notify_post_liked_label')
          });
        });
      });
    }
  };
});;System.register('flarum/likes/components/PostLikedNotification', ['flarum/components/Notification', 'flarum/helpers/username', 'flarum/helpers/punctuateSeries'], function (_export) {
  'use strict';

  var Notification, username, punctuateSeries, PostLikedNotification;
  return {
    setters: [function (_flarumComponentsNotification) {
      Notification = _flarumComponentsNotification['default'];
    }, function (_flarumHelpersUsername) {
      username = _flarumHelpersUsername['default'];
    }, function (_flarumHelpersPunctuateSeries) {
      punctuateSeries = _flarumHelpersPunctuateSeries['default'];
    }],
    execute: function () {
      PostLikedNotification = (function (_Notification) {
        babelHelpers.inherits(PostLikedNotification, _Notification);

        function PostLikedNotification() {
          babelHelpers.classCallCheck(this, PostLikedNotification);
          babelHelpers.get(Object.getPrototypeOf(PostLikedNotification.prototype), 'constructor', this).apply(this, arguments);
        }

        babelHelpers.createClass(PostLikedNotification, [{
          key: 'icon',
          value: function icon() {
            return 'thumbs-o-up';
          }
        }, {
          key: 'href',
          value: function href() {
            return app.route.post(this.props.notification.subject());
          }
        }, {
          key: 'content',
          value: function content() {
            var notification = this.props.notification;
            var user = notification.sender();
            var auc = notification.additionalUnreadCount();

            return app.translator.transChoice('flarum-likes.forum.notifications.post_liked_text', auc + 1, {
              user: user,
              username: auc ? punctuateSeries([username(user), app.translator.transChoice('flarum-likes.forum.notifications.others_text', auc, { count: auc })]) : undefined
            });
          }
        }, {
          key: 'excerpt',
          value: function excerpt() {
            return this.props.notification.subject().contentPlain();
          }
        }]);
        return PostLikedNotification;
      })(Notification);

      _export('default', PostLikedNotification);
    }
  };
});;System.register('flarum/likes/components/PostLikesModal', ['flarum/components/Modal', 'flarum/helpers/avatar', 'flarum/helpers/username'], function (_export) {
  'use strict';

  var Modal, avatar, username, PostLikesModal;
  return {
    setters: [function (_flarumComponentsModal) {
      Modal = _flarumComponentsModal['default'];
    }, function (_flarumHelpersAvatar) {
      avatar = _flarumHelpersAvatar['default'];
    }, function (_flarumHelpersUsername) {
      username = _flarumHelpersUsername['default'];
    }],
    execute: function () {
      PostLikesModal = (function (_Modal) {
        babelHelpers.inherits(PostLikesModal, _Modal);

        function PostLikesModal() {
          babelHelpers.classCallCheck(this, PostLikesModal);
          babelHelpers.get(Object.getPrototypeOf(PostLikesModal.prototype), 'constructor', this).apply(this, arguments);
        }

        babelHelpers.createClass(PostLikesModal, [{
          key: 'className',
          value: function className() {
            return 'PostLikesModal Modal--small';
          }
        }, {
          key: 'title',
          value: function title() {
            return app.translator.trans('flarum-likes.forum.post_likes.title');
          }
        }, {
          key: 'content',
          value: function content() {
            return m(
              'div',
              { className: 'Modal-body' },
              m(
                'ul',
                { className: 'PostLikesModal-list' },
                this.props.post.likes().map(function (user) {
                  return m(
                    'li',
                    null,
                    m(
                      'a',
                      { href: app.route.user(user), config: m.route },
                      avatar(user),
                      ' ',
                      ' ',
                      username(user)
                    )
                  );
                })
              )
            );
          }
        }]);
        return PostLikesModal;
      })(Modal);

      _export('default', PostLikesModal);
    }
  };
});<|endoftext|>


<commit_before>/**
 * Accordion module.
 * @module foundation.accordion
 * @requires foundation.util.keyboard
 * @requires foundation.util.animationFrame
 */
!function($) {
  'use strict';

  /**
   * Creates a new instance of an accordion.
   * @class
   * @fires Accordion#init
   * @param {jQuery} element - jQuery object to make into an accordion.
   */
  function Accordion(element, options){
    this.$element = element;
    this.options = $.extend({}, Accordion.defaults, this.$element.data(), options || {});

    this._init();
    /**
     * Fires when the plugin has been successfuly initialized.
     * @event Accordion#init
     */
     Foundation.registerPlugin(this);
  }

  Accordion.defaults = {
    slideSpeed: 250,
    multiExpand: false,
    allowAllClosed: false
  };

  /**
   * Initializes the accordion by animating the preset active pane(s).
   * @private
   */
  Accordion.prototype._init = function() {
    this.$element.attr('role', 'tablist');
    this.$tabs = this.$element.find('li');
    this.$tabs.each(function(idx, el){
      var $el = $(el),
          $content = $el.find('[data-tab-content]'),
          id = $content[0].id || Foundation.GetYoDigits(6, 'accordion'),
          linkId = el.id || id + '-label';

      $el.find('a').attr({'aria-controls': id, 'role': 'tab'});
      $content.attr({'role': 'tabpanel', 'aria-labelledby': linkId})
    })
    var $initActive = this.$element.find('.is-active').children('[data-tab-content]');
    if($initActive.length){
      this.down($initActive, true);
    }
    this._events();
  };

  /**
   * Adds event handlers for items within the accordion.
   * @private
   */
  Accordion.prototype._events = function() {
    var _this = this;

    this.$element.find('li').each(function() {
      var $tabContent = $(this).children('[data-tab-content]');
      var $elem = $(this);
      if ($tabContent.length) {
        $(this).off('click.zf.accordion keydown.zf.accordion')
               .on('click.zf.accordion', function(e) {
        // $(this).children('a').on('click.zf.accordion', function(e) {
          e.preventDefault();
          if ($tabContent.parent().hasClass('is-active')) {
            if(_this.options.allowAllClosed || $tabContent.parent().siblings().hasClass('is-active')){
              _this.up($tabContent);
            }
          }
          else {
            _this.down($tabContent);
          }
        }).on('keydown.zf.accordion', function(e){
          Foundation.handleKey(e, _this, {
            toggle: function() {
              _this.toggle($tabContent);
            },
            next: function() {
              $tabContent.parent().next().find('a').focus().trigger('click.zf.accordion');
            },
            previous: function() {
              $tabContent.parent().prev().find('a').focus().trigger('click.zf.accordion');
            },
            handled: function() {
              e.preventDefault();
              e.stopPropagation();
            }
          });
        });
      }
    });
  };
  Accordion.prototype.toggle = function($target){
    if($target.parent().hasClass('is-active')){
      if(this.options.allowAllClosed || $target.parent().siblings().hasClass('is-active')){
        this.up($target);
      }else{ return; }
    }else{
      this.down($target);
    }
  };
  /**
   * Opens the accordion tab defined by `$target`.
   * @param {jQuery} $target - Accordion tab to open.
   * @fires Accordion#down
   */
  Accordion.prototype.down = function($target, firstTime) {
    var _this = this;
    if(!this.options.multiExpand && !firstTime){
      var $currentActive = this.$element.find('.is-active').children('[data-tab-content]');
      if($currentActive.length){
        this.up($currentActive);
      }
    }
    $target
      .parent('[data-tab-content]')
      .addBack()
      .parent().addClass('is-active');

    Foundation.Move(_this.options.slideSpeed, $target, function(){
      $target.slideDown(_this.options.slideSpeed);
    });

    if(!firstTime){
      console.log('reflowing yo!');
      Foundation._reflow(this.$element.data('accordion'));
    }
    /**
     * Fires when the tab is done opening.
     * @event Accordion#down
     */
    this.$element.trigger('down.zf.accordion', [$target]);
  };

  /**
   * Closes the tab defined by `$target`.
   * @param {jQuery} $target - Accordion tab to close.
   * @fires Accordion#up
   */
  Accordion.prototype.up = function($target) {
    var $aunts = $target.parent().siblings(),
        _this = this;
    var canClose = this.options.multiExpand ? $aunts.hasClass('is-active') : $target.parent().hasClass('is-active');

    if(!this.options.allowAllClosed && !canClose){
      return;
    }
    $target.find('[data-tab-content]').slideUp(0);

    Foundation.Move(this.options.slideSpeed, $target, function(){
      $target.slideUp(_this.options.slideSpeed)
    });
    // $target.slideUp(this.options.slideSpeed, function() {
    //   $target.find('[data-tab-content]').slideUp(0);
    // })
    $target.parent().removeClass('is-active');

    /**
     * Fires when the tab is done collapsing up.
     * @event Accordion#up
     */
    this.$element.trigger('up.zf.accordion', [$target]);
  };

  /**
   * Destroys an instance of an accordion.
   * @fires Accordion#destroyed
   */
  Accordion.prototype.destroy = function() {
    this.$element.find('[data-tab-content]').slideUp(0).css('display', '');
    this.$element.find('a').off('click.zf.accordion');

    /**
     * Fires when the plugin has been destroyed.
     * @event Accordion#destroyed
     */
    // this.$element.trigger('destroyed.zf.accordion');
    Foundation.unregisterPlugin(this);
  }

  Foundation.plugin(Accordion);
}(jQuery);
<commit_msg>improves accordion aria attributes<commit_after>/**
 * Accordion module.
 * @module foundation.accordion
 * @requires foundation.util.keyboard
 * @requires foundation.util.animationFrame
 */
!function($) {
  'use strict';

  /**
   * Creates a new instance of an accordion.
   * @class
   * @fires Accordion#init
   * @param {jQuery} element - jQuery object to make into an accordion.
   */
  function Accordion(element, options){
    this.$element = element;
    this.options = $.extend({}, Accordion.defaults, this.$element.data(), options || {});

    this._init();
    /**
     * Fires when the plugin has been successfuly initialized.
     * @event Accordion#init
     */
     Foundation.registerPlugin(this);
  }

  Accordion.defaults = {
    slideSpeed: 250,
    multiExpand: false,
    allowAllClosed: false
  };

  /**
   * Initializes the accordion by animating the preset active pane(s).
   * @private
   */
  Accordion.prototype._init = function() {
    this.$element.attr('role', 'tablist');
    this.$tabs = this.$element.find('li');
    this.$tabs.each(function(idx, el){

      var $el = $(el),
          $content = $el.find('[data-tab-content]'),
          id = $content[0].id || Foundation.GetYoDigits(6, 'accordion'),
          linkId = el.id || id + '-label';

      $el.find('a').attr({'aria-controls': id, 'role': 'tab', 'id': linkId});
      $content.attr({'role': 'tabpanel', 'aria-labelledby': linkId, 'aria-hidden': true, 'id': id});
    });
    var $initActive = this.$element.find('.is-active').children('[data-tab-content]');
    if($initActive.length){
      this.down($initActive, true);
    }
    this._events();
  };

  /**
   * Adds event handlers for items within the accordion.
   * @private
   */
  Accordion.prototype._events = function() {
    var _this = this;

    this.$element.find('li').each(function() {
      var $elem = $(this);
      var $tabContent = $elem.children('[data-tab-content]');
      if ($tabContent.length) {
        $elem.off('click.zf.accordion keydown.zf.accordion')
               .on('click.zf.accordion', function(e) {
        // $(this).children('a').on('click.zf.accordion', function(e) {
          e.preventDefault();
          if ($elem.hasClass('is-active')) {
            if(_this.options.allowAllClosed || $elem.siblings().hasClass('is-active')){
              _this.up($tabContent);
            }
          }
          else {
            _this.down($tabContent);
          }
        }).on('keydown.zf.accordion', function(e){
          Foundation.handleKey(e, _this, {
            toggle: function() {
              _this.toggle($tabContent);
            },
            next: function() {
              $elem.next().find('a').focus().trigger('click.zf.accordion');
            },
            previous: function() {
              $elem.prev().find('a').focus().trigger('click.zf.accordion');
            },
            handled: function() {
              e.preventDefault();
              e.stopPropagation();
            }
          });
        });
      }
    });
  };
  Accordion.prototype.toggle = function($target){
    if($target.parent().hasClass('is-active')){
      if(this.options.allowAllClosed || $target.parent().siblings().hasClass('is-active')){
        this.up($target);
      }else{ return; }
    }else{
      this.down($target);
    }
  };
  /**
   * Opens the accordion tab defined by `$target`.
   * @param {jQuery} $target - Accordion tab to open.
   * @fires Accordion#down
   */
  Accordion.prototype.down = function($target, firstTime) {
    var _this = this;
    if(!this.options.multiExpand && !firstTime){
      var $currentActive = this.$element.find('.is-active').children('[data-tab-content]');
      if($currentActive.length){
        this.up($currentActive);
      }
    }

    $target
      .attr('aria-hidden', false)
      .parent('[data-tab-content]')
      .addBack()
      .parent().addClass('is-active');

    Foundation.Move(_this.options.slideSpeed, $target, function(){
      $target.slideDown(_this.options.slideSpeed);
    });

    if(!firstTime){
      Foundation._reflow(this.$element.data('accordion'));
    }
    /**
     * Fires when the tab is done opening.
     * @event Accordion#down
     */
    this.$element.trigger('down.zf.accordion', [$target]);
  };

  /**
   * Closes the tab defined by `$target`.
   * @param {jQuery} $target - Accordion tab to close.
   * @fires Accordion#up
   */
  Accordion.prototype.up = function($target) {
    var $aunts = $target.parent().siblings(),
        _this = this;
    var canClose = this.options.multiExpand ? $aunts.hasClass('is-active') : $target.parent().hasClass('is-active');

    if(!this.options.allowAllClosed && !canClose){
      return;
    }

    Foundation.Move(this.options.slideSpeed, $target, function(){
      $target.slideUp(_this.options.slideSpeed)
    });

    $target.attr('aria-hidden', true)
           .parent().removeClass('is-active');

    /**
     * Fires when the tab is done collapsing up.
     * @event Accordion#up
     */
    this.$element.trigger('up.zf.accordion', [$target]);
  };

  /**
   * Destroys an instance of an accordion.
   * @fires Accordion#destroyed
   */
  Accordion.prototype.destroy = function() {
    this.$element.find('[data-tab-content]').slideUp(0).css('display', '');
    this.$element.find('a').off('.zf.accordion');

    /**
     * Fires when the plugin has been destroyed.
     * @event Accordion#destroyed
     */
    // this.$element.trigger('destroyed.zf.accordion');
    Foundation.unregisterPlugin(this);
  }

  Foundation.plugin(Accordion);
}(jQuery);
<|endoftext|>


<commit_before>'use strict';

// Declare app level module which depends on views, and components
angular.module('myApp', [
  'ngRoute',
  'myApp.block',
  'myApp.master',
  'myApp.version'
])
.config(['$routeProvider', function($routeProvider) {
  $routeProvider.otherwise({redirectTo: '/master'});
}])
.directive('transactionBars', [ function() {
	return {
      restrict: 'E',
      scope: {
        data: '='
      },
      link: function (scope, element) {
        //Set margins, width, and height
        var margin = {top: 0, right: 0, bottom: 40, left: 40},
          width = 1280 - margin.left - margin.right,
          height = 640 - margin.top - margin.bottom;

        //Create the d3 element and position it based on margins
        var svg = d3.select(element[0])
          .append("svg")
          .attr('width', width + margin.left + margin.right)
          .attr('height', height + margin.top + margin.bottom)
          .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        //Create the scales we need for the graph
        var x = d3.scale.ordinal().rangeRoundBands([0, width], .1);
        var y = d3.scale.linear().range([height, 0]);

        //Create the axes we need for the graph
        var xAxis = d3.svg.axis()
            .scale(x)
            .orient("bottom");

        var yAxis = d3.svg.axis()
            .scale(y)
            .orient("left")
            .ticks(10);

        //Render graph based on 'data'
        scope.render = function(data) {
		  //Set our scale's domains
		  x.domain(data.map(function(d) { return d.hash; }));
		  y.domain([0, d3.max(data, function(d) { return d.size; })]);

		  //Remove the axes so we can draw updated ones
		  svg.selectAll('g.axis').remove();

		  //Render X axis
		  svg.append("g")
			  .attr("class", "x axis")
			  .attr("transform", "translate(0," + height + ")")
			  .call(xAxis);

		  //Render Y axis
		  svg.append("g")
			  .attr("class", "y axis")
			  .call(yAxis)
			.append("text")
			  .attr("transform", "rotate(-90)")
			  .attr("y", 6)
			  .attr("dy", ".71em")
			  .style("text-anchor", "end")
			  .text("Transaction Size");

		  //Create or update the bar data
		  var bars = svg.selectAll(".bar").data(data);
		  bars.enter()
			.append("rect")
			.attr("class", "bar")
			.attr("x", function(d) { return x(d.hash); })
			.attr("width", x.rangeBand())
			.text(function(d) {return d.hash;});

		  //Animate bars
		  bars
			  .transition()
			  .duration(1000)
			  .attr('height', function(d) { return height - y(d.size); })
			  .attr("y", function(d) { return y(d.size); })
		};

        //Watch 'data' and run scope.render(newVal) whenever it changes
        //Use true for 'objectEquality' property so comparisons are done on equality and not reference
        scope.$watch('data', function(){
          scope.render(scope.data);
        }, true);
      }
    };
}]);
<commit_msg>tinkering<commit_after>'use strict';

// Declare app level module which depends on views, and components
angular.module('myApp', [
  'ngRoute',
  'myApp.block',
  'myApp.master',
  'myApp.version'
])
.config(['$routeProvider', function($routeProvider) {
  $routeProvider.otherwise({redirectTo: '/master'});
}])
.directive('transactionBars', [ function() {
	return {
      restrict: 'E',
      scope: {
        data: '='
      },
      link: function (scope, element) {
        //Set margins, width, and height
        var margin = {top: 0, right: 0, bottom: 40, left: 40},
          width = 1280 - margin.left - margin.right,
          height = 2560 - margin.top - margin.bottom;

        //Create the d3 element and position it based on margins
        var svg = d3.select(element[0])
          .append("svg")
          .attr('width', width + margin.left + margin.right)
          .attr('height', height + margin.top + margin.bottom)
          .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        //Create the scales we need for the graph
        var x = d3.scale.ordinal().rangeRoundBands([0, width], .1);
        var y = d3.scale.linear().range([height, 0]);

        //Create the axes we need for the graph
        var xAxis = d3.svg.axis()
            .scale(x)
            .orient("bottom");

        var yAxis = d3.svg.axis()
            .scale(y)
            .orient("left")
            .ticks(10);

        //Render graph based on 'data'
        scope.render = function(data) {
		  //Set our scale's domains
		  x.domain(data.map(function(d) { return d.hash; }));
		  y.domain([0, d3.max(data, function(d) { return d.size; })]);

		  //Remove the axes so we can draw updated ones
		  svg.selectAll('g.axis').remove();

		  //Render X axis
		  svg.append("g")
			  .attr("class", "x axis")
			  .attr("transform", "translate(0," + height + ")")
			  .call(xAxis);

		  //Render Y axis
		  svg.append("g")
			  .attr("class", "y axis")
			  .call(yAxis)
			.append("text")
			  .attr("transform", "rotate(-90)")
			  .attr("y", 6)
			  .attr("dy", ".71em")
			  .style("text-anchor", "end")
			  .text("Transaction Size");

		  //Create or update the bar data
		  var bars = svg.selectAll(".bar").data(data);
		  bars.enter()
			.append("rect")
			.attr("class", "bar")
			.attr("x", function(d) { return x(d.hash); })
			.attr("width", x.rangeBand());

		  //Animate bars
		  bars
			  .transition()
			  .duration(1000)
			  .attr('height', function(d) { return height - y(d.size); })
			  .attr("y", function(d) { return y(d.size); })
		};

        //Watch 'data' and run scope.render(newVal) whenever it changes
        //Use true for 'objectEquality' property so comparisons are done on equality and not reference
        scope.$watch('data', function(){
          scope.render(scope.data);
        }, true);
      }
    };
}]);
<|endoftext|>


<commit_before>// sensors
import {SingleList} from './sensors/SingleList';
import {MultiList} from './sensors/MultiList';
import {RangeSlider} from './sensors/RangeSlider';
import {TextField} from './sensors/TextField';
import {DataSearch} from './sensors/DataSearch';
import {SingleRange} from './sensors/SingleRange';
import {AppbaseList} from './sensors/AppbaseList';
import {AppbaseSlider} from './sensors/AppbaseSlider';
import {AppbaseSearch} from './sensors/AppbaseSearch';
import {AppbaseDistanceSensor} from './sensors/AppbaseDistanceSensor';
import {AppbaseInputField} from './sensors/AppbaseInputField';
import {AppbaseButtonGroup} from './sensors/AppbaseButtonGroup';
import {AppbaseGoogleSearch} from './sensors/AppbaseGoogleSearch';
import {MultiRange} from './sensors/MultiRange';
import {ToggleButton} from './sensors/ToggleButton';
// middleware
import {AppbaseReactiveMap} from './middleware/AppbaseReactiveMap';
import {manager} from './middleware/ChannelManager';
var helper = require('./middleware/helper.js');

module.exports = {
	AppbaseReactiveMap: AppbaseReactiveMap,
	SingleList: SingleList,
	MultiList: MultiList,
	RangeSlider: RangeSlider,
	TextField: TextField,
	DataSearch: DataSearch,
	SingleRange: SingleRange,
	MultiRange: MultiRange,
	ToggleButton: ToggleButton,
	AppbaseList: AppbaseList,
	AppbaseSlider: AppbaseSlider,
	AppbaseSearch: AppbaseSearch,
	AppbaseDistanceSensor: AppbaseDistanceSensor,
	AppbaseInputField: AppbaseInputField,
	AppbaseButtonGroup: AppbaseButtonGroup,
	AppbaseGoogleSearch: AppbaseGoogleSearch,
	AppbaseChannelManager: manager,
	AppbaseSensorHelper: helper
};
<commit_msg>Remove old sensors<commit_after>// sensors
import {SingleList} from './sensors/SingleList';
import {MultiList} from './sensors/MultiList';
import {RangeSlider} from './sensors/RangeSlider';
import {TextField} from './sensors/TextField';
import {DataSearch} from './sensors/DataSearch';
import {SingleRange} from './sensors/SingleRange';
import {MultiRange} from './sensors/MultiRange';
import {ToggleButton} from './sensors/ToggleButton';
// middleware
import {AppbaseReactiveMap} from './middleware/AppbaseReactiveMap';
import {manager} from './middleware/ChannelManager';
var helper = require('./middleware/helper.js');

module.exports = {
	SingleList: SingleList,
	MultiList: MultiList,
	RangeSlider: RangeSlider,
	TextField: TextField,
	DataSearch: DataSearch,
	SingleRange: SingleRange,
	MultiRange: MultiRange,
	ToggleButton: ToggleButton,
	AppbaseReactiveMap: AppbaseReactiveMap,
	AppbaseChannelManager: manager,
	AppbaseSensorHelper: helper
};
<|endoftext|>


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

/**
 * Gets configuration information that is required by the 'build' task.
 * Reads information from multiple places, including:
 *
 * chipper/build.json
 * $HOME/.phet/build-local.json
 * REPO/package.json
 * grunt.options( optionName )
 *
 * The information is shared via global variable global.phet.chipper.buildConfig.
 * All entries are @public (read-only).
 * Entries include:
 *
 * {string} name - name of the repository being built
 * {string} version - version identifier
 * {string} license - license
 * {string} simTitleStringKey - key of the sim's title string
 * {string} brand - brand identifier
 * {string[]} phetLibs - other repositories that are required by the sim
 * {string[]} preload - scripts that need to be preloaded in the .html file, in the order that they will be preloaded
 * {string[]} licenseKeys - keys to licenses in sherpa/lib/license.json, for third-party dependencies
 * {string} fallbackLocale - the locale to use if none is specified
 * {string[]} locales - locales to build
 * {Object} gruntConfig
 *
 * @author Chris Malley (PixelZoom, Inc.)
 */

// The following comment permits node-specific globals (such as process.cwd()) to pass jshint
/* jslint node: true */
'use strict';

// built-in node APIs
var assert = require( 'assert' );
var fs = require( 'fs' );

// 3rd-party packages
/* jshint -W079 */
var _ = require( '../../../sherpa/lib/lodash-2.4.1.min' ); // allow _ to be redefined, contrary to jshintOptions.js
/* jshint +W079 */

/**
 * @param {Object} grunt - the grunt instance
 */
module.exports = function( grunt ) {

  /**
   * Gets the brand identifier.
   *
   * @param {Object} grunt - the grunt instance
   * @param {Object} buildLocalJSON - build-local.json
   * @returns {string}
   */
  function getBrand( grunt, buildLocalJSON ) {
    return grunt.option( 'brand' ) || buildLocalJSON.brand || 'adapted-from-phet';
  }

  /**
   * Gets phetLibs, the set of repositories on which the repository being built depends.
   *
   * @param {Object} packageJSON - package.json
   * @param {Object} buildJSON - build.json
   * @param {string} brand
   * @returns {string[]}
   */
  function getPhetLibs( packageJSON, buildJSON, brand ) {

    // start with package.json
    var phetLibs = packageJSON.phet.phetLibs || [];

    // add the repo that's being built
    phetLibs.push( packageJSON.name );

    // add common and brand-specific entries from build.json
    [ 'common', brand ].forEach( function( id ) {
      if ( buildJSON[ id ] && buildJSON[ id ].phetLibs ) {
        phetLibs = phetLibs.concat( buildJSON[ id ].phetLibs );
      }
    } );

    // sort and remove duplicates
    return _.uniq( phetLibs.sort() );
  }

  /**
   * Gets preload, the set of scripts to be preloaded in the .html file.
   * NOTE! Order of the return value is significant, since it corresponds to the order in which scripts will be preloaded.
   *
   * @param {Object} packageJSON - package.json
   * @param {Object} buildJSON - build.json
   * @param {string} brand
   * @returns {string[]}
   */
  function getPreload( packageJSON, buildJSON, brand ) {

    var preload = [];

    // add preloads that are common to all sims, from build.json
    if ( buildJSON.common && buildJSON.common.preload ) {
      preload = preload.concat( buildJSON.common.preload );
    }

    // add sim-specific preloads from package.json
    if ( packageJSON.preload ) {
      preload = preload.concat( packageJSON.preload );
    }

    // add brand-specific preloads from build.json
    if ( buildJSON[ buildConfig.brand ] && buildJSON[ buildConfig.brand ].preload ) {
      preload = preload.concat( buildJSON[ buildConfig.brand ].preload );
    }

    // add the together API file
    if ( brand === 'phet-io' ) {
      var TOGETHER_API_FILENAME = '../together/js/api/' + packageJSON.name + '-api.js';
      assert( fs.existsSync( TOGETHER_API_FILENAME ), 'together API file does not exist: ' + TOGETHER_API_FILENAME );
      preload.push( TOGETHER_API_FILENAME );
    }

    // sort and remove duplicates
    return _.uniq( preload.sort() );
  }

  /**
   * Gets the license keys for sherpa (third-party) libs that are used.
   *
   * @param {Object} packageJSON - package.json
   * @param {Object} buildJSON - build.json
   * @param {string} brand
   * @param {string[]} preload
   * @returns {string[]}
   */
  function getLicenseKeys( packageJSON, buildJSON, brand, preload ) {

    // start with package.json
    var licenseKeys = packageJSON.phet.licenseKeys || [];

    // add common and brand-specific entries from build.json
    [ 'common', brand ].forEach( function( id ) {
      if ( buildJSON[ id ] && buildJSON[ id ].licenseKeys ) {
        licenseKeys = licenseKeys.concat( buildJSON[ id ].licenseKeys );
      }
    } );

    // Extract keys from preload for sherpa (third-party) dependencies
    preload.forEach( function( path ) {
      if ( path.indexOf( '/sherpa/' ) !== -1 ) {
        var lastSlash = path.lastIndexOf( '/' );
        var key = path.substring( lastSlash + 1 );
        licenseKeys.push( key );
      }
    } );

    // sort and remove duplicates
    return _.uniq( _.sortBy( licenseKeys, function( key ) { return key.toUpperCase(); } ) );
  }

  /*
   * Gets the locales from a repository, by inspecting the names of the string files in that repository.
   *
   * @param {string} repository - name of the repository to get locales from
   */
  function getLocalesFromRepository( repository ) {

    // confirm that the repository has a strings directory
    var stringsDirectory = '../babel/' + repository;
    var stats = fs.statSync( stringsDirectory );
    assert( stats.isDirectory(), stringsDirectory + 'is not a directory' );

    // Get names of string files.
    var stringFiles = fs.readdirSync( stringsDirectory ).filter( function( filename ) {
      return (/^.*-strings.*\.json/).test( filename );
    } );
    assert( stringFiles.length > 0, 'no string files found in ' + stringsDirectory );

    // Extract the locales from the file names.
    // File names must have a form like 'graphing-lines-strings_ar_SA.json', where no '_' appear in the repo name.
    var locales = stringFiles.map( function( filename ) {
      return filename.substring( filename.indexOf( '_' ) + 1, filename.lastIndexOf( '.' ) );
    } );
    assert( locales.length > 0, 'no locales found in ' + stringsDirectory );

    return locales;
  }

  /**
   * Gets the set of locales to be built.
   *
   * The grunt options are:
   *
   * --locales=* : all locales from the repo's strings/ directory
   * --locales=fr : French
   * --locales=ar,fr,es : Arabic, French and Spanish (comma-separated locales)
   * --localesRepo=beers-law-lab: all locales from another repository's strings/ directory, ignored if --locales is specified
   *
   * @param {Object} grunt - the grunt instance
   * @param {string} repository - name of the repository that is being built
   * @param {string} fallbackLocale - the locale to build if no locales are specified
   */
  function getLocales( grunt, repository, fallbackLocale ) {

    var locales = grunt.option( 'locales' );

    if ( locales ) {
      if ( locales === '*' ) {
        locales = getLocalesFromRepository( repository ); // all locales for the repository that we're building
      }
      else {
        buildConfig.locales = _.uniq( gruntOptions.locales.split( ',' ) );
      }
    }
    else {
      var localesRepo = grunt.option( 'localesRepo' );
      if ( localesRepo ) {
        locales = getLocalesFromRepository( localesRepo ); // all locales for some other repository
      }
      else {
        locales = [ fallbackLocale ];
      }
    }
    return locales;
  }

  /**
   * Gets the JSHint configuration object.
   *
   * @param {Object} packageJSON - package.json
   * @param {string[]} phetLibs
   * @returns {Object}
   */
  function getJSHintConfig( packageJSON, phetLibs ) {

    // Repository files to be linted. brand has a non-standard directory structure.
    var repoFilesToLint = ( packageJSON.name === 'brand' ) ? [ '*/js/**/*.js' ] : [ 'js/**/*.js' ];

    // All files to be linted
    var allFilesToLint = _.map( phetLibs, function( repo ) {
      return '../' + repo + '/js/**/*.js';
    } );

    // brand repo has a non-standard directory structure, so add it explicitly if it's a dependency.
    if ( packageJSON.name !== 'brand' ) {
      allFilesToLint.push( '../brand/*/js/**/*.js' );
    }

    // Exclude svgPath.js, it was automatically generated and doesn't match pass lint.
    allFilesToLint.push( '!../kite/js/parser/svgPath.js' );
    allFilesToLint = _.uniq( allFilesToLint );

    //TODO chipper#276 provide a reference for where these fields are defined
    return {

      // Source files that are specific to this repository
      repoFiles: repoFilesToLint,

      // All source files for this repository (repository-specific and dependencies).
      allFiles: allFilesToLint,

      // Reference external options in jshintOptions.js
      options: require( './jshintOptions' )
    };
  }

  /**
   * Gets the Grunt configuration object.
   *
   * @param {Object} packageJSON - package.json
   * @param {strings[]} phetLibs
   */
  function getGruntConfig( packageJSON, phetLibs ) {
    return {

      //TODO chipper#278 is this necessary?
      // Setting pkg allows us to refer to package.json entries from within this config
      pkg: packageJSON,

      jshint: getJSHintConfig( packageJSON, phetLibs ),

      //TODO chipper#277 provide a reference for where these fields are defined
      // configure the RequireJS plugin
      requirejs: {

        // builds the minified script
        build: {

          options: {

            almond: true,
            //TODO chipper#278 is this necessary?
            mainConfigFile: 'js/<%= pkg.name %>-config.js',
            out: 'build/<%= pkg.name %>.min.js',
            name: '<%= pkg.name %>-config',

            // Minification strategy.  Put this to none if you want to debug a non-minified but compiled version
            optimize: 'uglify2',
            wrap: true,
            // generateSourceMaps: true, //#42 commented out this line until source maps are fixed
            preserveLicenseComments: false,
            uglify2: {
              output: {
                inline_script: true // escape </script
              },
              compress: {
                global_defs: {
                  // global assertions
                  assert: false,
                  assertSlow: false,
                  // scenery logging
                  sceneryLog: false,
                  sceneryLayerLog: false,
                  sceneryEventLog: false,
                  sceneryAccessibilityLog: false,
                  phetAllocation: false
                },
                dead_code: true
              }
            },

            //TODO chipper#275 should 'mipmap' be included here too?
            // stub out the plugins, so their source code won't be included in the minified file
            stubModules: [ 'string', 'audio', 'image' ]
          }
        }
      }
    };
  }

  //------------------------------------------------------------------------------------
  // read configuration files

  // ./package.json (required)
  var PACKAGE_FILENAME = 'package.json';
  assert( fs.existsSync( PACKAGE_FILENAME ), 'missing ' + PACKAGE_FILENAME );
  var packageJSON = grunt.file.readJSON( PACKAGE_FILENAME );
  assert( packageJSON.name, 'name missing from ' + PACKAGE_FILENAME );
  assert( packageJSON.version, 'version missing from ' + PACKAGE_FILENAME );
  assert( packageJSON.license, 'license missing from ' + PACKAGE_FILENAME );

  // chipper/build.json (required)
  var BUILD_FILENAME = '../chipper/build.json';
  assert( fs.existsSync( BUILD_FILENAME ), 'missing ' + BUILD_FILENAME );
  var buildJSON = grunt.file.readJSON( BUILD_FILENAME );

  // $HOME/.phet/build-local.json (optional)
  var BUILD_LOCAL_FILENAME = process.env.HOME + '/.phet/build-local.json';
  var buildLocalJSON = {};
  if ( fs.existsSync( BUILD_LOCAL_FILENAME ) ) {
    buildLocalJSON = grunt.file.readJSON( BUILD_LOCAL_FILENAME );
  }

  //------------------------------------------------------------------------------------
  // Assemble the buildConfig

  var buildConfig = {
    // These entries have no dependencies on other entries in buildConfig.
    name: packageJSON.name,
    version: packageJSON.version,
    license: packageJSON.name,
    simTitleStringKey: packageJSON.simTitleStringKey,
    brand: getBrand( grunt, buildLocalJSON ),
    fallbackLocale: 'en'
  };

  // These entries depend on other entries in buildConfig.
  buildConfig.phetLibs = getPhetLibs( packageJSON, buildJSON, buildConfig.brand );
  buildConfig.preload = getPreload( packageJSON, buildJSON, buildConfig.brand );
  buildConfig.licenseKeys = getLicenseKeys( packageJSON, buildJSON, buildConfig.brand, buildConfig.preload );
  buildConfig.locales = getLocales( grunt, buildConfig.name, buildConfig.fallbackLocale );
  buildConfig.gruntConfig = getGruntConfig( packageJSON, buildConfig.phetLibs );

  grunt.log.debug( 'buildConfig=' + JSON.stringify( buildConfig, null, 2 ) );
  return buildConfig;
};
<commit_msg>#232 fix in getLocales<commit_after>// Copyright 2002-2015, University of Colorado Boulder

/**
 * Gets configuration information that is required by the 'build' task.
 * Reads information from multiple places, including:
 *
 * chipper/build.json
 * $HOME/.phet/build-local.json
 * REPO/package.json
 * grunt.options( optionName )
 *
 * The information is shared via global variable global.phet.chipper.buildConfig.
 * All entries are @public (read-only).
 * Entries include:
 *
 * {string} name - name of the repository being built
 * {string} version - version identifier
 * {string} license - license
 * {string} simTitleStringKey - key of the sim's title string
 * {string} brand - brand identifier
 * {string[]} phetLibs - other repositories that are required by the sim
 * {string[]} preload - scripts that need to be preloaded in the .html file, in the order that they will be preloaded
 * {string[]} licenseKeys - keys to licenses in sherpa/lib/license.json, for third-party dependencies
 * {string} fallbackLocale - the locale to use if none is specified
 * {string[]} locales - locales to build
 * {Object} gruntConfig
 *
 * @author Chris Malley (PixelZoom, Inc.)
 */

// The following comment permits node-specific globals (such as process.cwd()) to pass jshint
/* jslint node: true */
'use strict';

// built-in node APIs
var assert = require( 'assert' );
var fs = require( 'fs' );

// 3rd-party packages
/* jshint -W079 */
var _ = require( '../../../sherpa/lib/lodash-2.4.1.min' ); // allow _ to be redefined, contrary to jshintOptions.js
/* jshint +W079 */

/**
 * @param {Object} grunt - the grunt instance
 */
module.exports = function( grunt ) {

  /**
   * Gets the brand identifier.
   *
   * @param {Object} grunt - the grunt instance
   * @param {Object} buildLocalJSON - build-local.json
   * @returns {string}
   */
  function getBrand( grunt, buildLocalJSON ) {
    return grunt.option( 'brand' ) || buildLocalJSON.brand || 'adapted-from-phet';
  }

  /**
   * Gets phetLibs, the set of repositories on which the repository being built depends.
   *
   * @param {Object} packageJSON - package.json
   * @param {Object} buildJSON - build.json
   * @param {string} brand
   * @returns {string[]}
   */
  function getPhetLibs( packageJSON, buildJSON, brand ) {

    // start with package.json
    var phetLibs = packageJSON.phet.phetLibs || [];

    // add the repo that's being built
    phetLibs.push( packageJSON.name );

    // add common and brand-specific entries from build.json
    [ 'common', brand ].forEach( function( id ) {
      if ( buildJSON[ id ] && buildJSON[ id ].phetLibs ) {
        phetLibs = phetLibs.concat( buildJSON[ id ].phetLibs );
      }
    } );

    // sort and remove duplicates
    return _.uniq( phetLibs.sort() );
  }

  /**
   * Gets preload, the set of scripts to be preloaded in the .html file.
   * NOTE! Order of the return value is significant, since it corresponds to the order in which scripts will be preloaded.
   *
   * @param {Object} packageJSON - package.json
   * @param {Object} buildJSON - build.json
   * @param {string} brand
   * @returns {string[]}
   */
  function getPreload( packageJSON, buildJSON, brand ) {

    var preload = [];

    // add preloads that are common to all sims, from build.json
    if ( buildJSON.common && buildJSON.common.preload ) {
      preload = preload.concat( buildJSON.common.preload );
    }

    // add sim-specific preloads from package.json
    if ( packageJSON.preload ) {
      preload = preload.concat( packageJSON.preload );
    }

    // add brand-specific preloads from build.json
    if ( buildJSON[ buildConfig.brand ] && buildJSON[ buildConfig.brand ].preload ) {
      preload = preload.concat( buildJSON[ buildConfig.brand ].preload );
    }

    // add the together API file
    if ( brand === 'phet-io' ) {
      var TOGETHER_API_FILENAME = '../together/js/api/' + packageJSON.name + '-api.js';
      assert( fs.existsSync( TOGETHER_API_FILENAME ), 'together API file does not exist: ' + TOGETHER_API_FILENAME );
      preload.push( TOGETHER_API_FILENAME );
    }

    // sort and remove duplicates
    return _.uniq( preload.sort() );
  }

  /**
   * Gets the license keys for sherpa (third-party) libs that are used.
   *
   * @param {Object} packageJSON - package.json
   * @param {Object} buildJSON - build.json
   * @param {string} brand
   * @param {string[]} preload
   * @returns {string[]}
   */
  function getLicenseKeys( packageJSON, buildJSON, brand, preload ) {

    // start with package.json
    var licenseKeys = packageJSON.phet.licenseKeys || [];

    // add common and brand-specific entries from build.json
    [ 'common', brand ].forEach( function( id ) {
      if ( buildJSON[ id ] && buildJSON[ id ].licenseKeys ) {
        licenseKeys = licenseKeys.concat( buildJSON[ id ].licenseKeys );
      }
    } );

    // Extract keys from preload for sherpa (third-party) dependencies
    preload.forEach( function( path ) {
      if ( path.indexOf( '/sherpa/' ) !== -1 ) {
        var lastSlash = path.lastIndexOf( '/' );
        var key = path.substring( lastSlash + 1 );
        licenseKeys.push( key );
      }
    } );

    // sort and remove duplicates
    return _.uniq( _.sortBy( licenseKeys, function( key ) { return key.toUpperCase(); } ) );
  }

  /*
   * Gets the locales from a repository, by inspecting the names of the string files in that repository.
   *
   * @param {string} repository - name of the repository to get locales from
   */
  function getLocalesFromRepository( repository ) {

    // confirm that the repository has a strings directory
    var stringsDirectory = '../babel/' + repository;
    var stats = fs.statSync( stringsDirectory );
    assert( stats.isDirectory(), stringsDirectory + 'is not a directory' );

    // Get names of string files.
    var stringFiles = fs.readdirSync( stringsDirectory ).filter( function( filename ) {
      return (/^.*-strings.*\.json/).test( filename );
    } );
    assert( stringFiles.length > 0, 'no string files found in ' + stringsDirectory );

    // Extract the locales from the file names.
    // File names must have a form like 'graphing-lines-strings_ar_SA.json', where no '_' appear in the repo name.
    var locales = stringFiles.map( function( filename ) {
      return filename.substring( filename.indexOf( '_' ) + 1, filename.lastIndexOf( '.' ) );
    } );
    assert( locales.length > 0, 'no locales found in ' + stringsDirectory );

    return locales;
  }

  /**
   * Gets the set of locales to be built.
   *
   * The grunt options are:
   *
   * --locales=* : all locales from the repo's strings/ directory
   * --locales=fr : French
   * --locales=ar,fr,es : Arabic, French and Spanish (comma-separated locales)
   * --localesRepo=beers-law-lab: all locales from another repository's strings/ directory, ignored if --locales is specified
   *
   * @param {Object} grunt - the grunt instance
   * @param {string} repository - name of the repository that is being built
   * @param {string} fallbackLocale - the locale to build if no locales are specified
   */
  function getLocales( grunt, repository, fallbackLocale ) {

    var locales = grunt.option( 'locales' );

    if ( locales ) {
      if ( locales === '*' ) {
        locales = getLocalesFromRepository( repository ); // all locales for the repository that we're building
      }
      else {
        locales = _.uniq( locales.split( ',' ) );
      }
    }
    else {
      var localesRepo = grunt.option( 'localesRepo' );
      if ( localesRepo ) {
        locales = getLocalesFromRepository( localesRepo ); // all locales for some other repository
      }
      else {
        locales = [ fallbackLocale ];
      }
    }
    return locales;
  }

  /**
   * Gets the JSHint configuration object.
   *
   * @param {Object} packageJSON - package.json
   * @param {string[]} phetLibs
   * @returns {Object}
   */
  function getJSHintConfig( packageJSON, phetLibs ) {

    // Repository files to be linted. brand has a non-standard directory structure.
    var repoFilesToLint = ( packageJSON.name === 'brand' ) ? [ '*/js/**/*.js' ] : [ 'js/**/*.js' ];

    // All files to be linted
    var allFilesToLint = _.map( phetLibs, function( repo ) {
      return '../' + repo + '/js/**/*.js';
    } );

    // brand repo has a non-standard directory structure, so add it explicitly if it's a dependency.
    if ( packageJSON.name !== 'brand' ) {
      allFilesToLint.push( '../brand/*/js/**/*.js' );
    }

    // Exclude svgPath.js, it was automatically generated and doesn't match pass lint.
    allFilesToLint.push( '!../kite/js/parser/svgPath.js' );
    allFilesToLint = _.uniq( allFilesToLint );

    //TODO chipper#276 provide a reference for where these fields are defined
    return {

      // Source files that are specific to this repository
      repoFiles: repoFilesToLint,

      // All source files for this repository (repository-specific and dependencies).
      allFiles: allFilesToLint,

      // Reference external options in jshintOptions.js
      options: require( './jshintOptions' )
    };
  }

  /**
   * Gets the Grunt configuration object.
   *
   * @param {Object} packageJSON - package.json
   * @param {strings[]} phetLibs
   */
  function getGruntConfig( packageJSON, phetLibs ) {
    return {

      //TODO chipper#278 is this necessary?
      // Setting pkg allows us to refer to package.json entries from within this config
      pkg: packageJSON,

      jshint: getJSHintConfig( packageJSON, phetLibs ),

      //TODO chipper#277 provide a reference for where these fields are defined
      // configure the RequireJS plugin
      requirejs: {

        // builds the minified script
        build: {

          options: {

            almond: true,
            //TODO chipper#278 is this necessary?
            mainConfigFile: 'js/<%= pkg.name %>-config.js',
            out: 'build/<%= pkg.name %>.min.js',
            name: '<%= pkg.name %>-config',

            // Minification strategy.  Put this to none if you want to debug a non-minified but compiled version
            optimize: 'uglify2',
            wrap: true,
            // generateSourceMaps: true, //#42 commented out this line until source maps are fixed
            preserveLicenseComments: false,
            uglify2: {
              output: {
                inline_script: true // escape </script
              },
              compress: {
                global_defs: {
                  // global assertions
                  assert: false,
                  assertSlow: false,
                  // scenery logging
                  sceneryLog: false,
                  sceneryLayerLog: false,
                  sceneryEventLog: false,
                  sceneryAccessibilityLog: false,
                  phetAllocation: false
                },
                dead_code: true
              }
            },

            //TODO chipper#275 should 'mipmap' be included here too?
            // stub out the plugins, so their source code won't be included in the minified file
            stubModules: [ 'string', 'audio', 'image' ]
          }
        }
      }
    };
  }

  //------------------------------------------------------------------------------------
  // read configuration files

  // ./package.json (required)
  var PACKAGE_FILENAME = 'package.json';
  assert( fs.existsSync( PACKAGE_FILENAME ), 'missing ' + PACKAGE_FILENAME );
  var packageJSON = grunt.file.readJSON( PACKAGE_FILENAME );
  assert( packageJSON.name, 'name missing from ' + PACKAGE_FILENAME );
  assert( packageJSON.version, 'version missing from ' + PACKAGE_FILENAME );
  assert( packageJSON.license, 'license missing from ' + PACKAGE_FILENAME );

  // chipper/build.json (required)
  var BUILD_FILENAME = '../chipper/build.json';
  assert( fs.existsSync( BUILD_FILENAME ), 'missing ' + BUILD_FILENAME );
  var buildJSON = grunt.file.readJSON( BUILD_FILENAME );

  // $HOME/.phet/build-local.json (optional)
  var BUILD_LOCAL_FILENAME = process.env.HOME + '/.phet/build-local.json';
  var buildLocalJSON = {};
  if ( fs.existsSync( BUILD_LOCAL_FILENAME ) ) {
    buildLocalJSON = grunt.file.readJSON( BUILD_LOCAL_FILENAME );
  }

  //------------------------------------------------------------------------------------
  // Assemble the buildConfig

  var buildConfig = {
    // These entries have no dependencies on other entries in buildConfig.
    name: packageJSON.name,
    version: packageJSON.version,
    license: packageJSON.name,
    simTitleStringKey: packageJSON.simTitleStringKey,
    brand: getBrand( grunt, buildLocalJSON ),
    fallbackLocale: 'en'
  };

  // These entries depend on other entries in buildConfig.
  buildConfig.phetLibs = getPhetLibs( packageJSON, buildJSON, buildConfig.brand );
  buildConfig.preload = getPreload( packageJSON, buildJSON, buildConfig.brand );
  buildConfig.licenseKeys = getLicenseKeys( packageJSON, buildJSON, buildConfig.brand, buildConfig.preload );
  buildConfig.locales = getLocales( grunt, buildConfig.name, buildConfig.fallbackLocale );
  buildConfig.gruntConfig = getGruntConfig( packageJSON, buildConfig.phetLibs );

  grunt.log.debug( 'buildConfig=' + JSON.stringify( buildConfig, null, 2 ) );
  return buildConfig;
};
<|endoftext|>


<commit_before>import Ember from 'ember';
import Resolver from './resolver';
import loadInitializers from 'ember-load-initializers';
import config from './config/environment';

let App;

Ember.MODEL_FACTORY_INJECTIONS = true;

App = Ember.Application.extend({
    modulePrefix: config.modulePrefix,
    podModulePrefix: config.podModulePrefix,
    Resolver,

    init() {
        this._super(...arguments);

        window.App = this;
    },

    serviceFor(name) {
        return this.__container__.lookup(`service:${name}`);
    }
});

loadInitializers(App, config.modulePrefix);

export default App;
<commit_msg>add componentFor for debugging<commit_after>import Ember from 'ember';
import Resolver from './resolver';
import loadInitializers from 'ember-load-initializers';
import config from './config/environment';

let App;

Ember.MODEL_FACTORY_INJECTIONS = true;

App = Ember.Application.extend({
    modulePrefix: config.modulePrefix,
    podModulePrefix: config.podModulePrefix,
    Resolver,

    init() {
        this._super(...arguments);

        window.App = this;
    },

    serviceFor(name) {
        return this.__container__.lookup(`service:${name}`);
    },

    componentFor: function (id) {
        return this.__container__.lookup('-view-registry:main')[id];
    }
});

loadInitializers(App, config.modulePrefix);

export default App;
<|endoftext|>


<commit_before>// actionConfirm plugin
// Call on <a> or <button>
// Prompts user with a dialog box to confirm their action.
// If the user confirms then the form is submitted if a button otherwise navigates to the anchor href.
;(function($, undefined) {
    $.fn.actionConfirm = function() {
        this.on('click', function(event) {
            event.preventDefault();
	    var $element = $(this);

            if ( ( ! $element.is('.disabled')) ) {
                var title = $element.text();
                var text = 'Are you sure you want to ' + coalesce($element.attr('title'), $element.text()) + '?';
                var tag = $element.prop('tagName');
                switch(tag) {
                case "BUTTON":
                    var yesFunction = function() {
                        $element.closest('form').submit();
                    }

                    break;
                case "A":
                    if ( ! $element.attr('href') ) {
                        return;
                    }

                    var yesFunction = function() {
                        window.location = $element.attr('href');
                    }

                    break;
                default:
                    return;
                }

	        $('<div>')
		        .text(text)
		        .dialog({
		            title: title,
		            buttons: {
			        Yes: yesFunction,
			        No: function() {
			            $(this).dialog('close').dialog('destroy').remove();
			        }
		            },
		            modal: true,
		            width: 400,
		            height: 200
		        });
	    }
        });
    }
})(jQuery);<commit_msg>comments<commit_after>// actionConfirm plugin
// Call on <a> or <button>
// Prompts user with a dialog box to confirm their action.
// If the user confirms then the form is submitted if a button otherwise navigates to the anchor href.
;(function($, undefined) {
    $.fn.actionConfirm = function() {
        this.on('click', function(event) {
            event.preventDefault();
	    var $element = $(this);

            if ( ( ! $element.is('.disabled')) ) {
                var title = $element.text();
                var text = 'Are you sure you want to ' + coalesce($element.attr('title'), $element.text()) + '?';
                var tag = $element.prop('tagName');
                switch(tag) {
                case "BUTTON":
                    var yesFunction = function() {
                        // Submit the form that the button belongs to.
                        $element.closest('form').submit();
                    }

                    break;
                case "A":
                    if ( ! $element.attr('href') ) {
                        return;
                    }

                    var yesFunction = function() {
                        // Navigate to the anchor href.
                        window.location = $element.attr('href');
                    }

                    break;
                default:
                    return;
                }

                // Dialog prompt for user to confirm their action.
	        $('<div>')
		        .text(text)
		        .dialog({
		            title: title,
		            buttons: {
			        Yes: yesFunction,
			        No: function() {
			            $(this).dialog('close').dialog('destroy').remove();
			        }
		            },
		            modal: true,
		            width: 400,
		            height: 200
		        });
	    }
        });
    }
})(jQuery);<|endoftext|>


<commit_before>'use strict';

// Declare app level module which depends on views, and components
angular.module('myApp', [
  'ngRoute',
  'myApp.version'
])
    .service("IDUpdate", function($rootScope) {
        return {
            setID: function(type, id) {
                this[type] = id;
                $rootScope.$broadcast("IDUpdated", {
                    type: type, recID: id
                });
            }
        }
    })
    .config(['$routeProvider', function($routeProvider) {
        $routeProvider.
            when('/multirow'  , {templateUrl: 'partials/multiRow.html', controller: 'multiRowCtrl'}).
            when('/singlerow' , {redirectTo:  'partials/singleRow.html'}).
            when('/edit/:id'  , {templateUrl: 'partials/singleRow.html', controller: 'singleRowCtrl'}).
            when('/add'       , {templateUrl: 'partials/singleRow.html', controller: 'singleRowCtrl'}).
            otherwise(          {templateUrl: 'partials/multiRow.html',controller: 'multiRowCtrl'});
    }])
    .controller('multiRowCtrl', function( $scope, $http, IDUpdate) {

        console.log('in de multiRowCtrl controller')

        var refresh = function() {
            $http.get('http://wlo1.open-i.nl:8888/rest/fine/finecr%24products?app_name=Fine')
                .success(function(response){
                    console.log('data wordt ververst');
                    // De rijen zitten in een 'record' node, dus:
                    $scope.productlist = response.record;
                    console.log('data is ververst');
                    //     $scope.emp ="";
                })
                .error(function(response){
                    console.log('Fout: ' +response);
                })
        }

        console.log("Refresh scope.");
        refresh();

        $scope.edit = function(id) {
            console.log(id);
            $scope.modus = 'UPDATE';
            window.location.href = "#/edit/" + id;
        }

    })

    .controller('singleRowCtrl', ['$scope','$http', '$routeParams', function ($scope,$http,$routeParams) {
        console.log('singlerow...')
        if (angular.isDefined($scope.productlist)) {
            console.log('id=' + $routeParams.id);
            $scope.product = $scope.productlist[$routeParams.id];
        } else {
            console.log('$scope.productlist is niet gedefinieerd');
            // Reload is hier niet mogelijk, daarom terug naar hoofdscherm.
            // window.location.href = "/";
        }

        $scope.update = function () {
            console.log($scope.product.ID);
            $http.put('http://wlo1.open-i.nl:8888/rest/fine/EMP/' + $scope.product.ID + '?app_name=Fine', $scope.product).success(function(response) {
                console.log('update uitgevoerd')
            })

        }

    }]);
<commit_msg>Laatse wijz. zondag<commit_after>'use strict';

// Declare app level module which depends on views, and components
angular.module('myApp', [
  'ngRoute',
  'myApp.version'
])

    .config(['$routeProvider', function($routeProvider) {
        $routeProvider.
            when('/multirow'  , {templateUrl: 'partials/multiRow.html', controller: 'multiRowCtrl'}).
            when('/singlerow' , {redirectTo:  'partials/singleRow.html'}).
            when('/edit/:id'  , {templateUrl: 'partials/singleRow.html', controller: 'singleRowCtrl'}).
            when('/add'       , {templateUrl: 'partials/singleRow.html', controller: 'singleRowCtrl'}).
            otherwise(          {templateUrl: 'partials/multiRow.html',controller: 'multiRowCtrl'});
    }])
    .controller('multiRowCtrl', function( $scope, $http) {

        console.log('in de multiRowCtrl controller')

        var refresh = function() {
            $http.get('http://wlo1.open-i.nl:8888/rest/fine/finecr%24products?app_name=Fine')
                .success(function(response){
                    console.log('data wordt ververst');
                    // De rijen zitten in een 'record' node, dus:
                    $scope.productlist = response.record;
                    console.log('data is ververst');
                    //     $scope.emp ="";
                })
                .error(function(response){
                    console.log('Fout: ' +response);
                })
        }

        console.log("Refresh scope.");
        refresh();

        $scope.edit = function(id) {
            console.log(id);
            $scope.modus = 'UPDATE';
            window.location.href = "#/edit/" + id;
        }

    })

    .controller('singleRowCtrl', ['$scope','$http', '$routeParams', function ($scope,$http,$routeParams) {
        console.log('singlerow...')
        if (angular.isDefined($scope.productlist)) {
            console.log('id=' + $routeParams.id);
            $scope.product = $scope.productlist[$routeParams.id];
        } else {
            console.log('$scope.productlist is niet gedefinieerd');
            // Reload is hier niet mogelijk, daarom terug naar hoofdscherm.
            // window.location.href = "/";
        }

        $scope.update = function () {
            console.log($scope.product.ID);
            $http.put('http://wlo1.open-i.nl:8888/rest/fine/EMP/' + $scope.product.ID + '?app_name=Fine', $scope.product).success(function(response) {
                console.log('update uitgevoerd')
            })

        }

    }]);
<|endoftext|>


<commit_before>/* jQueryMobile-router v0.3
 * Copyright 2011, Andrea Zicchetti
 */
(function($){

$(document).bind("mobileinit",function(){

	/* supports the following configurations:
		$.mobile.jqmRouter.fixFirstPageDataUrl=true
		$.mobile.jqmRouter.firstPageDataUrl="index.html"
			jQM doesn't handle correctly the dataurl of the first page you display
			in a single-page template mode. In fact, the page is fetched again
			from the server the first time you try to access it through a link.
			If this option is set to true, jquery mobile router extensions will
			try to fix this problem. In order to set the data url, you have to
			provide the name of the file containing the first page into the
			"firstPageDataUrl" property (for example: index.html)

	*/

	var config=$.extend({
		fixFirstPageDataUrl: false, firstPageDataUrl: "index.html"
	},$.mobile.jqmRouter || {});

	var DEBUG=true;
	function debug(err){
		if (DEBUG) console.log(err);
	}

	var previousUrl=null, nextUrl=null;

	$(document).bind("pagebeforechange", function( e, data ) {
		// We only want to handle changePage() calls where the caller is
		// asking us to load a page by URL.
		if ( typeof data.toPage === "string" ) {
			// We are being asked to load a page by URL, but we only
			// want to handle URLs that request the data for a specific
			// category.
			var u = $.mobile.path.parseUrl( data.toPage );
			previousUrl=nextUrl;
			nextUrl=u;

			if ( u.hash.indexOf("?") !== -1 ) {
				var page=u.hash.replace( /\?.*$/, "" );
				// We don't want the data-url of the page we just modified
				// to be the url that shows up in the browser's location field,
				// so set the dataUrl option to the URL for the category
				// we just loaded.
				data.options.dataUrl = u.href;
				// Now call changePage() and tell it to switch to
				// the page we just modified, but only in case it's different
				// from the current page
				if (	$.mobile.activePage &&
					page.replace(/^#/,"")==$.mobile.activePage.jqmData("url")
				){
					var ui={ prevPage: $.mobile.activePage };
					$.mobile.activePage
						.trigger("pagebeforeshow",[ui])
						.trigger("pageshow",[ui])
					;
				} else {
					$.mobile.changePage( $(page), data.options );
				}
				// Make sure to tell changePage() we've handled this call so it doesn't
				// have to do anything.
				e.preventDefault();
			}
		}
	});

	if (config.fixFirstPageDataUrl){
		$(document).ready(function(){
			var page=$(":jqmData(role='page')").first();
			var	dataUrl=page.jqmData("url"),
				guessedDataUrl=
					window.location.pathname.slice(-1)=="/"?
						window.location.pathname
						+config.firstPageDataUrl
						:window.location.pathname
			;
			if (dataUrl!=guessedDataUrl){
				page.attr("data-url",guessedDataUrl)
					.jqmData("url",guessedDataUrl);
			}
		});
	}

	$.mobile.Router=function(userRoutes,userHandlers,conf){
		/* userRoutes format:
			{
				"regexp": "function name", // defaults to jqm pagebeforeshow event
				"regexp": function(){ ... }, // defaults to jqm pagebeforeshow event
				"regexp": { handler: "function name", events: "bc,c,bs,s,bh,h"	},
				"regexp": { handler: function(){ ... }, events: "bc,c,bs,s,bh,h" }
			}
		*/
		this.routes={
			pagebeforecreate: null, pagecreate: null,
			pagebeforeshow: null, pageshow: null,
			pagebeforehide: null, pagehide: null,
			pageinit: null
		};
		this.routesRex={};
		this.conf=$.extend({
			ajaxApp: false
		}, config || {});
		this.add(userRoutes,userHandlers);
	}
	$.extend($.mobile.Router.prototype,{
		add: function(userRoutes,userHandlers){
			if (!userRoutes) return;

			var _self=this, evtList=[], evtLookup={
				bc: "pagebeforecreate", c: "pagecreate",
				bs: "pagebeforeshow", s: "pageshow",
				bh: "pagebeforehide", h: "pagehide",
				i: "pageinit"
			};
			$.each(userRoutes,function(r,el){
				if(typeof(el)=="string" || typeof(el)=="function"){
					if (_self.routes.pagebeforeshow===null) _self.routes.pagebeforeshow={};
					_self.routes.pagebeforeshow[r]=el;
					if (! _self.routesRex.hasOwnProperty(r)){
						_self.routesRex[r]=new RegExp(r);
					}
				} else {
					var i,trig=el.events.split(","),evt;
					for(i in trig){
						evt=evtLookup[trig[i]];
						if (_self.routes.hasOwnProperty(evt)){
							if (_self.routes[evt]===null) _self.routes[evt]={};
							_self.routes[evt][r]=el.handler;
							if (! _self.routesRex.hasOwnProperty(r)){
								_self.routesRex[r]=new RegExp(r);
							}
						} else {
							debug("can't set unsupported route "+trig[i]);
						}
					}
				}
			});
			$.each(_self.routes,function(evt,el){
				if (el!==null){
					evtList.push(evt);
				}
			});
			if (!this.userHandlers) this.userHandlers={};
			$.extend(this.userHandlers,userHandlers||{});
			this._detachEvents();
			if (evtList.length>0){
				this._liveData={
					events: evtList.join(" "),
					handler: function(e,ui){ _self._processRoutes(e,ui,this); }
				};
				$("div:jqmData(role='page'),div:jqmData(role='dialog')").live(
					this._liveData.events, this._liveData.handler
				);
			}
		},

		_processRoutes: function(e,ui,page){
			var _self=this, refUrl, url;
			if (e.type in {
				"pagebeforehide":true, "pagehide":true
			}){
				refUrl=previousUrl;
			} else {
				refUrl=nextUrl;
			}
			if (!refUrl && page){
				$page=$(page);
				refUrl=$page.jqmData("url");
				if (refUrl){
					if ($page.attr("id")==refUrl) refUrl="#"+refUrl;
					refUrl=$.mobile.path.parseUrl(refUrl);
				} else {
					refUrl=window.location;
				}
			}
			if (!refUrl) return;
			url=( !this.conf.ajaxApp ?
				refUrl.hash
				:refUrl.pathname + refUrl.search + refUrl.hash
			);
			$.each(this.routes[e.type],function(route,handler){
				var res, handleFn;
				if ( (res=url.match(_self.routesRex[route])) ){
					if (typeof(handler)=="function"){
						handleFn=handler;
					} else if (typeof(_self.userHandlers[handler])=="function"){
						handleFn=_self.userHandlers[handler];
					}
					if (handleFn){
						try { handleFn(e.type,res,ui,page);
						}catch(err){ debug(err); }
					}
				}
			});
		},

		_detachEvents: function(){
			if (this._liveData){
				$("div:jqmData(role='page'),div:jqmData(role='dialog')").die(
					this._liveData.events, this._liveData.handler
				);
			}
		} ,

		destroy: function(){
			this._detachEvents();
			this.routes=this.routesRex=null;
		} ,

		getParams: function(hashparams){
			if (!hashparams) return null;
			var params={}, tmp;
			var tokens=hashparams.slice( hashparams.indexOf('?')+1 ).split("&");
			$.each(tokens,function(k,v){
				tmp=v.split("=");
				params[tmp[0]]=tmp[1];
			});
			if ($.isEmptyObject(params)) return null;
			return params;
		}
	});

});

})(jQuery);
<commit_msg>Fixed the version number<commit_after>/* jQueryMobile-router v0.4
 * Copyright 2011, Andrea Zicchetti
 */
(function($){

$(document).bind("mobileinit",function(){

	/* supports the following configurations:
		$.mobile.jqmRouter.fixFirstPageDataUrl=true
		$.mobile.jqmRouter.firstPageDataUrl="index.html"
			jQM doesn't handle correctly the dataurl of the first page you display
			in a single-page template mode. In fact, the page is fetched again
			from the server the first time you try to access it through a link.
			If this option is set to true, jquery mobile router extensions will
			try to fix this problem. In order to set the data url, you have to
			provide the name of the file containing the first page into the
			"firstPageDataUrl" property (for example: index.html)

	*/

	var config=$.extend({
		fixFirstPageDataUrl: false, firstPageDataUrl: "index.html"
	},$.mobile.jqmRouter || {});

	var DEBUG=true;
	function debug(err){
		if (DEBUG) console.log(err);
	}

	var previousUrl=null, nextUrl=null;

	$(document).bind("pagebeforechange", function( e, data ) {
		// We only want to handle changePage() calls where the caller is
		// asking us to load a page by URL.
		if ( typeof data.toPage === "string" ) {
			// We are being asked to load a page by URL, but we only
			// want to handle URLs that request the data for a specific
			// category.
			var u = $.mobile.path.parseUrl( data.toPage );
			previousUrl=nextUrl;
			nextUrl=u;

			if ( u.hash.indexOf("?") !== -1 ) {
				var page=u.hash.replace( /\?.*$/, "" );
				// We don't want the data-url of the page we just modified
				// to be the url that shows up in the browser's location field,
				// so set the dataUrl option to the URL for the category
				// we just loaded.
				data.options.dataUrl = u.href;
				// Now call changePage() and tell it to switch to
				// the page we just modified, but only in case it's different
				// from the current page
				if (	$.mobile.activePage &&
					page.replace(/^#/,"")==$.mobile.activePage.jqmData("url")
				){
					var ui={ prevPage: $.mobile.activePage };
					$.mobile.activePage
						.trigger("pagebeforeshow",[ui])
						.trigger("pageshow",[ui])
					;
				} else {
					$.mobile.changePage( $(page), data.options );
				}
				// Make sure to tell changePage() we've handled this call so it doesn't
				// have to do anything.
				e.preventDefault();
			}
		}
	});

	if (config.fixFirstPageDataUrl){
		$(document).ready(function(){
			var page=$(":jqmData(role='page')").first();
			var	dataUrl=page.jqmData("url"),
				guessedDataUrl=
					window.location.pathname.slice(-1)=="/"?
						window.location.pathname
						+config.firstPageDataUrl
						:window.location.pathname
			;
			if (dataUrl!=guessedDataUrl){
				page.attr("data-url",guessedDataUrl)
					.jqmData("url",guessedDataUrl);
			}
		});
	}

	$.mobile.Router=function(userRoutes,userHandlers,conf){
		/* userRoutes format:
			{
				"regexp": "function name", // defaults to jqm pagebeforeshow event
				"regexp": function(){ ... }, // defaults to jqm pagebeforeshow event
				"regexp": { handler: "function name", events: "bc,c,bs,s,bh,h"	},
				"regexp": { handler: function(){ ... }, events: "bc,c,bs,s,bh,h" }
			}
		*/
		this.routes={
			pagebeforecreate: null, pagecreate: null,
			pagebeforeshow: null, pageshow: null,
			pagebeforehide: null, pagehide: null,
			pageinit: null
		};
		this.routesRex={};
		this.conf=$.extend({
			ajaxApp: false
		}, config || {});
		this.add(userRoutes,userHandlers);
	}
	$.extend($.mobile.Router.prototype,{
		add: function(userRoutes,userHandlers){
			if (!userRoutes) return;

			var _self=this, evtList=[], evtLookup={
				bc: "pagebeforecreate", c: "pagecreate",
				bs: "pagebeforeshow", s: "pageshow",
				bh: "pagebeforehide", h: "pagehide",
				i: "pageinit"
			};
			$.each(userRoutes,function(r,el){
				if(typeof(el)=="string" || typeof(el)=="function"){
					if (_self.routes.pagebeforeshow===null) _self.routes.pagebeforeshow={};
					_self.routes.pagebeforeshow[r]=el;
					if (! _self.routesRex.hasOwnProperty(r)){
						_self.routesRex[r]=new RegExp(r);
					}
				} else {
					var i,trig=el.events.split(","),evt;
					for(i in trig){
						evt=evtLookup[trig[i]];
						if (_self.routes.hasOwnProperty(evt)){
							if (_self.routes[evt]===null) _self.routes[evt]={};
							_self.routes[evt][r]=el.handler;
							if (! _self.routesRex.hasOwnProperty(r)){
								_self.routesRex[r]=new RegExp(r);
							}
						} else {
							debug("can't set unsupported route "+trig[i]);
						}
					}
				}
			});
			$.each(_self.routes,function(evt,el){
				if (el!==null){
					evtList.push(evt);
				}
			});
			if (!this.userHandlers) this.userHandlers={};
			$.extend(this.userHandlers,userHandlers||{});
			this._detachEvents();
			if (evtList.length>0){
				this._liveData={
					events: evtList.join(" "),
					handler: function(e,ui){ _self._processRoutes(e,ui,this); }
				};
				$("div:jqmData(role='page'),div:jqmData(role='dialog')").live(
					this._liveData.events, this._liveData.handler
				);
			}
		},

		_processRoutes: function(e,ui,page){
			var _self=this, refUrl, url;
			if (e.type in {
				"pagebeforehide":true, "pagehide":true
			}){
				refUrl=previousUrl;
			} else {
				refUrl=nextUrl;
			}
			if (!refUrl && page){
				$page=$(page);
				refUrl=$page.jqmData("url");
				if (refUrl){
					if ($page.attr("id")==refUrl) refUrl="#"+refUrl;
					refUrl=$.mobile.path.parseUrl(refUrl);
				} else {
					refUrl=window.location;
				}
			}
			if (!refUrl) return;
			url=( !this.conf.ajaxApp ?
				refUrl.hash
				:refUrl.pathname + refUrl.search + refUrl.hash
			);
			$.each(this.routes[e.type],function(route,handler){
				var res, handleFn;
				if ( (res=url.match(_self.routesRex[route])) ){
					if (typeof(handler)=="function"){
						handleFn=handler;
					} else if (typeof(_self.userHandlers[handler])=="function"){
						handleFn=_self.userHandlers[handler];
					}
					if (handleFn){
						try { handleFn(e.type,res,ui,page);
						}catch(err){ debug(err); }
					}
				}
			});
		},

		_detachEvents: function(){
			if (this._liveData){
				$("div:jqmData(role='page'),div:jqmData(role='dialog')").die(
					this._liveData.events, this._liveData.handler
				);
			}
		} ,

		destroy: function(){
			this._detachEvents();
			this.routes=this.routesRex=null;
		} ,

		getParams: function(hashparams){
			if (!hashparams) return null;
			var params={}, tmp;
			var tokens=hashparams.slice( hashparams.indexOf('?')+1 ).split("&");
			$.each(tokens,function(k,v){
				tmp=v.split("=");
				params[tmp[0]]=tmp[1];
			});
			if ($.isEmptyObject(params)) return null;
			return params;
		}
	});

});

})(jQuery);
<|endoftext|>


<commit_before>'use strict';

// Main application
angular.module('MatchCalendarApp', ['truncate', 'ui.bootstrap', 'LocalForageModule', 'monospaced.elastic', 'ngSanitize', 'ui.router', 'ngClipboard', 'vr.directives.slider', 'ngAnimate', 'xeditable', 'pasvaz.bindonce'])

    .run(function($rootScope, $localForage, editableOptions, $q, $window, $modal,
        // eager load some services that we want to run
        Posts, PostNotifications, DateTimeService // jshint ignore:line
        ){
        editableOptions.theme = 'bs3';

        //set up a new scope for the global settings to use
        $rootScope.settings = $rootScope.$new(true);

        $rootScope.showChangelog = function() {
            $modal.open({
                template: '

Changelog

<markdown class="md" content="markdown"></markdown>
',
                controller: function($scope, $http) {
                    $scope.markdown = '';

                    $http.get('/changelog.md').success(function(data) {
                        $scope.markdown = data;
                    }).error(function() {
                        $scope.markdown = 'Error loading changelog data';
                    });
                }
            });
        };

        //check appcache status
        if(angular.isDefined($window.applicationCache)) {

            var onUpdateReady = function() {
                $modal.open({
                    template: '

An update is ready, reload?

<button class="btn btn-warning" type="button" ng-click="reload()">Reload Now</button><button class="btn btn-info" type="button" ng-click="showChangelog()">Changelog</button>
',
                    controller: function($scope, $window) {
                        $scope.reload = function() {
                            $window.location.reload();
                        };
                    }
                });
            };

            $window.applicationCache.addEventListener('updateready', onUpdateReady);
            if ($window.applicationCache.status === $window.applicationCache.UPDATEREADY) {
                onUpdateReady();
            }
        }
    })

    //configuration
    .config(['$stateProvider', '$urlRouterProvider', '$localForageProvider', function($stateProvider, $urlRouterProvider, $localForageProvider) {
        $localForageProvider.config({
            name: 'MatchCalendar'
        });

        $stateProvider
            .state('list', {
                url: '/list?post',
                templateUrl: 'components/PostList/list.html',
                controller: 'PostListCtrl'
            })

            .state('listhelp', {
                url: '/list/help',
                templateUrl: 'components/PostList/listhelp.html',
                controller: 'PostListHelpCtrl'
            })

            .state('generate', {
                url: '/generate',
                templateUrl: 'components/Generator/generator.html',
                controller: 'PostGeneratorCtrl'
            })

            .state('settings', {
                url: '/settings',
                templateUrl: 'components/Settings/settings.html',
                controller: 'SettingsCtrl'
            })

            .state('editor', {
                url: '/editor',
                templateUrl: 'components/TemplateEditor/TemplateEditor.html',
                controller: 'TemplateEditorCtrl'
            })

            .state('about', {
                url: '/about',
                templateUrl: 'components/About/about.html',
                controller: 'AboutCtrl'
            });

        $urlRouterProvider.otherwise('/list');
    }]);
<commit_msg>fix(app): remove now unused settings scope within the $rootScope<commit_after>'use strict';

// Main application
angular.module('MatchCalendarApp', ['truncate', 'ui.bootstrap', 'LocalForageModule', 'monospaced.elastic', 'ngSanitize', 'ui.router', 'ngClipboard', 'vr.directives.slider', 'ngAnimate', 'xeditable', 'pasvaz.bindonce'])

    .run(function($rootScope, $localForage, editableOptions, $q, $window, $modal,
        // eager load some services that we want to run
        Posts, PostNotifications, DateTimeService // jshint ignore:line
        ){
        editableOptions.theme = 'bs3';

        $rootScope.showChangelog = function() {
            $modal.open({
                template: '

Changelog

<markdown class="md" content="markdown"></markdown>
',
                controller: function($scope, $http) {
                    $scope.markdown = '';

                    $http.get('/changelog.md').success(function(data) {
                        $scope.markdown = data;
                    }).error(function() {
                        $scope.markdown = 'Error loading changelog data';
                    });
                }
            });
        };

        //check appcache status
        if(angular.isDefined($window.applicationCache)) {

            var onUpdateReady = function() {
                $modal.open({
                    template: '

An update is ready, reload?

<button class="btn btn-warning" type="button" ng-click="reload()">Reload Now</button><button class="btn btn-info" type="button" ng-click="showChangelog()">Changelog</button>
',
                    controller: function($scope, $window) {
                        $scope.reload = function() {
                            $window.location.reload();
                        };
                    }
                });
            };

            $window.applicationCache.addEventListener('updateready', onUpdateReady);
            if ($window.applicationCache.status === $window.applicationCache.UPDATEREADY) {
                onUpdateReady();
            }
        }
    })

    //configuration
    .config(['$stateProvider', '$urlRouterProvider', '$localForageProvider', function($stateProvider, $urlRouterProvider, $localForageProvider) {
        $localForageProvider.config({
            name: 'MatchCalendar'
        });

        $stateProvider
            .state('list', {
                url: '/list?post',
                templateUrl: 'components/PostList/list.html',
                controller: 'PostListCtrl'
            })

            .state('listhelp', {
                url: '/list/help',
                templateUrl: 'components/PostList/listhelp.html',
                controller: 'PostListHelpCtrl'
            })

            .state('generate', {
                url: '/generate',
                templateUrl: 'components/Generator/generator.html',
                controller: 'PostGeneratorCtrl'
            })

            .state('settings', {
                url: '/settings',
                templateUrl: 'components/Settings/settings.html',
                controller: 'SettingsCtrl'
            })

            .state('editor', {
                url: '/editor',
                templateUrl: 'components/TemplateEditor/TemplateEditor.html',
                controller: 'TemplateEditorCtrl'
            })

            .state('about', {
                url: '/about',
                templateUrl: 'components/About/about.html',
                controller: 'AboutCtrl'
            });

        $urlRouterProvider.otherwise('/list');
    }]);
<|endoftext|>