<commit_before>
angular.module('os.administrative.institute',
  [
    'ui.router',
    'os.administrative.institute.list',
    'os.administrative.institute.addedit',
    'os.administrative.institute.detail'
  ])

  .config(function($stateProvider) {
    $stateProvider
      .state('institute-list', {
        url: '/institutes',
        templateUrl: 'modules/administrative/institute/list.html',
        controller: 'InstituteListCtrl',
        parent: 'signed-in'
      })
      .state('institute-addedit', {
        url: '/institute-addedit/:instituteId',
        templateUrl: 'modules/administrative/institute/addedit.html',
        resolve: {
          institute: function($stateParams, Institute) {
            if ($stateParams.instituteId) {
              return Institute.getById($stateParams.instituteId);
            }
            return new Institute();
          }
        },
        controller: 'InstituteAddEditCtrl',
        parent: 'signed-in'
      })
      .state('institute-import', {
        url: '/institutes-import',
        templateUrl: 'modules/common/import/add.html',
        controller: 'ImportObjectCtrl',
        resolve: {
          importDetail: function() {
            return {
              breadcrumbs: [{state: 'institute-list', title: 'institutes.list'}],
              objectType: 'institute',
              title: 'institutes.bulk_import',
              onSuccess: {state: 'institute-list'}
            };
          }
        },
        parent: 'signed-in'
      })
      .state('institute-import-jobs', {
        url: '/institutes-import-jobs',
        templateUrl: 'modules/common/import/list.html',
        controller: 'ImportJobsListCtrl',
        resolve: {
          importDetail: function() {
            return {
              breadcrumbs: [{state: 'institute-list', title: 'institutes.list'}],
              title: 'institutes.bulk_import_jobs',
              objectTypes: ['institute']
            }
          }
        },
        parent: 'signed-in'
      })
      .state('institute-detail', {
        url: '/institutes/:instituteId',
        templateUrl: 'modules/administrative/institute/detail.html',
        resolve: {
          institute: function($stateParams, Institute) {
            return Institute.getById($stateParams.instituteId);
          }
        },
        controller: 'InstituteDetailCtrl',
        parent: 'signed-in'
      })
      .state('institute-detail.overview', {
        url: '/overview',
        templateUrl: 'modules/administrative/institute/overview.html',
        controller: function() {
        },
        parent: 'institute-detail'
      })
  });
<commit_msg>OPSMN-3791 Fixed broken i18n messages due to key changes. (Got broken while fix OPSMN-3723)<commit_after>
angular.module('os.administrative.institute',
  [
    'ui.router',
    'os.administrative.institute.list',
    'os.administrative.institute.addedit',
    'os.administrative.institute.detail'
  ])

  .config(function($stateProvider) {
    $stateProvider
      .state('institute-list', {
        url: '/institutes',
        templateUrl: 'modules/administrative/institute/list.html',
        controller: 'InstituteListCtrl',
        parent: 'signed-in'
      })
      .state('institute-addedit', {
        url: '/institute-addedit/:instituteId',
        templateUrl: 'modules/administrative/institute/addedit.html',
        resolve: {
          institute: function($stateParams, Institute) {
            if ($stateParams.instituteId) {
              return Institute.getById($stateParams.instituteId);
            }
            return new Institute();
          }
        },
        controller: 'InstituteAddEditCtrl',
        parent: 'signed-in'
      })
      .state('institute-import', {
        url: '/institutes-import',
        templateUrl: 'modules/common/import/add.html',
        controller: 'ImportObjectCtrl',
        resolve: {
          importDetail: function() {
            return {
              breadcrumbs: [{state: 'institute-list', title: 'institute.list'}],
              objectType: 'institute',
              title: 'institute.bulk_import',
              onSuccess: {state: 'institute-list'}
            };
          }
        },
        parent: 'signed-in'
      })
      .state('institute-import-jobs', {
        url: '/institutes-import-jobs',
        templateUrl: 'modules/common/import/list.html',
        controller: 'ImportJobsListCtrl',
        resolve: {
          importDetail: function() {
            return {
              breadcrumbs: [{state: 'institute-list', title: 'institute.list'}],
              title: 'institute.bulk_import_jobs',
              objectTypes: ['institute']
            }
          }
        },
        parent: 'signed-in'
      })
      .state('institute-detail', {
        url: '/institutes/:instituteId',
        templateUrl: 'modules/administrative/institute/detail.html',
        resolve: {
          institute: function($stateParams, Institute) {
            return Institute.getById($stateParams.instituteId);
          }
        },
        controller: 'InstituteDetailCtrl',
        parent: 'signed-in'
      })
      .state('institute-detail.overview', {
        url: '/overview',
        templateUrl: 'modules/administrative/institute/overview.html',
        controller: function() {
        },
        parent: 'institute-detail'
      })
  });
<|endoftext|>


<commit_before>//$('#side-menu').metisMenu();

//Loads the correct sidebar on window load,
//collapses the sidebar on window resize.
// Sets the min-height of #page-wrapper to window size
$(window).bind("load resize", function() {
  topOffset = 71;
  width = (this.window.innerWidth > 0) ? this.window.innerWidth : this.screen.width;
  if (width < 768) {
    $('div.navbar-collapse').addClass('collapse')
    topOffset = 100; // 2-row-menu
  } else {
    $('div.navbar-collapse').removeClass('collapse')
  }

  height = (this.window.innerHeight > 0) ? this.window.innerHeight : this.screen.height;
  height = height - topOffset;
  if (height < 1) height = 1;
  if (height > topOffset) {
    $("#page-wrapper").css("min-height", (height) + "px");
  }
});

var lys = {};

lys.fa_icon = function(e) {
  switch(e.msg.build.status) {
    case 'success':   return {icon: 'check',    color: 'green'};
    case 'failed':    return {icon: 'warning',  color: 'firebrick'};
    case 'scheduled': return {icon: 'calendar', color: ''};
    case 'working':   return {icon: 'gear',     color: ''};
    default:          return {icon: 'gear',     color: ''};
  }
};

lys.handleEvent = function(e) {
  switch(e.msg.type) {
    case 'build_create':
      console.log('adding build');
      var elems = document.getElementsByClassName('lys-builds');
      for(i = 0; i < elems.length; i++) {
        if(elems[i].classList.contains('list-group')) {
          var new_item = elems[i].insertBefore(document.createElement('a'), elems[i].childNodes[0]);
          new_item.className = 'list-group-item';
          new_item.setAttribute('href', '/repo/' + e.msg.repo + '/builds/' + e.msg.build.number);
          new_item.innerText = ' ' + e.msg.repo + ' ';
          var icon = new_item.insertBefore(document.createElement('i'), new_item.childNodes[0]);
          icon.className = 'fa fa-' + lys.fa_icon(e).icon + ' fa-fw';
          icon.style.color = lys.fa_icon(e).color;
          var number = new_item.appendChild(document.createElement('b'));
          number.className = 'pull-left';
          number.innerText = '#' + e.msg.build.number;
          var date = new_item.appendChild(document.createElement('span'));
          date.className = 'pull-right text-muted small';
          date.innerHTML = '' + e.msg.build.date + '';
        }
      }
      break;
    case 'build_update':
      console.log('updating build');
      var elems = document.getElementsByClassName('lys-builds');
      for(i = 0; i < elems.length; i++) {
        if(elems[i].classList.contains('list-group')) {
          for(ii = 0; ii < elems[i].childNodes.length; ii++) {
            if(elems[i].childNodes[ii].getAttribute === undefined) {
              continue;
            }
            if(elems[i].childNodes[ii].getAttribute('href') === ('/repo/' + e.msg.repo + '/builds/' + e.msg.build.number)) {
              elems[i].childNodes[ii].childNodes[0].className = 'fa fa-' + lys.fa_icon(e).icon + ' fa-fw';
              elems[i].childNodes[ii].childNodes[0].style.color = lys.fa_icon(e).color;
              elems[i].childNodes[ii].childNodes[3].innerHTML = '' + e.msg.build.date ? e.msg.build.date : '' + '';
            }
          }
        }
      }
      break;
  }
};

lys.handle = function(data) {
  if(!this.initialized) {
    console.log('remote ver.', data.ver);
    this.initialized = true;
  } else {
    switch(data.type) {
      case 'error':     console.log('error:', data.err, data.msg); break;
      case 'success':   console.log('success:', data.msg); break;
      case 'msg':       lys.handleEvent(data); break;
      case 'keepalive': console.log('keepalive'); break;
      default:          console.log('unknown msg type', data.type);
    }
  }
};

lys.setupWs = function() {
  lys.ws           = new WebSocket('ws' + (window.location.protocol == 'https:' ? 's' : '') + '://' + window.location.host + '/realtime');
  lys.ws.onopen    = function()  {
    console.log('websocket opened');
    if(document.getElementsByClassName('lys-builds').length > 0) {
      lys.ws.send('sub builds');
    }
  };
  lys.ws.onclose   = function()  { console.log('websocket closed, reconnecting in 3s'); setTimeout(lys.setupWs, 3000); };
  lys.ws.onmessage = function(m) { lys.handle(JSON.parse(m.data)); };
};

window.addEventListener('load', function() {
  lys.setupWs();
});<commit_msg>Uninitialize on drop<commit_after>//$('#side-menu').metisMenu();

//Loads the correct sidebar on window load,
//collapses the sidebar on window resize.
// Sets the min-height of #page-wrapper to window size
$(window).bind("load resize", function() {
  topOffset = 71;
  width = (this.window.innerWidth > 0) ? this.window.innerWidth : this.screen.width;
  if (width < 768) {
    $('div.navbar-collapse').addClass('collapse')
    topOffset = 100; // 2-row-menu
  } else {
    $('div.navbar-collapse').removeClass('collapse')
  }

  height = (this.window.innerHeight > 0) ? this.window.innerHeight : this.screen.height;
  height = height - topOffset;
  if (height < 1) height = 1;
  if (height > topOffset) {
    $("#page-wrapper").css("min-height", (height) + "px");
  }
});

var lys = {};

lys.fa_icon = function(e) {
  switch(e.msg.build.status) {
    case 'success':   return {icon: 'check',    color: 'green'};
    case 'failed':    return {icon: 'warning',  color: 'firebrick'};
    case 'scheduled': return {icon: 'calendar', color: ''};
    case 'working':   return {icon: 'gear',     color: ''};
    default:          return {icon: 'gear',     color: ''};
  }
};

lys.handleEvent = function(e) {
  switch(e.msg.type) {
    case 'build_create':
      console.log('adding build');
      var elems = document.getElementsByClassName('lys-builds');
      for(i = 0; i < elems.length; i++) {
        if(elems[i].classList.contains('list-group')) {
          var new_item = elems[i].insertBefore(document.createElement('a'), elems[i].childNodes[0]);
          new_item.className = 'list-group-item';
          new_item.setAttribute('href', '/repo/' + e.msg.repo + '/builds/' + e.msg.build.number);
          new_item.innerText = ' ' + e.msg.repo + ' ';
          var icon = new_item.insertBefore(document.createElement('i'), new_item.childNodes[0]);
          icon.className = 'fa fa-' + lys.fa_icon(e).icon + ' fa-fw';
          icon.style.color = lys.fa_icon(e).color;
          var number = new_item.appendChild(document.createElement('b'));
          number.className = 'pull-left';
          number.innerText = '#' + e.msg.build.number;
          var date = new_item.appendChild(document.createElement('span'));
          date.className = 'pull-right text-muted small';
          date.innerHTML = '' + e.msg.build.date + '';
        }
      }
      break;
    case 'build_update':
      console.log('updating build');
      var elems = document.getElementsByClassName('lys-builds');
      for(i = 0; i < elems.length; i++) {
        if(elems[i].classList.contains('list-group')) {
          for(ii = 0; ii < elems[i].childNodes.length; ii++) {
            if(elems[i].childNodes[ii].getAttribute === undefined) {
              continue;
            }
            if(elems[i].childNodes[ii].getAttribute('href') === ('/repo/' + e.msg.repo + '/builds/' + e.msg.build.number)) {
              elems[i].childNodes[ii].childNodes[0].className = 'fa fa-' + lys.fa_icon(e).icon + ' fa-fw';
              elems[i].childNodes[ii].childNodes[0].style.color = lys.fa_icon(e).color;
              elems[i].childNodes[ii].childNodes[3].innerHTML = '' + e.msg.build.date ? e.msg.build.date : '' + '';
            }
          }
        }
      }
      break;
  }
};

lys.handle = function(data) {
  if(!this.initialized) {
    console.log('remote ver.', data.ver);
    this.initialized = true;
  } else {
    switch(data.type) {
      case 'error':     console.log('error:', data.err, data.msg); break;
      case 'success':   console.log('success:', data.msg); break;
      case 'msg':       lys.handleEvent(data); break;
      case 'keepalive': console.log('keepalive'); break;
      default:          console.log('unknown msg type', data.type);
    }
  }
};

lys.setupWs = function() {
  lys.ws           = new WebSocket('ws' + (window.location.protocol == 'https:' ? 's' : '') + '://' + window.location.host + '/realtime');
  lys.ws.onopen    = function()  {
    console.log('websocket opened');
    if(document.getElementsByClassName('lys-builds').length > 0) {
      lys.ws.send('sub builds');
    }
  };
  lys.ws.onclose   = function()  { console.log('websocket closed, reconnecting in 3s'); lys.initialized = false; setTimeout(lys.setupWs, 3000); };
  lys.ws.onmessage = function(m) { lys.handle(JSON.parse(m.data)); };
};

window.addEventListener('load', function() {
  lys.setupWs();
});<|endoftext|>


<commit_before>import { registerFragment } from 'meteor/vulcan:core';

registerFragment(`
  fragment UsersAdmin on User {
    _id
    username
    createdAt
    isAdmin
    displayName
    email
    slug
    groups
    services

    karma
  }
`);

registerFragment(`
  fragment conversationsListFragment on Conversation {
    _id
    title
    createdAt
    latestActivity
    participantIds
    participants {
      ...UsersMinimumInfo
    }
    archivedByIds
    messageCount
  }
`);

registerFragment(`
  fragment newConversationFragment on Conversation {
    _id
    title
    participantIds
  }
`);

registerFragment(`
  fragment messageListFragment on Message {
    _id
    user {
      ...UsersMinimumInfo
    }
    contents {
      html
    }
    createdAt
    conversationId
  }
`);

registerFragment(`
  fragment editTitle on Conversation {
    _id
    title
  }
`);

registerFragment(`
  fragment NotificationsList on Notification {
    _id
    userId
    createdAt
    link
    message
    type
    viewed
  }
`);

registerFragment(`
  fragment UsersCurrent on User {
    ...UsersMinimumInfo

    _id
    username
    createdAt
    isAdmin
    displayName
    email
    slug
    groups
    services
    pageUrl
    locale
    defaultToCKEditor
    voteBanned
    banned
    isReviewed
    nullifyVotes
    hideIntercom
    hideNavigationSidebar
    currentFrontpageFilter
    allPostsTimeframe
    allPostsSorting
    allPostsFilter
    allPostsShowLowKarma
    allPostsOpenSettings
    lastNotificationsCheck
    subscribedItems
    groups
    bannedUserIds
    moderationStyle
    moderationGuidelines {
      ...RevisionEdit
    }
    markDownPostEditor
    commentSorting
    location
    googleLocation
    mongoLocation
    mapLocation
    mapLocationSet
    mapMarkerText
    htmlMapMarkerText
    nearbyEventsNotifications
    nearbyEventsNotificationsLocation
    nearbyEventsNotificationsRadius
    nearbyPeopleNotificationThreshold
    hideFrontpageMap
    emailSubscribedToCurated
    unsubscribeFromAll
    emails
    whenConfirmationEmailSent
    noCollapseCommentsFrontpage
    noCollapseCommentsPosts
    noSingleLineComments
    karmaChangeNotifierSettings
    karmaChangeLastOpened
    shortformFeedId
    viewUnreviewedComments
    sunshineShowNewUserContent
    recommendationSettings
    // petrovPressedButtonDate
    // petrovCodesEnteredDate
    // petrovCodesEntered
  }
`);

registerFragment(`
  fragment UserKarmaChanges on User {
    _id
    karmaChanges {
      totalChange
      updateFrequency
      startDate
      endDate
      nextBatchDate
      posts {
        _id
        scoreChange
        title
        slug
      }
      comments {
        _id
        scoreChange
        description
        postId
      }
    }
  }
`);

registerFragment(`
  fragment RSSFeedMinimumInfo on RSSFeed {
    _id
    userId
    user {
      ...UsersMinimumInfo
    }
    createdAt
    ownedByUser
    displayFullContent
    nickname
    url
  }
`);

registerFragment(`
  fragment CommentStats on Comment {
    currentUserVotes{
      ...VoteFragment
    }
    baseScore
    score
  }
`);

registerFragment(`
  fragment DeletedCommentsMetaData on Comment {
    _id
    deleted
    deletedDate
    deletedByUser {
      _id
      displayName
    }
    deletedReason
    deletedPublic
  }
`)

registerFragment(`
  fragment DeletedCommentsModerationLog on Comment {
    ...DeletedCommentsMetaData
    user {
      ...UsersMinimumInfo
    }
    post {
      title
      slug
      _id
    }
  }
`)

registerFragment(`
  fragment UsersBannedFromUsersModerationLog on User {
    _id
    slug
    displayName
    bannedUserIds
  }
`)

registerFragment(`
  fragment SelectCommentsList on Comment {
    ...CommentsList
    post {
      title
      _id
      slug
    }
  }
`);

registerFragment(`
  fragment UsersList on User {
    ...UsersMinimumInfo
    karma
  }
`);

registerFragment(`
  fragment SunshineUsersList on User {
    ...UsersMinimumInfo
    karma
    bio
    htmlBio
    createdAt
    email
    commentCount
    postCount
    voteCount
    smallUpvoteCount
    bigUpvoteCount
    smallDownvoteCount
    bigDownvoteCount
    banned
    reviewedByUserId
    signUpReCaptchaRating
  }
`);

registerFragment(`
  fragment newRSSFeedFragment on RSSFeed {
    _id
    userId
    createdAt
    ownedByUser
    displayFullContent
    nickname
    url
    status
  }
`);

registerFragment(`
  fragment RSSFeedMutationFragment on RSSFeed {
    _id
    userId
    ownedByUser
    displayFullContent
    nickname
    url
  }
`);

registerFragment(`
  fragment newEventFragment on LWEvent {
    _id
    createdAt
    userId
    name
    important
    properties
    intercom
  }
`);

registerFragment(`
  fragment lastEventFragment on LWEvent {
    _id
    createdAt
    documentId
    userId
    name
    important
    properties
    intercom
  }
`);

registerFragment(`
  fragment commentWithContextFragment on Comment {
    # example-forum
    _id
    parentCommentId
    topLevelCommentId
    contents {
      ...RevisionDisplay
    }
    postedAt
    # vulcan:users
    userId
    user {
      ...UsersMinimumInfo
    }
    # example-forum
    # vulcan:voting
    currentUserVotes{
      ...VoteFragment
    }
    baseScore
    score
  }
`);

registerFragment(`
  fragment commentInlineFragment on Comment {
    # example-forum
    _id
    contents {
      ...RevisionDisplay
    }
    # vulcan:users
    userId
    user {
      ...UsersMinimumInfo
    }
  }
`);

registerFragment(`
  fragment UsersMinimumInfo on User {
    # vulcan:users
    _id
    slug
    oldSlugs
    createdAt
    username
    displayName
    fullName
    karma
    afKarma
    deleted
    groups
    htmlBio
    postCount
    commentCount
    sequenceCount
    afPostCount
    afCommentCount
    beta
    spamRiskScore
  }
`);

registerFragment(`
  fragment UsersProfile on User {
    # vulcan:users
    ...UsersMinimumInfo
    createdAt
    isAdmin
    bio
    htmlBio
    website
    groups
    # example-forum
    postCount
    afPostCount
    frontpagePostCount
    # example-forum
    commentCount
    sequenceCount
    afCommentCount
    sequenceCount
    afSequenceCount
    afSequenceDraftCount
    sequenceDraftCount
    moderationStyle
    moderationGuidelines {
      ...RevisionDisplay
    }
    bannedUserIds
    location
    googleLocation
    mapLocation
    mapLocationSet
    mapMarkerText
    htmlMapMarkerText
    mongoLocation
    shortformFeedId
    viewUnreviewedComments
    auto_subscribe_to_my_posts
    auto_subscribe_to_my_comments
    sunshineShowNewUserContent
    defaultToCKEditor
  }
`);

registerFragment(`
  fragment UsersMapEntry on User {
    # vulcan:users
    ...UsersMinimumInfo
    createdAt
    isAdmin
    groups
    # example-forum
    location
    googleLocation
    mapLocation
    mapLocationSet
    mapMarkerText
    htmlMapMarkerText
    mongoLocation
  }
`);

registerFragment(`
  fragment UsersEdit on User {
    ...UsersProfile
    # Moderation Guidelines editor information
    moderationGuidelines {
      ...RevisionEdit
    }

    # UI Settings
    markDownPostEditor
    hideIntercom
    commentSorting
    currentFrontpageFilter
    noCollapseCommentsPosts
    noCollapseCommentsFrontpage
    noSingleLineComments
    sunshineShowNewUserContent

    # Emails
    email
    whenConfirmationEmailSent
    emailSubscribedToCurated
    unsubscribeFromAll

    # Moderation
    moderatorAssistance
    collapseModerationGuidelines
    bannedUserIds
    bannedPersonalUserIds

    # Ban & Purge
    voteBanned
    nullifyVotes
    deleteContent
    banned

    # Name
    username
    displayName
    fullName

    # Location
    mongoLocation
    googleLocation
    location

    # Admin & Review
    reviewedByUserId

    # Alignment Forum
    reviewForAlignmentForumUserId
    groups
    afApplicationText
    afSubmittedApplication

    # Karma Settings
    karmaChangeLastOpened
    karmaChangeNotifierSettings

    recommendationSettings

    hideFrontpageMap
  }
`)

registerFragment(`
  fragment unclaimedReportsList on Report {
    _id
    userId
    user {
      _id
      displayName
      username
      slug
    }
    commentId
    comment {
      _id
      userId
      user {
        ...UsersMinimumInfo
      }
      baseScore
      contents {
        ...RevisionDisplay
      }
      postedAt
      deleted
      postId
      post {
        _id
        slug
        title
        isEvent
      }
    }
    postId
    post {
      _id
      slug
      title
      isEvent
      contents {
        ...RevisionDisplay
      }
    }
    closedAt
    createdAt
    claimedUserId
    claimedUser {
      _id
      displayName
      username
      slug
    }
    link
    description
    reportedAsSpam
    markedAsSpam
  }
`);

registerFragment(`
  fragment VoteMinimumInfo on Vote {
    _id
    voteType
  }
`);

registerFragment(`
  fragment VoteFragment on Vote {
    _id
    voteType
    power
  }
`);

registerFragment(`
  fragment WithVotePost on Post {
    __typename
    _id
    currentUserVotes{
      _id
      voteType
      power
    }
    baseScore
    score
    afBaseScore
    voteCount
  }
`);

registerFragment(`
  fragment WithVoteComment on Comment {
    __typename
    _id
    currentUserVotes{
      _id
      voteType
      power
    }
    baseScore
    score
    afBaseScore
    voteCount
  }
`);

//
// example-forum migrated fragments
//

// note: fragment used by default on the UsersProfile fragment
registerFragment(/* GraphQL */`
  fragment VotedItem on Vote {
    # vulcan:voting
    documentId
    power
    votedAt
  }
`);

registerFragment(`
  fragment RevisionDisplay on Revision {
    version
    updateType
    editedAt
    userId
    html
    wordCount
    htmlHighlight
    plaintextDescription
  }
`)

registerFragment(`
  fragment RevisionEdit on Revision {
    version
    updateType
    editedAt
    userId
    originalContents
    html
    markdown
    draftJS
    ckEditorMarkup
    wordCount
    htmlHighlight
    plaintextDescription
  }
`)
<commit_msg>Fix broken fragment that Ray left in<commit_after>import { registerFragment } from 'meteor/vulcan:core';

registerFragment(`
  fragment UsersAdmin on User {
    _id
    username
    createdAt
    isAdmin
    displayName
    email
    slug
    groups
    services

    karma
  }
`);

registerFragment(`
  fragment conversationsListFragment on Conversation {
    _id
    title
    createdAt
    latestActivity
    participantIds
    participants {
      ...UsersMinimumInfo
    }
    archivedByIds
    messageCount
  }
`);

registerFragment(`
  fragment newConversationFragment on Conversation {
    _id
    title
    participantIds
  }
`);

registerFragment(`
  fragment messageListFragment on Message {
    _id
    user {
      ...UsersMinimumInfo
    }
    contents {
      html
    }
    createdAt
    conversationId
  }
`);

registerFragment(`
  fragment editTitle on Conversation {
    _id
    title
  }
`);

registerFragment(`
  fragment NotificationsList on Notification {
    _id
    userId
    createdAt
    link
    message
    type
    viewed
  }
`);

registerFragment(`
  fragment UsersCurrent on User {
    ...UsersMinimumInfo

    _id
    username
    createdAt
    isAdmin
    displayName
    email
    slug
    groups
    services
    pageUrl
    locale
    defaultToCKEditor
    voteBanned
    banned
    isReviewed
    nullifyVotes
    hideIntercom
    hideNavigationSidebar
    currentFrontpageFilter
    allPostsTimeframe
    allPostsSorting
    allPostsFilter
    allPostsShowLowKarma
    allPostsOpenSettings
    lastNotificationsCheck
    subscribedItems
    groups
    bannedUserIds
    moderationStyle
    moderationGuidelines {
      ...RevisionEdit
    }
    markDownPostEditor
    commentSorting
    location
    googleLocation
    mongoLocation
    mapLocation
    mapLocationSet
    mapMarkerText
    htmlMapMarkerText
    nearbyEventsNotifications
    nearbyEventsNotificationsLocation
    nearbyEventsNotificationsRadius
    nearbyPeopleNotificationThreshold
    hideFrontpageMap
    emailSubscribedToCurated
    unsubscribeFromAll
    emails
    whenConfirmationEmailSent
    noCollapseCommentsFrontpage
    noCollapseCommentsPosts
    noSingleLineComments
    karmaChangeNotifierSettings
    karmaChangeLastOpened
    shortformFeedId
    viewUnreviewedComments
    sunshineShowNewUserContent
    recommendationSettings
  }
`);

registerFragment(`
  fragment UserKarmaChanges on User {
    _id
    karmaChanges {
      totalChange
      updateFrequency
      startDate
      endDate
      nextBatchDate
      posts {
        _id
        scoreChange
        title
        slug
      }
      comments {
        _id
        scoreChange
        description
        postId
      }
    }
  }
`);

registerFragment(`
  fragment RSSFeedMinimumInfo on RSSFeed {
    _id
    userId
    user {
      ...UsersMinimumInfo
    }
    createdAt
    ownedByUser
    displayFullContent
    nickname
    url
  }
`);

registerFragment(`
  fragment CommentStats on Comment {
    currentUserVotes{
      ...VoteFragment
    }
    baseScore
    score
  }
`);

registerFragment(`
  fragment DeletedCommentsMetaData on Comment {
    _id
    deleted
    deletedDate
    deletedByUser {
      _id
      displayName
    }
    deletedReason
    deletedPublic
  }
`)

registerFragment(`
  fragment DeletedCommentsModerationLog on Comment {
    ...DeletedCommentsMetaData
    user {
      ...UsersMinimumInfo
    }
    post {
      title
      slug
      _id
    }
  }
`)

registerFragment(`
  fragment UsersBannedFromUsersModerationLog on User {
    _id
    slug
    displayName
    bannedUserIds
  }
`)

registerFragment(`
  fragment SelectCommentsList on Comment {
    ...CommentsList
    post {
      title
      _id
      slug
    }
  }
`);

registerFragment(`
  fragment UsersList on User {
    ...UsersMinimumInfo
    karma
  }
`);

registerFragment(`
  fragment SunshineUsersList on User {
    ...UsersMinimumInfo
    karma
    bio
    htmlBio
    createdAt
    email
    commentCount
    postCount
    voteCount
    smallUpvoteCount
    bigUpvoteCount
    smallDownvoteCount
    bigDownvoteCount
    banned
    reviewedByUserId
    signUpReCaptchaRating
  }
`);

registerFragment(`
  fragment newRSSFeedFragment on RSSFeed {
    _id
    userId
    createdAt
    ownedByUser
    displayFullContent
    nickname
    url
    status
  }
`);

registerFragment(`
  fragment RSSFeedMutationFragment on RSSFeed {
    _id
    userId
    ownedByUser
    displayFullContent
    nickname
    url
  }
`);

registerFragment(`
  fragment newEventFragment on LWEvent {
    _id
    createdAt
    userId
    name
    important
    properties
    intercom
  }
`);

registerFragment(`
  fragment lastEventFragment on LWEvent {
    _id
    createdAt
    documentId
    userId
    name
    important
    properties
    intercom
  }
`);

registerFragment(`
  fragment commentWithContextFragment on Comment {
    # example-forum
    _id
    parentCommentId
    topLevelCommentId
    contents {
      ...RevisionDisplay
    }
    postedAt
    # vulcan:users
    userId
    user {
      ...UsersMinimumInfo
    }
    # example-forum
    # vulcan:voting
    currentUserVotes{
      ...VoteFragment
    }
    baseScore
    score
  }
`);

registerFragment(`
  fragment commentInlineFragment on Comment {
    # example-forum
    _id
    contents {
      ...RevisionDisplay
    }
    # vulcan:users
    userId
    user {
      ...UsersMinimumInfo
    }
  }
`);

registerFragment(`
  fragment UsersMinimumInfo on User {
    # vulcan:users
    _id
    slug
    oldSlugs
    createdAt
    username
    displayName
    fullName
    karma
    afKarma
    deleted
    groups
    htmlBio
    postCount
    commentCount
    sequenceCount
    afPostCount
    afCommentCount
    beta
    spamRiskScore
  }
`);

registerFragment(`
  fragment UsersProfile on User {
    # vulcan:users
    ...UsersMinimumInfo
    createdAt
    isAdmin
    bio
    htmlBio
    website
    groups
    # example-forum
    postCount
    afPostCount
    frontpagePostCount
    # example-forum
    commentCount
    sequenceCount
    afCommentCount
    sequenceCount
    afSequenceCount
    afSequenceDraftCount
    sequenceDraftCount
    moderationStyle
    moderationGuidelines {
      ...RevisionDisplay
    }
    bannedUserIds
    location
    googleLocation
    mapLocation
    mapLocationSet
    mapMarkerText
    htmlMapMarkerText
    mongoLocation
    shortformFeedId
    viewUnreviewedComments
    auto_subscribe_to_my_posts
    auto_subscribe_to_my_comments
    sunshineShowNewUserContent
    defaultToCKEditor
  }
`);

registerFragment(`
  fragment UsersMapEntry on User {
    # vulcan:users
    ...UsersMinimumInfo
    createdAt
    isAdmin
    groups
    # example-forum
    location
    googleLocation
    mapLocation
    mapLocationSet
    mapMarkerText
    htmlMapMarkerText
    mongoLocation
  }
`);

registerFragment(`
  fragment UsersEdit on User {
    ...UsersProfile
    # Moderation Guidelines editor information
    moderationGuidelines {
      ...RevisionEdit
    }

    # UI Settings
    markDownPostEditor
    hideIntercom
    commentSorting
    currentFrontpageFilter
    noCollapseCommentsPosts
    noCollapseCommentsFrontpage
    noSingleLineComments
    sunshineShowNewUserContent

    # Emails
    email
    whenConfirmationEmailSent
    emailSubscribedToCurated
    unsubscribeFromAll

    # Moderation
    moderatorAssistance
    collapseModerationGuidelines
    bannedUserIds
    bannedPersonalUserIds

    # Ban & Purge
    voteBanned
    nullifyVotes
    deleteContent
    banned

    # Name
    username
    displayName
    fullName

    # Location
    mongoLocation
    googleLocation
    location

    # Admin & Review
    reviewedByUserId

    # Alignment Forum
    reviewForAlignmentForumUserId
    groups
    afApplicationText
    afSubmittedApplication

    # Karma Settings
    karmaChangeLastOpened
    karmaChangeNotifierSettings

    recommendationSettings

    hideFrontpageMap
  }
`)

registerFragment(`
  fragment unclaimedReportsList on Report {
    _id
    userId
    user {
      _id
      displayName
      username
      slug
    }
    commentId
    comment {
      _id
      userId
      user {
        ...UsersMinimumInfo
      }
      baseScore
      contents {
        ...RevisionDisplay
      }
      postedAt
      deleted
      postId
      post {
        _id
        slug
        title
        isEvent
      }
    }
    postId
    post {
      _id
      slug
      title
      isEvent
      contents {
        ...RevisionDisplay
      }
    }
    closedAt
    createdAt
    claimedUserId
    claimedUser {
      _id
      displayName
      username
      slug
    }
    link
    description
    reportedAsSpam
    markedAsSpam
  }
`);

registerFragment(`
  fragment VoteMinimumInfo on Vote {
    _id
    voteType
  }
`);

registerFragment(`
  fragment VoteFragment on Vote {
    _id
    voteType
    power
  }
`);

registerFragment(`
  fragment WithVotePost on Post {
    __typename
    _id
    currentUserVotes{
      _id
      voteType
      power
    }
    baseScore
    score
    afBaseScore
    voteCount
  }
`);

registerFragment(`
  fragment WithVoteComment on Comment {
    __typename
    _id
    currentUserVotes{
      _id
      voteType
      power
    }
    baseScore
    score
    afBaseScore
    voteCount
  }
`);

//
// example-forum migrated fragments
//

// note: fragment used by default on the UsersProfile fragment
registerFragment(/* GraphQL */`
  fragment VotedItem on Vote {
    # vulcan:voting
    documentId
    power
    votedAt
  }
`);

registerFragment(`
  fragment RevisionDisplay on Revision {
    version
    updateType
    editedAt
    userId
    html
    wordCount
    htmlHighlight
    plaintextDescription
  }
`)

registerFragment(`
  fragment RevisionEdit on Revision {
    version
    updateType
    editedAt
    userId
    originalContents
    html
    markdown
    draftJS
    ckEditorMarkup
    wordCount
    htmlHighlight
    plaintextDescription
  }
`)
<|endoftext|>


<commit_before>F2.Apps["com_openf2_examples_javascript_chart"] = (function(){

	var app = function (appConfig, appContent, root) {
		this.symbol = "MSFT";
		this.appConfig = appConfig;
		this.appContent = appContent;
		this.ui = this.appConfig.ui;
		this.root = root;
		this.$root = $(root);
		this.$app = $("#f2-1year-chart", this.$root);
		//set configuration
		this.config();
	};

	app.prototype.config = function() {

		var defaults = {
			backgroundColor: '#fff',
			lineColor: '#6A8F8E',
			lineWidth: 1.5,
			gridColor: '#DDDDDD',
			gridAltColor: '#F7F7F7',
			fontColor: '#444444',
			fontFamily: 'Arial, sans-serif',
			fontSize: 12,
			lineHeight: 1.2,
			greenBar: '#2EA94F',
			redBar: '#DB411C'
		},
		styleImport = (this.appConfig.context && this.appConfig.context.style)?this.appConfig.context.style:{};

		/** for example purposes*/
		console.group('Chart app');
		console.info('The chart app (com_openf2_examples_javascript_chart) has configuration options which can be override by using Context. Set a "style" property in the AppConfig\'s Context property. The current AppConfig is on the next line.');
		console.info(this.appConfig);
		console.info('The chart\'s configuration parameters (defaults) are found in the following hash');
		console.info(defaults);
		console.groupEnd();

		this.CHT_CONTAINER = 'f2-1year-chart';
		this.CHART_STYLES = $.extend({},defaults,styleImport);
	};

	app.prototype.redraw = function(data) {
		this.hc = null;
		this.symbol = data.symbol;
		this.getData();
	};

	app.prototype.init = function() {

		this.getData();

		//setup container symbol change listener to draw new chart.
		F2.Events.on(F2.Constants.Events.CONTAINER_SYMBOL_CHANGE, $.proxy(function(symbolData){
				this.redraw(symbolData);
			},this)
		);
	};

	app.prototype.getData = function() {

		this.ui.showMask(this.$root,true);

		$.ajax({
			beforeSend:function () {
				this.ui.setTitle('Loading chart...');
			},
			data: {
				symbol: this.symbol,
				duration: 365  // Fixed to one year
			},
			url: 'http://dev.markitondemand.com/Api/Timeseries/jsonp',
			dataType: 'jsonp',
			context: this

		}).done(function(jqxhr,txtStatus){
			//Catch errors
			if ( !jqxhr.Data || jqxhr.Message ) {
				if ( typeof console == 'object' ) console.error('Error: ', jqxhr.Message);
				this._chartError(jqxhr);
				return;
			}
			this.HandleAPIData(jqxhr);

		}).fail(function(jqxhr,txtStatus){
			F2.log('Could not generate chart.', jqxhr);
			this._chartError(jqxhr);
		});
	};

	app.prototype._chartError = function(jqxhr) {
		F2.log("Price Chart Error", jqxhr);
		this.ui.setTitle("Chart Error");
		this.$app.html("
An error occurred loading price data for " +this.symbol+ ".
");
		this.ui.hideMask(this.$root);
		this.ui.updateHeight();
	};

	// Parses API data to provide HighCharts-ready data series for close values,
	// additionally deriving up/down month indicators.
	//
	app.prototype.HandleAPIData = function (json) {

		$(this.CHT_CONTAINER).empty();

		// Set up vars for first data series
		var apiDates = json.Data.SeriesDates,
			apiValues = json.Data.Series.close.values,
			closeSeriesData = [ ];

		// Translate API JSON into a HighCharts-format data series
		for ( var i = 0; i < apiDates.length; i++ ) {
			var dat = new Date(apiDates[i]);
			var dateIn = Date.UTC(dat.getFullYear(), dat.getMonth(), dat.getDate());
			var val = apiValues[i];
			closeSeriesData.push([dateIn,val]);
		}

		// Instantiate a new chart with base configuration options (everything but the data)
		var hcChartObj = new Highcharts.Chart(this.getBaselineOptions());
		hcChartObj.series[0].setData(closeSeriesData, true);  // Set close-values series data
		//hcChartObj.setTitle({ text: ('One-year price movement for ' + json.Data.Name).toUpperCase() });  // Set title
		hcChartObj.setTitle({ text:'' });

		this.ui.hideMask(this.$root);
		this.ui.setTitle("ONE-YEAR PRICE MOVEMENT FOR " + this.symbol);

		// No options setting is available for this, so force the price line to be rounded
		$('.highcharts-series path:first', this.root).attr('stroke-linejoin', 'round').attr('stroke-linecap', 'round');

		// Set up vars for up/down month data series
		var currentMonthName, currentJSDate, currentJSUTCDate, currentVal,
			upSeriesData = [ ],
			downSeriesData = [ ];
		var dataRanges = hcChartObj.yAxis[0].getExtremes();  // Will need to reset to this later
			minVal = dataRanges.min,  // Will set red/green indicators to this value
			apiValues = json.Data.Series.close.values,
			apiDates = json.Data.SeriesDates,
			firstMonthName = apiDates[0].substr(4, 3),  // First!
			prevMonthName = firstMonthName,
			prevJSDate = new Date(prevMonthName + ' 1, ' + apiDates[0].substr(-4)),
			prevJSUTCDate = Date.UTC(prevJSDate.getFullYear(), prevJSDate.getMonth(), prevJSDate.getDate()),
			prevVal = apiValues[0];

		// Now walk through all data points again (had to do it once before to get the ranges),
		// looking for month boundaries and deciding if the previous month ended up or down over
		// the preceding month's close
		for ( var i = 1; i < apiDates.length; i++ ) {
			currentMonthName = apiDates[i].substr(4, 3);
			if ( currentMonthName != prevMonthName ) {  // Into a new month in the data
				currentVal = apiValues[i - 1];  // Last close in the preceding month
				currentJSDate = new Date(currentMonthName + ' 1, ' + apiDates[i].substr(-4));
				currentJSUTCDate = Date.UTC(currentJSDate.getFullYear(), currentJSDate.getMonth(), currentJSDate.getDate());
				if ( prevMonthName != firstMonthName ) {  // Skip the first month, it's incomplete
					if ( currentVal >= prevVal ) {
						upSeriesData.push( [ prevJSUTCDate, minVal ], [ currentJSUTCDate, minVal ] );
						downSeriesData.push( [ currentJSUTCDate, null ] );
					}
					else {
						downSeriesData.push( [ prevJSUTCDate, minVal ], [ currentJSUTCDate, minVal ] );
						upSeriesData.push( [ currentJSUTCDate, null ] );
					}
				}
				prevVal = currentVal;
				prevMonthName = currentMonthName;
				prevJSUTCDate = currentJSUTCDate;
			}
		}
		// Add one last interval for the partial month-to-date
		currentVal = apiValues[i - 1];  // Last close value in the data
		currentJSDate = new Date(apiDates[i - 1]);
		currentJSUTCDate = Date.UTC(currentJSDate.getFullYear(), currentJSDate.getMonth(), currentJSDate.getDate());
		if ( currentVal >= prevVal ) upSeriesData.push( [ prevJSUTCDate, minVal ], [ currentJSUTCDate, minVal ] );
		else downSeriesData.push( [ prevJSUTCDate, minVal ], [ currentJSUTCDate, minVal ] );

		// Add the up month/down month data to the chart's series
        hcChartObj.series[1].setData(upSeriesData, false);
        hcChartObj.series[2].setData(downSeriesData, false);

        hcChartObj.yAxis[0].setExtremes(dataRanges.dataMin, dataRanges.dataMax, true, false);

		this.ui.updateHeight();
	};

	// Defines the HighCharts configuration options.
	//
	app.prototype.getBaselineOptions = function () {
		return {
			chart: {
				borderColor: 'rgba(255, 255, 255, 0.0)',
				borderRadius: 0,
				defaultSeriesType: 'line',
				renderTo: this.CHT_CONTAINER,
				spacingBottom: 25,
				spacingLeft: 1,
				spacingRight: 1,
				backgroundColor: this.CHART_STYLES.backgroundColor
			},
			credits: {
				enabled: false
			},
			legend: {
				enabled: false
			},
			plotOptions: {
				line: {
					animation: false,
					lineWidth: this.CHART_STYLES.lineWidth
				},
				series: {
					marker: {
						enabled: false
					},
					shadow: false,
					states: {
						hover: {
							enabled: false
						}
					}
				}
			},
			series: [{
				color: this.CHART_STYLES.lineColor,
				name: 'Close price'
			},
			{
				color: this.CHART_STYLES.greenBar,
				lineWidth: 6,
				name: 'Up months'
			},
			{
				color: this.CHART_STYLES.redBar,
				lineWidth: 6,
				name: 'Down months'
			}],
			title: {
				align: 'left',
				style: {
					color: '#666',
					fontFamily: this.CHART_STYLES.fontFamily,
					fontSize: 14,
					fontWeight: 'bold',
					lineHeight: this.CHART_STYLES.lineHeight
				}
			},
			tooltip: {
				borderRadius: 1,
				crosshairs: true,
				formatter: function () {
					if ( this.series.name == 'Close price' ) {
						return ''
							+ Highcharts.dateFormat('%b %e %Y', this.x)
							+ '
'
							+ this.series.name + ': ' + Highcharts.numberFormat(this.y, 2)
							+ '';
					}
					else return false;
				},
				style: {
					color: this.CHART_STYLES.fontColor,
					fontFamily: this.CHART_STYLES.fontFamily,
					fontSize: this.CHART_STYLES.fontSize,
					lineHeight: this.CHART_STYLES.lineHeight,
					padding: this.CHART_STYLES.fontSize
				}
			},
			xAxis: [{  // Bottom datetime axis (short intervals)
				dateTimeLabelFormats: {
					minute: '%l:%M%P',
					hour: '%l%P',
					day: '%a',
					day: '%b %e',
					week: '%b %e',
					month: '%b',
					year: '%Y'
				},
				gridLineDashStyle: 'shortdot',
				gridLineColor: this.CHART_STYLES.gridAltColor,
				gridLineWidth: 1,
				labels: {
					align: 'left',
					style: {
						color: this.CHART_STYLES.fontColor,
						fontFamily: this.CHART_STYLES.fontFamily,
						fontSize: this.CHART_STYLES.fontSize
					},
					x: (this.CHART_STYLES.fontSize / 2),
					y: (this.CHART_STYLES.fontSize * this.CHART_STYLES.lineHeight * 1.5)
				},
				lineColor: this.CHART_STYLES.gridColor,
				tickColor: this.CHART_STYLES.gridColor,
				tickInterval: (30 * 24 * 3600 * 1000),  // One month
				tickLength: (this.CHART_STYLES.fontSize * this.CHART_STYLES.lineHeight * 1.5),
				type: 'datetime'
			},{  // Top datetime axis (longer intervals)
				dateTimeLabelFormats: {
					day: '%a',  // Default
					week: '%a',
					month: '%b %Y',
					year: '%Y'
				},
				gridLineWidth: 1,
				gridLineColor: this.CHART_STYLES.gridColor,
				labels: {
					align: 'left',
					style: {
						color: this.CHART_STYLES.fontColor,
						fontFamily: this.CHART_STYLES.fontFamily,
						fontSize: this.CHART_STYLES.fontSize
					},
					x: (this.CHART_STYLES.fontSize / 2)
				},
				lineColor: this.CHART_STYLES.gridColor,
				linkedTo: 0,
				opposite: true,
				tickColor: this.CHART_STYLES.gridColor,
				tickInterval: (365 * 24 * 3600 * 1000),  // One year
				tickLength: (this.CHART_STYLES.fontSize * this.CHART_STYLES.lineHeight),
				type: 'datetime'
			}],
			yAxis: [{
				gridLineColor: this.CHART_STYLES.gridColor,
				labels: {
					align: 'left',
					formatter: function () {
						return Highcharts.numberFormat(this.value, 2);
					},
					style: {
						color: this.CHART_STYLES.fontColor,
						fontFamily: this.CHART_STYLES.fontFamily,
						fontSize: this.CHART_STYLES.fontSize
					},
					x: 0,
					y: (this.CHART_STYLES.fontSize + 3)
				},
				maxPadding: 0,
				minPadding: 0,
				opposite: true,
				showFirstLabel: false,
				tickColor: this.CHART_STYLES.gridColor,
				tickLength: 100,  // Cropped at left of chart
				tickWidth: 1,
				title: {
					text: ''
				}
			}]
		};
	};

		return app;

})();<commit_msg>bringin back 88e21d1<commit_after>F2.Apps["com_openf2_examples_javascript_chart"] = (function(){

	var app = function (appConfig, appContent, root) {
		this.symbol = "MSFT";
		this.appConfig = appConfig;
		this.appContent = appContent;
		this.ui = this.appConfig.ui;
		this.root = root;
		this.$root = $(root);
		this.$app = $("#f2-1year-chart", this.$root);
		//set configuration
		this.config();
	};

	app.prototype.config = function() {

		var defaults = {
			backgroundColor: '#fff',
			lineColor: '#6A8F8E',
			lineWidth: 1.5,
			gridColor: '#DDDDDD',
			gridAltColor: '#F7F7F7',
			fontColor: '#444444',
			fontFamily: 'Arial, sans-serif',
			fontSize: 12,
			lineHeight: 1.2,
			greenBar: '#2EA94F',
			redBar: '#DB411C'
		},
		styleImport = (this.appConfig.context && this.appConfig.context.style)?this.appConfig.context.style:{};

		/** for example purposes*/
		console.group('Chart app');
		console.info('The chart app (com_openf2_examples_javascript_chart) has configuration options which can be overriden by using Context. Set a "style" property in the AppConfig\'s Context property. The current AppConfig is on the next line.');
		console.info(this.appConfig);
		console.info('The chart\'s configuration parameters (defaults) are found in the following hash');
		console.info(defaults);
		console.groupEnd();

		this.CHT_CONTAINER = 'f2-1year-chart';
		this.CHART_STYLES = $.extend({},defaults,styleImport);
	};

	app.prototype.redraw = function(data) {
		this.hc = null;
		this.symbol = data.symbol;
		this.getData();
	};

	app.prototype.init = function() {

		this.getData();

		//setup container symbol change listener to draw new chart.
		F2.Events.on(F2.Constants.Events.CONTAINER_SYMBOL_CHANGE, $.proxy(function(symbolData){
				this.redraw(symbolData);
			},this)
		);
	};

	app.prototype.getData = function() {

		this.ui.showMask(this.$root,true);

		$.ajax({
			beforeSend:function () {
				this.ui.setTitle('Loading chart...');
			},
			data: {
				symbol: this.symbol,
				duration: 365  // Fixed to one year
			},
			url: 'http://dev.markitondemand.com/Api/Timeseries/jsonp',
			dataType: 'jsonp',
			context: this

		}).done(function(jqxhr,txtStatus){
			//Catch errors
			if ( !jqxhr.Data || jqxhr.Message ) {
				if ( typeof console == 'object' ) console.error('Error: ', jqxhr.Message);
				this._chartError(jqxhr);
				return;
			}
			this.HandleAPIData(jqxhr);

		}).fail(function(jqxhr,txtStatus){
			F2.log('Could not generate chart.', jqxhr);
			this._chartError(jqxhr);
		});
	};

	app.prototype._chartError = function(jqxhr) {
		F2.log("Price Chart Error", jqxhr);
		this.ui.setTitle("Chart Error");
		this.$app.html("
An error occurred loading price data for " +this.symbol+ ".
");
		this.ui.hideMask(this.$root);
		this.ui.updateHeight();
	};

	// Parses API data to provide HighCharts-ready data series for close values,
	// additionally deriving up/down month indicators.
	//
	app.prototype.HandleAPIData = function (json) {

		$(this.CHT_CONTAINER).empty();

		// Set up vars for first data series
		var apiDates = json.Data.SeriesDates,
			apiValues = json.Data.Series.close.values,
			closeSeriesData = [ ];

		// Translate API JSON into a HighCharts-format data series
		for ( var i = 0; i < apiDates.length; i++ ) {
			var dat = new Date(apiDates[i]);
			var dateIn = Date.UTC(dat.getFullYear(), dat.getMonth(), dat.getDate());
			var val = apiValues[i];
			closeSeriesData.push([dateIn,val]);
		}

		// Instantiate a new chart with base configuration options (everything but the data)
		var hcChartObj = new Highcharts.Chart(this.getBaselineOptions());
		hcChartObj.series[0].setData(closeSeriesData, true);  // Set close-values series data
		//hcChartObj.setTitle({ text: ('One-year price movement for ' + json.Data.Name).toUpperCase() });  // Set title
		hcChartObj.setTitle({ text:'' });

		this.ui.hideMask(this.$root);
		this.ui.setTitle("ONE-YEAR PRICE MOVEMENT FOR " + this.symbol);

		// No options setting is available for this, so force the price line to be rounded
		$('.highcharts-series path:first', this.root).attr('stroke-linejoin', 'round').attr('stroke-linecap', 'round');

		// Set up vars for up/down month data series
		var currentMonthName, currentJSDate, currentJSUTCDate, currentVal,
			upSeriesData = [ ],
			downSeriesData = [ ];
		var dataRanges = hcChartObj.yAxis[0].getExtremes();  // Will need to reset to this later
			minVal = dataRanges.min,  // Will set red/green indicators to this value
			apiValues = json.Data.Series.close.values,
			apiDates = json.Data.SeriesDates,
			firstMonthName = apiDates[0].substr(4, 3),  // First!
			prevMonthName = firstMonthName,
			prevJSDate = new Date(prevMonthName + ' 1, ' + apiDates[0].substr(-4)),
			prevJSUTCDate = Date.UTC(prevJSDate.getFullYear(), prevJSDate.getMonth(), prevJSDate.getDate()),
			prevVal = apiValues[0];

		// Now walk through all data points again (had to do it once before to get the ranges),
		// looking for month boundaries and deciding if the previous month ended up or down over
		// the preceding month's close
		for ( var i = 1; i < apiDates.length; i++ ) {
			currentMonthName = apiDates[i].substr(4, 3);
			if ( currentMonthName != prevMonthName ) {  // Into a new month in the data
				currentVal = apiValues[i - 1];  // Last close in the preceding month
				currentJSDate = new Date(currentMonthName + ' 1, ' + apiDates[i].substr(-4));
				currentJSUTCDate = Date.UTC(currentJSDate.getFullYear(), currentJSDate.getMonth(), currentJSDate.getDate());
				if ( prevMonthName != firstMonthName ) {  // Skip the first month, it's incomplete
					if ( currentVal >= prevVal ) {
						upSeriesData.push( [ prevJSUTCDate, minVal ], [ currentJSUTCDate, minVal ] );
						downSeriesData.push( [ currentJSUTCDate, null ] );
					}
					else {
						downSeriesData.push( [ prevJSUTCDate, minVal ], [ currentJSUTCDate, minVal ] );
						upSeriesData.push( [ currentJSUTCDate, null ] );
					}
				}
				prevVal = currentVal;
				prevMonthName = currentMonthName;
				prevJSUTCDate = currentJSUTCDate;
			}
		}
		// Add one last interval for the partial month-to-date
		currentVal = apiValues[i - 1];  // Last close value in the data
		currentJSDate = new Date(apiDates[i - 1]);
		currentJSUTCDate = Date.UTC(currentJSDate.getFullYear(), currentJSDate.getMonth(), currentJSDate.getDate());
		if ( currentVal >= prevVal ) upSeriesData.push( [ prevJSUTCDate, minVal ], [ currentJSUTCDate, minVal ] );
		else downSeriesData.push( [ prevJSUTCDate, minVal ], [ currentJSUTCDate, minVal ] );

		// Add the up month/down month data to the chart's series
        hcChartObj.series[1].setData(upSeriesData, false);
        hcChartObj.series[2].setData(downSeriesData, false);

        hcChartObj.yAxis[0].setExtremes(dataRanges.dataMin, dataRanges.dataMax, true, false);

		this.ui.updateHeight();
	};

	// Defines the HighCharts configuration options.
	//
	app.prototype.getBaselineOptions = function () {
		return {
			chart: {
				borderColor: 'rgba(255, 255, 255, 0.0)',
				borderRadius: 0,
				defaultSeriesType: 'line',
				renderTo: this.CHT_CONTAINER,
				spacingBottom: 25,
				spacingLeft: 1,
				spacingRight: 1,
				backgroundColor: this.CHART_STYLES.backgroundColor
			},
			credits: {
				enabled: false
			},
			legend: {
				enabled: false
			},
			plotOptions: {
				line: {
					animation: false,
					lineWidth: this.CHART_STYLES.lineWidth
				},
				series: {
					marker: {
						enabled: false
					},
					shadow: false,
					states: {
						hover: {
							enabled: false
						}
					}
				}
			},
			series: [{
				color: this.CHART_STYLES.lineColor,
				name: 'Close price'
			},
			{
				color: this.CHART_STYLES.greenBar,
				lineWidth: 6,
				name: 'Up months'
			},
			{
				color: this.CHART_STYLES.redBar,
				lineWidth: 6,
				name: 'Down months'
			}],
			title: {
				align: 'left',
				style: {
					color: '#666',
					fontFamily: this.CHART_STYLES.fontFamily,
					fontSize: 14,
					fontWeight: 'bold',
					lineHeight: this.CHART_STYLES.lineHeight
				}
			},
			tooltip: {
				borderRadius: 1,
				crosshairs: true,
				formatter: function () {
					if ( this.series.name == 'Close price' ) {
						return ''
							+ Highcharts.dateFormat('%b %e %Y', this.x)
							+ '
'
							+ this.series.name + ': ' + Highcharts.numberFormat(this.y, 2)
							+ '';
					}
					else return false;
				},
				style: {
					color: this.CHART_STYLES.fontColor,
					fontFamily: this.CHART_STYLES.fontFamily,
					fontSize: this.CHART_STYLES.fontSize,
					lineHeight: this.CHART_STYLES.lineHeight,
					padding: this.CHART_STYLES.fontSize
				}
			},
			xAxis: [{  // Bottom datetime axis (short intervals)
				dateTimeLabelFormats: {
					minute: '%l:%M%P',
					hour: '%l%P',
					day: '%a',
					day: '%b %e',
					week: '%b %e',
					month: '%b',
					year: '%Y'
				},
				gridLineDashStyle: 'shortdot',
				gridLineColor: this.CHART_STYLES.gridAltColor,
				gridLineWidth: 1,
				labels: {
					align: 'left',
					style: {
						color: this.CHART_STYLES.fontColor,
						fontFamily: this.CHART_STYLES.fontFamily,
						fontSize: this.CHART_STYLES.fontSize
					},
					x: (this.CHART_STYLES.fontSize / 2),
					y: (this.CHART_STYLES.fontSize * this.CHART_STYLES.lineHeight * 1.5)
				},
				lineColor: this.CHART_STYLES.gridColor,
				tickColor: this.CHART_STYLES.gridColor,
				tickInterval: (30 * 24 * 3600 * 1000),  // One month
				tickLength: (this.CHART_STYLES.fontSize * this.CHART_STYLES.lineHeight * 1.5),
				type: 'datetime'
			},{  // Top datetime axis (longer intervals)
				dateTimeLabelFormats: {
					day: '%a',  // Default
					week: '%a',
					month: '%b %Y',
					year: '%Y'
				},
				gridLineWidth: 1,
				gridLineColor: this.CHART_STYLES.gridColor,
				labels: {
					align: 'left',
					style: {
						color: this.CHART_STYLES.fontColor,
						fontFamily: this.CHART_STYLES.fontFamily,
						fontSize: this.CHART_STYLES.fontSize
					},
					x: (this.CHART_STYLES.fontSize / 2)
				},
				lineColor: this.CHART_STYLES.gridColor,
				linkedTo: 0,
				opposite: true,
				tickColor: this.CHART_STYLES.gridColor,
				tickInterval: (365 * 24 * 3600 * 1000),  // One year
				tickLength: (this.CHART_STYLES.fontSize * this.CHART_STYLES.lineHeight),
				type: 'datetime'
			}],
			yAxis: [{
				gridLineColor: this.CHART_STYLES.gridColor,
				labels: {
					align: 'left',
					formatter: function () {
						return Highcharts.numberFormat(this.value, 2);
					},
					style: {
						color: this.CHART_STYLES.fontColor,
						fontFamily: this.CHART_STYLES.fontFamily,
						fontSize: this.CHART_STYLES.fontSize
					},
					x: 0,
					y: (this.CHART_STYLES.fontSize + 3)
				},
				maxPadding: 0,
				minPadding: 0,
				opposite: true,
				showFirstLabel: false,
				tickColor: this.CHART_STYLES.gridColor,
				tickLength: 100,  // Cropped at left of chart
				tickWidth: 1,
				title: {
					text: ''
				}
			}]
		};
	};

		return app;

})();<|endoftext|>


<commit_before>module.exports = {

    // Task options
    options: {
        limit: 4
    },

    // Tasks
    // all tasks inside one section run in parallel!

    // ===== Compile =====
    all_preprocess: [
        // CSS
        'spritesmith',
        'newer:sass',
        // JS
        'newer:jshint',
    ],
    all_postprocess: [
        // CSS
        'newer:csslint',
        'newer:postcss',
    ],
    all_min: [
        // JS
        'newer:uglify',
        // IMG
        'newer:imagemin',
    ],

    // ----- Watch -----
    // CSS
    css_preprocess: [
        'newer:spritesmith',
        'newer:sass',
    ],
    css_postprocess: [
        'newer:csslint',
        'newer:postcss',
    ],

    // JS
    js_preprocess: [
        'newer:jshint',
    ],
    js_postprocess: [

    ],
    js_merge: [
        'newer:concat',
    ],
    js_min: [
        'newer:uglify',
    ],

    // Images
    images: [
        'newer:imagemin'
    ]
};
<commit_msg>Disable Grunt:Sprite<commit_after>module.exports = {

    // Task options
    options: {
        limit: 4
    },

    // Tasks
    // all tasks inside one section run in parallel!

    // ===== Compile =====
    all_preprocess: [
        // CSS
        //'newer:spritesmith',
        'newer:sass',
        // JS
        'newer:jshint',
    ],
    all_postprocess: [
        // CSS
        'newer:csslint',
        'newer:postcss',
    ],
    all_min: [
        // JS
        'newer:uglify',
        // IMG
        'newer:imagemin',
    ],

    // ----- Watch -----
    // CSS
    css_preprocess: [
        //'newer:spritesmith',
        'newer:sass',
    ],
    css_postprocess: [
        'newer:csslint',
        'newer:postcss',
    ],

    // JS
    js_preprocess: [
        'newer:jshint',
    ],
    js_postprocess: [

    ],
    js_merge: [
        'newer:concat',
    ],
    js_min: [
        'newer:uglify',
    ],

    // Images
    images: [
        'newer:imagemin'
    ]
};
<|endoftext|>


<commit_before>/**
 * maryamyriameliamurphies.js
 * A library of Haskell-style morphisms ported to ES2015 JavaScript.
 *
 * test/ord-test.js
 *
 * @file Tests for Ord type class.
 * @license ISC
 */

/* global describe, it */

import {
  EQ,
  LT,
  GT,
  compare,
  lessThan,
  lessThanOrEqual,
  greaterThan,
  greaterThanOrEqual,
  max,
  min,
  just,
  tuple,
  list
} from '../source';

describe(`Ord type class`, function() {
  const a = 1;
  const b = 2;
  const c = 2;
  const d = 2;
  const mb1 = just(1);
  const mb2 = just(2);
  const tup1 = tuple(1,2);
  const tup2 = tuple(2,1);
  const lst1 = list(1,2,3);
  const lst2 = list(3,2,1);
  describe(`compare()`, function() {
    it(`should return the Ordering of two values if they are the same type`, function() {
      compare(a, b).should.equal(LT);
      compare(b, a).should.equal(GT);
      compare(b, c).should.equal(EQ);
      compare(mb1, mb2).should.equal(LT);
      compare(mb2, mb1).should.equal(GT);
      compare(mb1, just(1)).should.equal(EQ);
      compare(tup1, tup2).should.equal(LT);
      compare(tup2, tup1).should.equal(GT);
      compare(tup1, tuple(1,2)).should.equal(EQ);
      compare(lst1, lst2).should.equal(LT);
      compare(lst2, lst1).should.equal(GT);
      compare(lst1, list(1,2,3)).should.equal(EQ);
    });
    it(`should throw a type error if two tuples are not the same type`, function() {
      compare.bind(null, c, `text`).should.throw();
    });
  });
  describe(`lessThan()`, function() {
    it(`should return true if the first argument is less than the second argument`, function() {
      lessThan(a, b).should.be.true;
      lessThan(mb1, mb2).should.be.true;
      lessThan(tup1, tup2).should.be.true;
      lessThan(lst1, lst2).should.be.true;
    });
    it(`should return false if the first argument is not less than the second argument`, function() {
      lessThan(c, d).should.be.false;
      lessThan(b, a).should.be.false;
      lessThan(mb2, mb1).should.be.false;
      lessThan(tup2, tup1).should.be.false;
      lessThan(lst2, lst1).should.be.false;
    });
  });
  describe(`lessThanOrEqual()`, function() {
    it(`should return true if the first argument is less than or equal to the second argument`, function() {
      lessThanOrEqual(a, b).should.be.true;
      lessThanOrEqual(c, d).should.be.true;
      lessThanOrEqual(mb1, mb2).should.be.true;
      lessThanOrEqual(mb1, just(1)).should.be.true;
      lessThanOrEqual(tup1, tup2).should.be.true;
      lessThanOrEqual(tup1, tuple(1,2)).should.be.true;
      lessThanOrEqual(lst1, lst2).should.be.true;
      lessThanOrEqual(lst1, list(1,2,3)).should.be.true;
    });
    it(`should return false if the first argument is not less than or equal to the second argument`, function() {
      lessThanOrEqual(b, a).should.be.false;
      lessThanOrEqual(mb2, mb1).should.be.false;
      lessThanOrEqual(tup2, tup1).should.be.false;
      lessThanOrEqual(lst2, lst1).should.be.false;
    });
  });
  describe(`greaterThan()`, function() {
    it(`should return true if the first argument is greater than to the second argument`, function() {
      greaterThan(b, a).should.be.true;
      greaterThan(mb2, mb1).should.be.true;
      greaterThan(tup2, tup1).should.be.true;
      greaterThan(lst2, lst1).should.be.true;
    });
    it(`should return false if the first argument is not greater than to the second argument`, function() {
      greaterThan(c, d).should.be.false;
      greaterThan(a, b).should.be.false;
      greaterThan(mb1, mb2).should.be.false;
      greaterThan(tup1, tup2).should.be.false;
      greaterThan(lst1, lst2).should.be.false;
    });
  });
  describe(`greaterThanOrEqual()`, function() {
    it(`should return true if the first argument is greater than or equal to the second argument`, function() {
      greaterThanOrEqual(mb2, mb1).should.be.true;
      greaterThanOrEqual(mb2, just(2)).should.be.true;
      greaterThanOrEqual(tup2, tup1).should.be.true;
      greaterThanOrEqual(tup2, tuple(2,1)).should.be.true;
      greaterThanOrEqual(lst2, lst1).should.be.true;
      greaterThanOrEqual(lst2, list(3,2,1)).should.be.true;
    });
    it(`should return false if the first argument is not greater than or equal to the second argument`, function() {
      greaterThanOrEqual(b, a).should.be.true;
      greaterThanOrEqual(c, d).should.be.true;
      greaterThanOrEqual(a, b).should.be.false;
      greaterThanOrEqual(mb1, mb2).should.be.false;
      greaterThanOrEqual(tup1, tup2).should.be.false;
      greaterThanOrEqual(lst1, lst2).should.be.false;
    });
  });
  describe(`max()`, function() {
    it(`should return the greater of two values`, function() {
      max(a, b).should.equal(2);
      max(mb1, mb2).should.equal(mb2);
      max(tup1, tup2).should.equal(tup2);
      max(lst1, lst2).should.equal(lst2);
    });
  });
  describe(`min()`, function() {
    it(`should return the lesser of two values`, function() {
      min(a, b).should.equal(1);
      min(mb1, mb2).should.equal(mb1);
      min(tup1, tup2).should.equal(tup1);
      min(lst1, lst2).should.equal(lst1);
    });
  });
});
<commit_msg>Add a test for ternary tuples to make coverage of Tuple 100%<commit_after>/**
 * maryamyriameliamurphies.js
 * A library of Haskell-style morphisms ported to ES2015 JavaScript.
 *
 * test/ord-test.js
 *
 * @file Tests for Ord type class.
 * @license ISC
 */

/* global describe, it */

import {
  EQ,
  LT,
  GT,
  compare,
  lessThan,
  lessThanOrEqual,
  greaterThan,
  greaterThanOrEqual,
  max,
  min,
  just,
  tuple,
  list
} from '../source';

describe(`Ord type class`, function() {
  const a = 1;
  const b = 2;
  const c = 2;
  const d = 2;
  const mb1 = just(1);
  const mb2 = just(2);
  const tup1 = tuple(1,2);
  const tup2 = tuple(2,1);
  const tup3 = tuple(2,2,1);
  const tup4 = tuple(2,2,2);
  const lst1 = list(1,2,3);
  const lst2 = list(3,2,1);
  describe(`compare()`, function() {
    it(`should return the Ordering of two values if they are the same type`, function() {
      compare(a, b).should.equal(LT);
      compare(b, a).should.equal(GT);
      compare(b, c).should.equal(EQ);
      compare(mb1, mb2).should.equal(LT);
      compare(mb2, mb1).should.equal(GT);
      compare(mb1, just(1)).should.equal(EQ);
      compare(tup1, tup2).should.equal(LT);
      compare(tup2, tup1).should.equal(GT);
      compare(tup3, tup4).should.equal(LT);
      compare(tup4, tup3).should.equal(GT);
      compare(tup1, tuple(1,2)).should.equal(EQ);
      compare(lst1, lst2).should.equal(LT);
      compare(lst2, lst1).should.equal(GT);
      compare(lst1, list(1,2,3)).should.equal(EQ);
    });
    it(`should throw a type error if two tuples are not the same type`, function() {
      compare.bind(null, c, `text`).should.throw();
    });
  });
  describe(`lessThan()`, function() {
    it(`should return true if the first argument is less than the second argument`, function() {
      lessThan(a, b).should.be.true;
      lessThan(mb1, mb2).should.be.true;
      lessThan(tup1, tup2).should.be.true;
      lessThan(lst1, lst2).should.be.true;
    });
    it(`should return false if the first argument is not less than the second argument`, function() {
      lessThan(c, d).should.be.false;
      lessThan(b, a).should.be.false;
      lessThan(mb2, mb1).should.be.false;
      lessThan(tup2, tup1).should.be.false;
      lessThan(lst2, lst1).should.be.false;
    });
  });
  describe(`lessThanOrEqual()`, function() {
    it(`should return true if the first argument is less than or equal to the second argument`, function() {
      lessThanOrEqual(a, b).should.be.true;
      lessThanOrEqual(c, d).should.be.true;
      lessThanOrEqual(mb1, mb2).should.be.true;
      lessThanOrEqual(mb1, just(1)).should.be.true;
      lessThanOrEqual(tup1, tup2).should.be.true;
      lessThanOrEqual(tup1, tuple(1,2)).should.be.true;
      lessThanOrEqual(lst1, lst2).should.be.true;
      lessThanOrEqual(lst1, list(1,2,3)).should.be.true;
    });
    it(`should return false if the first argument is not less than or equal to the second argument`, function() {
      lessThanOrEqual(b, a).should.be.false;
      lessThanOrEqual(mb2, mb1).should.be.false;
      lessThanOrEqual(tup2, tup1).should.be.false;
      lessThanOrEqual(lst2, lst1).should.be.false;
    });
  });
  describe(`greaterThan()`, function() {
    it(`should return true if the first argument is greater than to the second argument`, function() {
      greaterThan(b, a).should.be.true;
      greaterThan(mb2, mb1).should.be.true;
      greaterThan(tup2, tup1).should.be.true;
      greaterThan(lst2, lst1).should.be.true;
    });
    it(`should return false if the first argument is not greater than to the second argument`, function() {
      greaterThan(c, d).should.be.false;
      greaterThan(a, b).should.be.false;
      greaterThan(mb1, mb2).should.be.false;
      greaterThan(tup1, tup2).should.be.false;
      greaterThan(lst1, lst2).should.be.false;
    });
  });
  describe(`greaterThanOrEqual()`, function() {
    it(`should return true if the first argument is greater than or equal to the second argument`, function() {
      greaterThanOrEqual(mb2, mb1).should.be.true;
      greaterThanOrEqual(mb2, just(2)).should.be.true;
      greaterThanOrEqual(tup2, tup1).should.be.true;
      greaterThanOrEqual(tup2, tuple(2,1)).should.be.true;
      greaterThanOrEqual(lst2, lst1).should.be.true;
      greaterThanOrEqual(lst2, list(3,2,1)).should.be.true;
    });
    it(`should return false if the first argument is not greater than or equal to the second argument`, function() {
      greaterThanOrEqual(b, a).should.be.true;
      greaterThanOrEqual(c, d).should.be.true;
      greaterThanOrEqual(a, b).should.be.false;
      greaterThanOrEqual(mb1, mb2).should.be.false;
      greaterThanOrEqual(tup1, tup2).should.be.false;
      greaterThanOrEqual(lst1, lst2).should.be.false;
    });
  });
  describe(`max()`, function() {
    it(`should return the greater of two values`, function() {
      max(a, b).should.equal(2);
      max(mb1, mb2).should.equal(mb2);
      max(tup1, tup2).should.equal(tup2);
      max(lst1, lst2).should.equal(lst2);
    });
  });
  describe(`min()`, function() {
    it(`should return the lesser of two values`, function() {
      min(a, b).should.equal(1);
      min(mb1, mb2).should.equal(mb1);
      min(tup1, tup2).should.equal(tup1);
      min(lst1, lst2).should.equal(lst1);
    });
  });
});
<|endoftext|>


<commit_before>angular.module("omniControllers")
	.controller("ExplorerCrowdsalesController",["$scope", "PropertyManager", "$timeout","$http","$templateCache","$element","$compile",
		function ExplorerCrowdsalesController($scope, PropertyManager, $timeout, $http, $templateCache, $element, $compile){
		    $scope.crowdsales = [];

		    $scope.setEcosystem = function(ecosystem){
			  	$scope.ecosystem=ecosystem;
			    PropertyManager.getActiveCrowdsales($scope.ecosystem).then(function(result){
			        $scope.crowdsales=result.data.crowdsales;
			        if($scope.crowdsales.length>0)
				        $timeout(function (){
				        	return $http.get("/views/assets/partials/remaining_timer.html", {cache: $templateCache}).success(function(template) {
					            for (var i = 0; i < $scope.crowdsales.length; i++) {
				        			var endTime = $scope.crowdsales[i].deadline;
				              		$element.find('#timerWrapper-'+$scope.crowdsales[i].propertyid).append(template.replace("{{endtime}}",endTime));
				        		}
				        		$compile($element.contents())($scope);
						    });
				        });;
			    });
			}

			$scope.setEcosystem(1);
	}])<commit_msg>Fix typo<commit_after>angular.module("omniControllers")
	.controller("ExplorerCrowdsalesController",["$scope", "PropertyManager", "$timeout","$http","$templateCache","$element","$compile",
		function ExplorerCrowdsalesController($scope, PropertyManager, $timeout, $http, $templateCache, $element, $compile){
		    $scope.crowdsales = [];

		    $scope.setEcosystem = function(ecosystem){
			  	$scope.ecosystem=ecosystem;
			    PropertyManager.getActiveCrowdsales($scope.ecosystem).then(function(result){
			        $scope.crowdsales=result.data.crowdsales;
			        if($scope.crowdsales.length>0)
				        $timeout(function (){
				        	return $http.get("/views/assets/partials/timer_remaining.html", {cache: $templateCache}).success(function(template) {
					            for (var i = 0; i < $scope.crowdsales.length; i++) {
				        			var endTime = $scope.crowdsales[i].deadline;
				              		$element.find('#timerWrapper-'+$scope.crowdsales[i].propertyid).append(template.replace("{{endtime}}",endTime));
				        		}
				        		$compile($element.contents())($scope);
						    });
				        });;
			    });
			}

			$scope.setEcosystem(1);
	}])<|endoftext|>


<commit_before>/*
 *   User ufo
 */
if(typeof(require) !== 'undefined'){
	var helpers = require("./helpers").helpers;
	var entity = require("./entity").entity;
	var colors; // = require("./rules").colors;
	var laserbeam = require("./laserbeam").laserbeam;
	var explosion = require("./explosion").explosion;
	// AI
	var engine = require("./engine").engine;
	require('./ai/ufo.js');
}

var ufo = function(config){
	helpers.apply(config, this);
	this.laserState = 10; // 10 = ready, 0 = charging
	this.direction = this.direction || 1;
	this.audioDone = false;
	this.colors = colors ? colors : require("./rules").colors;
	this.color = this.colors[this.colorIndex] || this.color || "#FFF";
	this.speed = 3;
	this.invulerability = 20;
	this.nextFrame = false;
	this.name = this.name || 'ufo';
	this.position = this.position || {x:0, y:0};
	this.gunOffset =  {x:40, y:0};
	// x -20   y -15
	this.collisionRect = {x: -20, y: -15, w: 40,h: 30};
	this.modelIndex = 4;
	this.ufoFrame = 0;
	this.ufoFrames = [ [
		{x: -10, y: -15, w: 20, h: 10},
		{x: -10, y: -5, w: 30, h: 10},
		{x: -10, y: 5, w: 20, h: 10}
	],
	[
		{x: -10, y: -15, w: 20, h: 10},
		{x: -20, y: -5, w: 10, h: 10}, {x: 0, y: -5, w: 20, h: 10},
		{x: -10, y: 5, w: 20, h: 10}
	],
	[
		{x: -10, y: -15, w: 20, h: 10},
		{x: -20, y: -5, w: 20, h: 10}, {x: 10, y: -5, w: 10, h: 10},
		{x: -10, y: 5, w: 20, h: 10}
	],
	[
		{x: -10, y: -15, w: 20, h: 10},
		{x: -20, y: -5, w: 30, h: 10},
		{x: -10, y: 5, w: 20, h: 10}
	],
	[
		{x: -10, y: -15, w: 20, h: 10},
		{x: -20, y: -5, w: 40, h: 10},
		{x: -10, y: 5, w: 20, h: 10}
	]];
};

ufo.prototype = new entity();

ufo.prototype.render = function(){
	if(!this.audioDone){
		this.audioDone = true;
		try{
		if(audio){
			audio.appearAudio.play();
		}}catch(ex){}
	}
};

ufo.prototype.update = function(time){
	if(this.engine.mode !== 'client'){
		this.handleCollisions();
		var controls = engine.ai[engine.ufoai].call(this);
		this.mousePosition = controls.mousePosition;
		this.shoot = controls.shoot;
	}
	var timeDelta = this.getTimeDelta();
	this.position = this.calculateMovement(this.position, this.mousePosition, 10, timeDelta);
	if(this.engine.mode !== 'client'){
		this.handleLaser(time);
	}
	this.handleAnimation(time);
};

ufo.prototype.getTimeDelta = function(){
	if(!this.lastTimeCalled){
		this.lastTimeCalled = time;
	}
	var timeDelta = time - this.lastTimeCalled;
	this.lastTimeCalled = time;
	return timeDelta;
};

ufo.prototype.calculateMovement = function(currentPosition, mousePosition, speedLimit, timeDelta){
	var result = currentPosition;
	if(mousePosition){
		var deltaX = mousePosition.x - currentPosition.x;
		var deltaY = mousePosition.y - currentPosition.y;
		var distance = helpers.distance(currentPosition, mousePosition);
		var f = 0.25;
		var speed = speedLimit * (timeDelta / 40);
		if(distance > speed){
			f = speed / distance;
		}
		result = {
			x: this.position.x + (deltaX * f),
			y: this.position.y + (deltaY * f)
		};
	}
	return result;
};

ufo.prototype.handleCollisions = function(){
	if(this.invulerability){
		this.invulerability--;
	}
	if(this.collisions && this.collisions.length){
		for(var i = 0; i < this.collisions.length; i++){
			if(this.collisions[i].owner != this && !this.invulerability){
				if(!this.engine.gameState.gameOver && !this.finished){
					if(this.collisions[i].owner == this.engine.gameState.player1Ship){
						this.engine.gameState.player1Score++;
					}
					if(this.collisions[i].owner == this.engine.gameState.player2Ship){
						this.engine.gameState.player2Score++;
					}
				}
				this.finished = true;
				break;
			}
		}
	}
};

ufo.prototype.onRemove = function(){
	if(this.engine.mode !== 'server'){
		// The server does not care about the explosion as it is just a visual
		this.engine.add(new explosion({
			position: this.position
		}));
	}
};

ufo.prototype.handleLaser = function(time){
	if(this.shoot && this.laserState == 10){
		this.laserState = -20;
		this.gunOffset.x = this.direction === 1 ? 40 : -40;
		this.engine.add(new laserbeam({
									position: {x:this.position.x + this.gunOffset.x, y:this.position.y + this.gunOffset.y},
									direction: this.direction,
									owner: this
									}));
	}
	else if(this.laserState != 10){
		this.laserState = this.laserState + 2;
	}
};

ufo.prototype.handleAnimation = function(time){
	this.direction = 1;
	if(this.mousePosition && this.position.x < this.mousePosition.x){
		this.direction = -1;
	}
	if(!this.lastTimeFrameChanged){
		this.lastTimeFrameChanged = time;
	}
	var frameChangeTimeDelta = time - this.lastTimeFrameChanged;
	if(frameChangeTimeDelta > 80){
		this.lastTimeFrameChanged = time;
		this.classicModel = this.ufoFrames[this.ufoFrame];
		this.ufoFrame += this.direction;
		if(this.ufoFrame >= this.ufoFrames.length) this.ufoFrame = 0;
		if(this.ufoFrame < 0) this.ufoFrame = this.ufoFrames.length - 1;
	}
	if(this.ufoFrame === 0){
		this.modelIndex = 2;
		this.direction = 1;
	}
	else if(this.ufoFrame === 1){
		this.modelIndex = 3;
		this.direction = 1;
	}
	else if(this.ufoFrame === 2){
		this.modelIndex = 4;
		this.direction = 1;
	}
	else if(this.ufoFrame === 3){
		this.modelIndex = 4;
		this.direction = -1;
	}
	else if(this.ufoFrame === 4){
		this.modelIndex = 3;
		this.direction = -1;
	}
};

ufo.prototype.getRemoteData = function(){
	if(this.mousePosition){
		var mouseX = Math.ceil(this.mousePosition.x);
		var mouseY = Math.ceil(this.mousePosition.y);
		if(!this.previousMousePosition || mouseX !== this.previousMousePosition.x || mouseY !== this.previousMousePosition.y){
			this.previousMousePosition = {
				x: mouseX,
				y: mouseY
			};
			var result = "3," + Math.ceil(this.position.x) + "," +
			              Math.ceil(this.position.y) + "," +
			              this.colorIndex + "," +
		        		  mouseX + "," +
			              mouseY;
		}
	}
	return result;
};

ufo.prototype.renderRemoteData = function(remoteData, offset){
	this.position = {x:parseFloat(remoteData[offset + 1]), y:parseFloat(remoteData[offset + 2])};
	this.colorIndex = parseInt(remoteData[offset + 3]);
	this.color = this.colors[this.colorIndex];
	this.mousePosition = {x:parseInt(remoteData[offset + 4]), y: parseInt(remoteData[offset + 5])};
	return offset + 6;
};

if(typeof(exports) !== 'undefined'){
	exports.ufo = ufo;
}<commit_msg>Removed spurious var<commit_after>/*
 *   User ufo
 */
if(typeof(require) !== 'undefined'){
	var helpers = require("./helpers").helpers;
	var entity = require("./entity").entity;
	var colors; // = require("./rules").colors;
	var laserbeam = require("./laserbeam").laserbeam;
	var explosion = require("./explosion").explosion;
	// AI
	var engine = require("./engine").engine;
	require('./ai/ufo.js');
}

var ufo = function(config){
	helpers.apply(config, this);
	this.laserState = 10; // 10 = ready, 0 = charging
	this.direction = this.direction || 1;
	this.audioDone = false;
	this.colors = colors ? colors : require("./rules").colors;
	this.color = this.colors[this.colorIndex] || this.color || "#FFF";
	this.speed = 3;
	this.invulerability = 20;
	this.nextFrame = false;
	this.name = this.name || 'ufo';
	this.position = this.position || {x:0, y:0};
	this.gunOffset =  {x:40, y:0};
	// x -20   y -15
	this.collisionRect = {x: -20, y: -15, w: 40,h: 30};
	this.modelIndex = 4;
	this.ufoFrame = 0;
	this.ufoFrames = [ [
		{x: -10, y: -15, w: 20, h: 10},
		{x: -10, y: -5, w: 30, h: 10},
		{x: -10, y: 5, w: 20, h: 10}
	],
	[
		{x: -10, y: -15, w: 20, h: 10},
		{x: -20, y: -5, w: 10, h: 10}, {x: 0, y: -5, w: 20, h: 10},
		{x: -10, y: 5, w: 20, h: 10}
	],
	[
		{x: -10, y: -15, w: 20, h: 10},
		{x: -20, y: -5, w: 20, h: 10}, {x: 10, y: -5, w: 10, h: 10},
		{x: -10, y: 5, w: 20, h: 10}
	],
	[
		{x: -10, y: -15, w: 20, h: 10},
		{x: -20, y: -5, w: 30, h: 10},
		{x: -10, y: 5, w: 20, h: 10}
	],
	[
		{x: -10, y: -15, w: 20, h: 10},
		{x: -20, y: -5, w: 40, h: 10},
		{x: -10, y: 5, w: 20, h: 10}
	]];
};

ufo.prototype = new entity();

ufo.prototype.render = function(){
	if(!this.audioDone){
		this.audioDone = true;
		try{
		if(audio){
			audio.appearAudio.play();
		}}catch(ex){}
	}
};

ufo.prototype.update = function(time){
	if(this.engine.mode !== 'client'){
		this.handleCollisions();
		var controls = engine.ai[engine.ufoai].call(this);
		this.mousePosition = controls.mousePosition;
		this.shoot = controls.shoot;
	}
	var timeDelta = this.getTimeDelta();
	this.position = this.calculateMovement(this.position, this.mousePosition, 10, timeDelta);
	if(this.engine.mode !== 'client'){
		this.handleLaser(time);
	}
	this.handleAnimation(time);
};

ufo.prototype.getTimeDelta = function(){
	if(!this.lastTimeCalled){
		this.lastTimeCalled = time;
	}
	var timeDelta = time - this.lastTimeCalled;
	this.lastTimeCalled = time;
	return timeDelta;
};

ufo.prototype.calculateMovement = function(currentPosition, mousePosition, speedLimit, timeDelta){
	var result = currentPosition;
	if(mousePosition){
		var deltaX = mousePosition.x - currentPosition.x;
		var deltaY = mousePosition.y - currentPosition.y;
		var distance = helpers.distance(currentPosition, mousePosition);
		var f = 0.25;
		var speed = speedLimit * (timeDelta / 40);
		if(distance > speed){
			f = speed / distance;
		}
		result = {
			x: this.position.x + (deltaX * f),
			y: this.position.y + (deltaY * f)
		};
	}
	return result;
};

ufo.prototype.handleCollisions = function(){
	if(this.invulerability){
		this.invulerability--;
	}
	if(this.collisions && this.collisions.length){
		for(var i = 0; i < this.collisions.length; i++){
			if(this.collisions[i].owner != this && !this.invulerability){
				if(!this.engine.gameState.gameOver && !this.finished){
					if(this.collisions[i].owner == this.engine.gameState.player1Ship){
						this.engine.gameState.player1Score++;
					}
					if(this.collisions[i].owner == this.engine.gameState.player2Ship){
						this.engine.gameState.player2Score++;
					}
				}
				this.finished = true;
				break;
			}
		}
	}
};

ufo.prototype.onRemove = function(){
	if(this.engine.mode !== 'server'){
		// The server does not care about the explosion as it is just a visual
		this.engine.add(new explosion({
			position: this.position
		}));
	}
};

ufo.prototype.handleLaser = function(time){
	if(this.shoot && this.laserState == 10){
		this.laserState = -20;
		this.gunOffset.x = this.direction === 1 ? 40 : -40;
		this.engine.add(new laserbeam({
									position: {x:this.position.x + this.gunOffset.x, y:this.position.y + this.gunOffset.y},
									direction: this.direction,
									owner: this
									}));
	}
	else if(this.laserState != 10){
		this.laserState = this.laserState + 2;
	}
};

ufo.prototype.handleAnimation = function(time){
	this.direction = 1;
	if(this.mousePosition && this.position.x < this.mousePosition.x){
		this.direction = -1;
	}
	if(!this.lastTimeFrameChanged){
		this.lastTimeFrameChanged = time;
	}
	var frameChangeTimeDelta = time - this.lastTimeFrameChanged;
	if(frameChangeTimeDelta > 80){
		this.lastTimeFrameChanged = time;
		this.classicModel = this.ufoFrames[this.ufoFrame];
		this.ufoFrame += this.direction;
		if(this.ufoFrame >= this.ufoFrames.length) this.ufoFrame = 0;
		if(this.ufoFrame < 0) this.ufoFrame = this.ufoFrames.length - 1;
	}
	if(this.ufoFrame === 0){
		this.modelIndex = 2;
		this.direction = 1;
	}
	else if(this.ufoFrame === 1){
		this.modelIndex = 3;
		this.direction = 1;
	}
	else if(this.ufoFrame === 2){
		this.modelIndex = 4;
		this.direction = 1;
	}
	else if(this.ufoFrame === 3){
		this.modelIndex = 4;
		this.direction = -1;
	}
	else if(this.ufoFrame === 4){
		this.modelIndex = 3;
		this.direction = -1;
	}
};

ufo.prototype.getRemoteData = function(){
	var result = null;
	if(this.mousePosition){
		var mouseX = Math.ceil(this.mousePosition.x);
		var mouseY = Math.ceil(this.mousePosition.y);
		if(!this.previousMousePosition || mouseX !== this.previousMousePosition.x || mouseY !== this.previousMousePosition.y){
			this.previousMousePosition = {
				x: mouseX,
				y: mouseY
			};
			result = "3," + Math.ceil(this.position.x) + "," +
			              Math.ceil(this.position.y) + "," +
			              this.colorIndex + "," +
		        		  mouseX + "," +
			              mouseY;
		}
	}
	return result;
};

ufo.prototype.renderRemoteData = function(remoteData, offset){
	this.position = {x:parseFloat(remoteData[offset + 1]), y:parseFloat(remoteData[offset + 2])};
	this.colorIndex = parseInt(remoteData[offset + 3]);
	this.color = this.colors[this.colorIndex];
	this.mousePosition = {x:parseInt(remoteData[offset + 4]), y: parseInt(remoteData[offset + 5])};
	return offset + 6;
};

if(typeof(exports) !== 'undefined'){
	exports.ufo = ufo;
}<|endoftext|>


<commit_before>const PubsubConnector = require('./pubsub-connector')

module.exports = (db, sequelize) => {
  const parseHookData = ({dataValues, _changed, $modelOptions}) => {
    return {
      objectId: dataValues.id,
      modelName: $modelOptions.name.singular,
      changedFields: _changed,
    }
  }

  const isTransaction = ({$modelOptions}) => {
    return $modelOptions.name.singular === "Transaction"
  }

  const transactionLogger = (type) => {
    return (sequelizeHookData) => {
      if (isTransaction(sequelizeHookData)) return;
      const transactionData = Object.assign({type: type},
        parseHookData(sequelizeHookData)
      );
      db.Transaction.create(transactionData);
      transactionData.object = sequelizeHookData.dataValues;

      PubsubConnector.notifyDelta(db.accountId, transactionData);
    }
  }

  sequelize.addHook("afterCreate", transactionLogger("create"))
  sequelize.addHook("afterUpdate", transactionLogger("update"))
  sequelize.addHook("afterDelete", transactionLogger("delete"))
}
<commit_msg>Fix transaction case issue<commit_after>const PubsubConnector = require('./pubsub-connector')

module.exports = (db, sequelize) => {
  const parseHookData = ({dataValues, _changed, $modelOptions}) => {
    return {
      objectId: dataValues.id,
      modelName: $modelOptions.name.singular,
      changedFields: _changed,
    }
  }

  const isTransaction = ({$modelOptions}) => {
    return $modelOptions.name.singular === "transaction"
  }

  const transactionLogger = (type) => {
    return (sequelizeHookData) => {
      if (isTransaction(sequelizeHookData)) return;
      const transactionData = Object.assign({type: type},
        parseHookData(sequelizeHookData)
      );
      db.Transaction.create(transactionData);
      transactionData.object = sequelizeHookData.dataValues;

      PubsubConnector.notifyDelta(db.accountId, transactionData);
    }
  }

  sequelize.addHook("afterCreate", transactionLogger("create"))
  sequelize.addHook("afterUpdate", transactionLogger("update"))
  sequelize.addHook("afterDelete", transactionLogger("delete"))
}
<|endoftext|>


<commit_before>/**
 * @scope enchant.InputManager.prototype
 */
enchant.InputManager = enchant.Class.create(enchant.EventTarget, {
    /**
     * @name enchant.InputManager
     * @class
     [lang:ja]
     * 入力を管理するためのクラス.
     * @param {*} flagStore 入力のフラグを保持させるオブジェクト.
     * @param {String} activeEventNameSuffix イベント名の接尾辞.
     * @param {String} inactiveEventNameSuffix イベント名の接尾辞.
     [/lang]
     [lang:en]
     * Class for managing input.
     * @param {*} flagStore object that store input flag.
     * @param {String} activeEventNameSuffix event name suffix.
     * @param {String} inactiveEventNameSuffix event name suffix.
     [/lang]
     * @constructs
     * @extends enchant.EventTarget
     */
    initialize: function(flagStore, activeEventNameSuffix, inactiveEventNameSuffix) {
        enchant.EventTarget.call(this);
        /**
         [lang:ja]
         * アクティブな入力の数.
         [/lang]
         [lang:en]
         * The number of active inputs.
         [/lang]
         * @type {Number}
         */
        this.activeInputsNum = 0;
        /**
         [lang:ja]
         * 入力の変化を通知する対象を保持する配列.
         [/lang]
         [lang:en]
         * Array that store event target.
         [/lang]
         * @type {enchant.EventTarget[]}
         */
        this.broadcastTarget = [];
        /**
         [lang:ja]
         * 入力の状態を真偽値で保持する連想配列.
         [/lang]
         [lang:en]
         * Object that store input flag.
         [/lang]
         * @type {Object}
         */
        this.flagStore = flagStore;
        /**
         [lang:ja]
         * InputManagerが発行するイベント名の接尾辞.
         [/lang]
         [lang:en]
         * event name suffix that dispatched by InputManager.
         [/lang]
         * @type {String}
         */
        this.activeEventNameSuffix = activeEventNameSuffix;
        /**
         [lang:ja]
         * InputManagerが発行するイベント名の接尾辞.
         [/lang]
         [lang:en]
         * event name suffix that dispatched by InputManager.
         [/lang]
         * @type {String}
         */
        this.inactiveEventNameSuffix = inactiveEventNameSuffix;

        this._binds = {};
        this._stateHandler = function(e) {
            var id = e.source.identifier;
            var name = this._binds[id];
            this.changeState(name, e.state);
        }.bind(this);
    },
    /**
     [lang:ja]
     * 入力の変化を通知する対象を追加する.
     [/lang]
     [lang:en]
     * Add event target.
     [/lang]
     * @param {enchant.EventTarget} eventTarget broadcast target.
     */
    addBroadcastTarget: function(eventTarget) {
        this.broadcastTarget.push(this);
    },
    /**
     [lang:ja]
     * 入力の変化を通知する対象を削除する.
     [/lang]
     [lang:en]
     * Remove event target.
     [/lang]
     * @param {enchant.EventTarget} eventTarget broadcast target.
     */
    removeBroadcastTarget: function(eventTarget) {
        var i = this.broadcastTarget.indexOf(eventTarget);
        if (i !== -1) {
            this.broadcastTarget.splice(i, 1);
        }
    },
    /**
     [lang:ja]
     * イベントを{@link enchant.InputManager#broadcastTarget}に発行する.
     [/lang]
     [lang:en]
     * Dispatch event to {@link enchant.InputManager#broadcastTarget}.
     [/lang]
     * @param {enchant.Event} e event.
     */
    broadcastEvent: function(e) {
        var target = this.broadcastTarget;
        for (var i = 0, l = target.length; i < l; i++) {
            target[i].dispatchEvent(e);
        }
    },
    /**
     [lang:ja]
     * 特定の入力に名前をつける.
     * 入力はフラグとイベントで監視できるようになる.
     [/lang]
     [lang:en]
     * Name specified input.
     * Input can be watched by flag or event.
     [/lang]
     * @param {enchant.InputSource} inputSource input source.
     * @param {String} name input name.
     */
    bind: function(inputSource, name) {
        inputSource.addEventListener(enchant.Event.INPUT_STATE_CHANGED, this._stateHandler);
        this._binds[inputSource.identifier] = name;
        this.flagStore[inputSource.identifier] = false;
    },
    /**
     [lang:ja]
     * 入力のバインドを解除する.
     [/lang]
     [lang:en]
     * Remove binded name.
     [/lang]
     * @param {enchant.InputSource} inputSource input source.
     */
    unbind: function(inputSource) {
        inputSource.removeEventListener(enchant.Event.INPUT_STATE_CHANGED, this._stateHandler);
        delete this._binds[inputSource.identifier];
        delete this.flagStore[inputSource.identifier];
    },
    /**
     [lang:ja]
     * 入力の状態変更を変更する.
     [/lang]
     [lang:en]
     * Change state of input.
     [/lang]
     * @param {String} name input name.
     * @param {Boolean} bool input state.
     */
    changeState: function(name, bool) {
        var inputEvent;
        if (bool) {
            this._down(name);
        } else {
            this._up(name);
        }
    },
    _down: function(name) {
        var inputEvent;
        if (!this.flagStore[name]) {
            this.flagStore[name] = true;
            inputEvent = new enchant.Event((this.activeInputsNum++) ? 'inputchange' : 'inputstart');
            inputEvent.manager = this;
            this.broadcastEvent(inputEvent);
        }
        var downEvent = new enchant.Event(name + this.activeEventNameSuffix);
        this.broadcastEvent(downEvent);
    },
    _up: function(name) {
        var inputEvent;
        if (this.flagStore[name]) {
            this.flagStore[name] = false;
            inputEvent = new enchant.Event((--this.activeInputsNum) ? 'inputchange' : 'inputend');
            inputEvent.manager = this;
            this.broadcastEvent(inputEvent);
        }
        var upEvent = new enchant.Event(name + this.inactiveEventNameSuffix);
        this.broadcastEvent(upEvent);
    }
});
<commit_msg>bugfix about InputManager#addBroadcastTarget<commit_after>/**
 * @scope enchant.InputManager.prototype
 */
enchant.InputManager = enchant.Class.create(enchant.EventTarget, {
    /**
     * @name enchant.InputManager
     * @class
     [lang:ja]
     * 入力を管理するためのクラス.
     * @param {*} flagStore 入力のフラグを保持させるオブジェクト.
     * @param {String} activeEventNameSuffix イベント名の接尾辞.
     * @param {String} inactiveEventNameSuffix イベント名の接尾辞.
     [/lang]
     [lang:en]
     * Class for managing input.
     * @param {*} flagStore object that store input flag.
     * @param {String} activeEventNameSuffix event name suffix.
     * @param {String} inactiveEventNameSuffix event name suffix.
     [/lang]
     * @constructs
     * @extends enchant.EventTarget
     */
    initialize: function(flagStore, activeEventNameSuffix, inactiveEventNameSuffix) {
        enchant.EventTarget.call(this);
        /**
         [lang:ja]
         * アクティブな入力の数.
         [/lang]
         [lang:en]
         * The number of active inputs.
         [/lang]
         * @type {Number}
         */
        this.activeInputsNum = 0;
        /**
         [lang:ja]
         * 入力の変化を通知する対象を保持する配列.
         [/lang]
         [lang:en]
         * Array that store event target.
         [/lang]
         * @type {enchant.EventTarget[]}
         */
        this.broadcastTarget = [];
        /**
         [lang:ja]
         * 入力の状態を真偽値で保持する連想配列.
         [/lang]
         [lang:en]
         * Object that store input flag.
         [/lang]
         * @type {Object}
         */
        this.flagStore = flagStore;
        /**
         [lang:ja]
         * InputManagerが発行するイベント名の接尾辞.
         [/lang]
         [lang:en]
         * event name suffix that dispatched by InputManager.
         [/lang]
         * @type {String}
         */
        this.activeEventNameSuffix = activeEventNameSuffix;
        /**
         [lang:ja]
         * InputManagerが発行するイベント名の接尾辞.
         [/lang]
         [lang:en]
         * event name suffix that dispatched by InputManager.
         [/lang]
         * @type {String}
         */
        this.inactiveEventNameSuffix = inactiveEventNameSuffix;

        this._binds = {};
        this._stateHandler = function(e) {
            var id = e.source.identifier;
            var name = this._binds[id];
            this.changeState(name, e.state);
        }.bind(this);
    },
    /**
     [lang:ja]
     * 入力の変化を通知する対象を追加する.
     [/lang]
     [lang:en]
     * Add event target.
     [/lang]
     * @param {enchant.EventTarget} eventTarget broadcast target.
     */
    addBroadcastTarget: function(eventTarget) {
        this.broadcastTarget.push(eventTarget);
    },
    /**
     [lang:ja]
     * 入力の変化を通知する対象を削除する.
     [/lang]
     [lang:en]
     * Remove event target.
     [/lang]
     * @param {enchant.EventTarget} eventTarget broadcast target.
     */
    removeBroadcastTarget: function(eventTarget) {
        var i = this.broadcastTarget.indexOf(eventTarget);
        if (i !== -1) {
            this.broadcastTarget.splice(i, 1);
        }
    },
    /**
     [lang:ja]
     * イベントを{@link enchant.InputManager#broadcastTarget}に発行する.
     [/lang]
     [lang:en]
     * Dispatch event to {@link enchant.InputManager#broadcastTarget}.
     [/lang]
     * @param {enchant.Event} e event.
     */
    broadcastEvent: function(e) {
        var target = this.broadcastTarget;
        for (var i = 0, l = target.length; i < l; i++) {
            target[i].dispatchEvent(e);
        }
    },
    /**
     [lang:ja]
     * 特定の入力に名前をつける.
     * 入力はフラグとイベントで監視できるようになる.
     [/lang]
     [lang:en]
     * Name specified input.
     * Input can be watched by flag or event.
     [/lang]
     * @param {enchant.InputSource} inputSource input source.
     * @param {String} name input name.
     */
    bind: function(inputSource, name) {
        inputSource.addEventListener(enchant.Event.INPUT_STATE_CHANGED, this._stateHandler);
        this._binds[inputSource.identifier] = name;
        this.flagStore[inputSource.identifier] = false;
    },
    /**
     [lang:ja]
     * 入力のバインドを解除する.
     [/lang]
     [lang:en]
     * Remove binded name.
     [/lang]
     * @param {enchant.InputSource} inputSource input source.
     */
    unbind: function(inputSource) {
        inputSource.removeEventListener(enchant.Event.INPUT_STATE_CHANGED, this._stateHandler);
        delete this._binds[inputSource.identifier];
        delete this.flagStore[inputSource.identifier];
    },
    /**
     [lang:ja]
     * 入力の状態変更を変更する.
     [/lang]
     [lang:en]
     * Change state of input.
     [/lang]
     * @param {String} name input name.
     * @param {Boolean} bool input state.
     */
    changeState: function(name, bool) {
        var inputEvent;
        if (bool) {
            this._down(name);
        } else {
            this._up(name);
        }
    },
    _down: function(name) {
        var inputEvent;
        if (!this.flagStore[name]) {
            this.flagStore[name] = true;
            inputEvent = new enchant.Event((this.activeInputsNum++) ? 'inputchange' : 'inputstart');
            inputEvent.manager = this;
            this.broadcastEvent(inputEvent);
        }
        var downEvent = new enchant.Event(name + this.activeEventNameSuffix);
        this.broadcastEvent(downEvent);
    },
    _up: function(name) {
        var inputEvent;
        if (this.flagStore[name]) {
            this.flagStore[name] = false;
            inputEvent = new enchant.Event((--this.activeInputsNum) ? 'inputchange' : 'inputend');
            inputEvent.manager = this;
            this.broadcastEvent(inputEvent);
        }
        var upEvent = new enchant.Event(name + this.inactiveEventNameSuffix);
        this.broadcastEvent(upEvent);
    }
});
<|endoftext|>