<commit_before>"use strict";

/*global nodeca*/

/*
 * This seed create data for demo forum:
 *   3 category, each category contain 10 forums
 *   first forum contain 200 threads, all others only one
 *   first thread in first thread contain 100 post, all others only one
 *
 */

var NLib = require('nlib');

var _ = NLib.Vendor.Underscore;
var Async = NLib.Vendor.Async;
var Faker = NLib.Vendor.Faker;

var CATEGORY_COUNT = 3;
var FORUM_COUNT  = 10;
var THREAD_COUNT_IN_BIG_FORUM  = 200;
var POST_COUNT_IN_BIG_THREAD  = 100;

var CATEGORY_ID_SHIFT = 3;
var FORUM_ID_SHIFT = CATEGORY_ID_SHIFT + CATEGORY_COUNT;
var THREAD_ID_SHIFT = 2;
var POST_ID_SHIFT = 2;

// extend Faker
// add numeric id generator
Faker.Ids = {
  category_shift: CATEGORY_ID_SHIFT,
  forum_shift: FORUM_ID_SHIFT,
  thread_shift: THREAD_ID_SHIFT,
  post_shift: POST_ID_SHIFT
};

Faker.Ids.next = function(type){
  var last_id_prop_name = type + '_last_id';
  if (!this[last_id_prop_name]) {
    var shift_prop_name = type + '_shift';
    if (!this[shift_prop_name]) {
      this[shift_prop_name] = 0;
    }
    this[last_id_prop_name] = this[shift_prop_name];
  }
  this[last_id_prop_name]++;
  return this[last_id_prop_name];
};

// add helpers for categorys,forums, threads and posts
Faker.Helpers.category = function (){
  return {
    title: Faker.Lorem.words(),
    description: Faker.Lorem.sentence(),

    id: Faker.Ids.next('category'),
    is_category: true
  };
};

Faker.Helpers.forum = function (category){
  return {
    title: Faker.Lorem.words(),
    description: Faker.Lorem.sentence(),

    id: Faker.Ids.next('forum'),

    parent: category._id,
    parent_id: category.id,

    parent_list: [category._id],
    parent_id_list: [category.id]
  };
};

Faker.Helpers.thread = function (forum){
  return {
    title: Faker.Lorem.words(),

    id: Faker.Ids.next('thread'),

    // Stub. This constants should be defined globally
    state:  0,

    forum_id: forum.id,
    forum: forum._id
  };
};

Faker.Helpers.post = function (thread){
  return {
    text: Faker.Lorem.paragraph(),
    fmt:  'txt',

    id: Faker.Ids.next('post'),

    // Stub. This constants should be defined globally
    state: 0,

    thread_id: thread.id,
    thread: thread._id,

    forum_id: thread.forum_id,
    forum: thread.forum._id,

    ts: new Date()
    // ToDo user
  };
};

var Category = nodeca.models.forum.Section;
var Forum    = nodeca.models.forum.Section;
var Thread   = nodeca.models.forum.Thread;
var Post     = nodeca.models.forum.Post;

var is_big_thread = true;
var is_big_forum = true;

var create_post = function(thread, callback) {
  var post = new Post(Faker.Helpers.post(thread));

  post.save(callback);
};

var create_thread = function(forum, callback) {
  var first_post;
  var last_post;
  var post_count;

  if (is_big_thread) {
    is_big_thread = false;
    post_count = POST_COUNT_IN_BIG_THREAD;
  } else{
    post_count = 1;
  }

  var thread = new Thread(Faker.Helpers.thread(forum));

  Async.series([
    function(cb){
      thread.save(cb);
    },
    // create posts
    function(cb){
      Async.forEach(_.range(post_count), function (current_post, next_post) {
        create_post(thread, function(err, post){
          if (!first_post){
            first_post = post;
          }
          last_post = post;
          next_post();
        });
      }, cb);
    },
    // update thread
    function(cb){
      thread.post_count = post_count;

      thread.first_post = first_post._id;
      thread.first_post_id = first_post.id;
      thread.first_ts = first_post.ts;

      thread.last_post = last_post._id;
      thread.last_post_id = last_post.id;
      thread.last_ts = last_post.ts;

      thread.save(cb);
    }
  ], function(err) {
    callback(err, thread);
  });
};

var create_forum = function(category, callback){
  var last_thread;
  var thread_count;

  if (is_big_forum) {
    is_big_forum = false;
    thread_count = THREAD_COUNT_IN_BIG_FORUM;
  } else{
    thread_count = 1;
  }

  var forum = new Forum(Faker.Helpers.forum(category));

  Async.series([
    function(cb){
      forum.save(cb);
    },
    // create threads
    function(cb){
      Async.forEach(_.range(thread_count), function (current_thread, next_thread) {
        create_thread(forum, function(err, thread){
          last_thread = thread;
          next_thread();
        });
      }, cb);
    },
    // update forum dependent info
    function(cb){
      forum.last_thread = last_thread._id;
      forum.last_thread_id = last_thread.id;

      forum.last_post = last_thread.last_post;
      forum.last_post_id = last_thread.last_post_id;
      forum.last_ts = last_thread.last_ts;

      forum.save(cb);
    }
  ], function(err) {
    callback(err, forum);
  });
};

module.exports = function(callback) {
  Async.forEachSeries(_.range(CATEGORY_COUNT), function(current_category, next_category) {
    var forum_list = [];
    var forum_id_list = [];

    var category = new Category(Faker.Helpers.category());

    Async.series([
      function(cb){
        category.save(cb);
      },
      // create forums
      function(cb){
        Async.forEach( _.range(FORUM_COUNT), function (current_forum, next_forum) {
          create_forum(category, function(err, forum){
            forum_list.push(forum._id);
            forum_id_list.push(forum.id);
            next_forum(err);
          });
        }, cb);
      },
      // update parent category dependent info
      function(cb){
        category.child_list = forum_list;
        category.child_id_list = forum_id_list;

        category.save(cb);
      }
    ], next_category);
  }, function(err){
    callback(err);
  });
};
<commit_msg>Fixed demo forum seed<commit_after>"use strict";

/*global nodeca*/

/*
 * This seed create data for demo forum:
 *   3 category, each category contain 10 forums
 *   first forum contain 200 threads, all others only one
 *   first thread in first thread contain 100 post, all others only one
 *
 */

var NLib = require('nlib');

var _ = NLib.Vendor.Underscore;
var Async = NLib.Vendor.Async;
var Faker = NLib.Vendor.Faker;

var CATEGORY_COUNT = 3;
var FORUM_COUNT  = 10;
var THREAD_COUNT_IN_BIG_FORUM  = 200;
var POST_COUNT_IN_BIG_THREAD  = 100;

var CATEGORY_ID_SHIFT = 3;
var FORUM_ID_SHIFT = CATEGORY_ID_SHIFT + CATEGORY_COUNT;
var THREAD_ID_SHIFT = 2;
var POST_ID_SHIFT = 2;

// extend Faker
// add numeric id generator
Faker.Ids = {
  category_shift: CATEGORY_ID_SHIFT,
  forum_shift: FORUM_ID_SHIFT,
  thread_shift: THREAD_ID_SHIFT,
  post_shift: POST_ID_SHIFT
};

Faker.Ids.next = function(type){
  var last_id_prop_name = type + '_last_id';
  if (!this[last_id_prop_name]) {
    var shift_prop_name = type + '_shift';
    if (!this[shift_prop_name]) {
      this[shift_prop_name] = 0;
    }
    this[last_id_prop_name] = this[shift_prop_name];
  }
  this[last_id_prop_name]++;
  return this[last_id_prop_name];
};

function capitalize(str) {
  return str.charAt(0).toUpperCase() + str.slice(1);
}

// add helpers for categorys,forums, threads and posts
Faker.Helpers.category = function (){
  return {
    title: capitalize(Faker.Lorem.sentence()),
    description: capitalize(Faker.Lorem.sentence()),

    id: Faker.Ids.next('category'),
    is_category: true
  };
};

Faker.Helpers.forum = function (category){
  return {
    title: capitalize(Faker.Lorem.sentence()),
    description: capitalize(Faker.Lorem.sentence()),

    id: Faker.Ids.next('forum'),

    parent: category._id,
    parent_id: category.id,

    parent_list: [category._id],
    parent_id_list: [category.id]
  };
};

Faker.Helpers.thread = function (forum){
  return {
    title: capitalize(Faker.Lorem.sentence()),

    id: Faker.Ids.next('thread'),

    // Stub. This constants should be defined globally
    state:  0,

    forum_id: forum.id,
    forum: forum._id
  };
};

Faker.Helpers.post = function (thread){
  return {
    text: capitalize(Faker.Lorem.paragraph()),
    fmt:  'txt',

    id: Faker.Ids.next('post'),

    // Stub. This constants should be defined globally
    state: 0,

    thread_id: thread.id,
    thread: thread._id,

    forum_id: thread.forum_id,
    forum: thread.forum._id,

    ts: new Date()
    // ToDo user
  };
};

var Category = nodeca.models.forum.Section;
var Forum    = nodeca.models.forum.Section;
var Thread   = nodeca.models.forum.Thread;
var Post     = nodeca.models.forum.Post;

var is_big_thread = true;
var is_big_forum = true;

var create_post = function(thread, callback) {
  var post = new Post(Faker.Helpers.post(thread));

  post.save(callback);
};

var create_thread = function(forum, callback) {
  var first_post;
  var last_post;
  var post_count;

  if (is_big_thread) {
    is_big_thread = false;
    post_count = POST_COUNT_IN_BIG_THREAD;
  } else{
    post_count = 1;
  }

  var thread = new Thread(Faker.Helpers.thread(forum));

  Async.series([
    function(cb){
      thread.save(cb);
    },
    // create posts
    function(cb){
      Async.forEach(_.range(post_count), function (current_post, next_post) {
        create_post(thread, function(err, post){
          if (!first_post){
            first_post = post;
          }
          last_post = post;
          next_post();
        });
      }, cb);
    },
    // update thread
    function(cb){
      thread.post_count = post_count;

      thread.first_post = first_post._id;
      thread.first_post_id = first_post.id;
      thread.first_ts = first_post.ts;

      thread.last_post = last_post._id;
      thread.last_post_id = last_post.id;
      thread.last_ts = last_post.ts;

      thread.save(cb);
    }
  ], function(err) {
    callback(err, thread);
  });
};

var create_forum = function(category, callback){
  var last_thread;
  var thread_count;

  if (is_big_forum) {
    is_big_forum = false;
    thread_count = THREAD_COUNT_IN_BIG_FORUM;
  } else{
    thread_count = 1;
  }

  var forum = new Forum(Faker.Helpers.forum(category));

  Async.series([
    function(cb){
      forum.save(cb);
    },
    // create threads
    function(cb){
      Async.forEach(_.range(thread_count), function (current_thread, next_thread) {
        create_thread(forum, function(err, thread){
          last_thread = thread;
          next_thread();
        });
      }, cb);
    },
    // update forum dependent info
    function(cb){
      forum.last_thread = last_thread._id;
      forum.last_thread_id = last_thread.id;

      forum.last_post = last_thread.last_post;
      forum.last_post_id = last_thread.last_post_id;
      forum.last_ts = last_thread.last_ts;

      forum.save(cb);
    }
  ], function(err) {
    callback(err, forum);
  });
};

module.exports = function(callback) {
  Async.forEachSeries(_.range(CATEGORY_COUNT), function(current_category, next_category) {
    var forum_list = [];
    var forum_id_list = [];

    var category = new Category(Faker.Helpers.category());

    Async.series([
      function(cb){
        category.save(cb);
      },
      // create forums
      function(cb){
        Async.forEach( _.range(FORUM_COUNT), function (current_forum, next_forum) {
          create_forum(category, function(err, forum){
            forum_list.push(forum._id);
            forum_id_list.push(forum.id);
            next_forum(err);
          });
        }, cb);
      },
      // update parent category dependent info
      function(cb){
        category.child_list = forum_list;
        category.child_id_list = forum_id_list;

        category.save(cb);
      }
    ], next_category);
  }, function(err){
    callback(err);
  });
};
<|endoftext|>


<commit_before>// @flow
import * as Tabs from '../../constants/tabs'
import React from 'react'
import flags from '../../util/feature-flags'
import {Box} from '../../common-adapters'
import {TabBarButton} from '../../common-adapters/tab-bar'
import {globalStyles, globalColors} from '../../styles'

import type {Props} from './index.render'

const _icons = {
  [Tabs.chatTab]: {selected: 'icon-nav-chat-selected-32', unselected: 'icon-nav-chat-32'},
  [Tabs.devicesTab]: {selected: 'icon-nav-devices-selected-32', unselected: 'icon-nav-devices-32'},
  [Tabs.folderTab]: {selected: 'icon-nav-folders-selected-32', unselected: 'icon-nav-folders-32'},
  [Tabs.peopleTab]: {selected: 'icon-nav-people-selected-32', unselected: 'icon-nav-people-32'},
  [Tabs.searchTab]: {selected: 'icon-nav-people-selected-32', unselected: 'icon-nav-people-32'},
  [Tabs.settingsTab]: {selected: 'icon-nav-settings-selected-32', unselected: 'icon-nav-settings-32'},
}

const _labels = {
  [Tabs.chatTab]: 'Chat',
  [Tabs.devicesTab]: 'Devices',
  [Tabs.folderTab]: 'Folders',
  [Tabs.peopleTab]: 'People',
  [Tabs.searchTab]: 'Search',
  [Tabs.settingsTab]: 'Settings',
}

const _tabs = [
  ...(flags.tabPeopleEnabled ? [Tabs.peopleTab] : []),
  Tabs.folderTab,
  Tabs.chatTab,
  Tabs.devicesTab,
  Tabs.settingsTab,
].filter(Boolean)

const TabBar = ({onTabClick, selectedTab, username, badgeNumbers}: Props) => (
  <Box style={stylesTabBar}>
    {_tabs.map(tab => (
      <TabBarButton
        className="keybase-nav"
        badgeNumber={badgeNumbers[tab]}
        isNav={true}
        key={tab}
        label={_labels[tab]}
        onClick={() => onTabClick(tab)}
        selected={selectedTab === tab}
        source={{icon: _icons[tab][selectedTab === tab ? 'selected' : 'unselected'], type: 'nav'}}
        style={stylesTabButton}
      />
    ))}
    <Box style={{flex: 1}} />
    <TabBarButton
      label={username}
      isNav={true}
      selected={selectedTab === Tabs.profileTab}
      onClick={() => onTabClick(Tabs.profileTab)}
      badgeNumber={badgeNumbers[Tabs.profileTab]}
      source={{type: 'avatar', username}}
      style={stylesTabButton}
    />
  </Box>
)

const stylesTabBar = {
  ...globalStyles.flexBoxColumn,
  backgroundColor: globalColors.darkBlue2,
  justifyContent: 'flex-start',
  paddingTop: 15,
  paddingBottom: 15,
  width: 80,
}

const stylesTabButton = {
  height: 56,
}

export default TabBar
<commit_msg>Desktop nav: have subroutes of Profile show up as selecting the People tab<commit_after>// @flow
import * as Tabs from '../../constants/tabs'
import React from 'react'
import flags from '../../util/feature-flags'
import {Box} from '../../common-adapters'
import {TabBarButton} from '../../common-adapters/tab-bar'
import {globalStyles, globalColors} from '../../styles'

import type {Props} from './index.render'

const _icons = {
  [Tabs.chatTab]: {selected: 'icon-nav-chat-selected-32', unselected: 'icon-nav-chat-32'},
  [Tabs.devicesTab]: {selected: 'icon-nav-devices-selected-32', unselected: 'icon-nav-devices-32'},
  [Tabs.folderTab]: {selected: 'icon-nav-folders-selected-32', unselected: 'icon-nav-folders-32'},
  [Tabs.peopleTab]: {selected: 'icon-nav-people-selected-32', unselected: 'icon-nav-people-32'},
  [Tabs.profileTab]: {selected: 'icon-nav-people-selected-32', unselected: 'icon-nav-people-32'},
  [Tabs.searchTab]: {selected: 'icon-nav-people-selected-32', unselected: 'icon-nav-people-32'},
  [Tabs.settingsTab]: {selected: 'icon-nav-settings-selected-32', unselected: 'icon-nav-settings-32'},
}

const _labels = {
  [Tabs.chatTab]: 'Chat',
  [Tabs.devicesTab]: 'Devices',
  [Tabs.folderTab]: 'Folders',
  [Tabs.peopleTab]: 'People',
  [Tabs.profileTab]: 'People',
  [Tabs.searchTab]: 'Search',
  [Tabs.settingsTab]: 'Settings',
}

const _tabs = [
  ...(flags.tabPeopleEnabled ? [Tabs.profileTab] : []),
  Tabs.folderTab,
  Tabs.chatTab,
  Tabs.devicesTab,
  Tabs.settingsTab,
].filter(Boolean)

const iconForTab = (tab, selectedTab) => {
  const icon = tab === Tabs.profileTab
    ? _icons[Tabs.peopleTab][selectedTab === tab ? 'selected' : 'unselected']
    : _icons[tab][selectedTab === tab ? 'selected' : 'unselected']
  return {
    icon,
    type: 'nav',
  }
}

const TabBar = ({onTabClick, selectedTab, username, badgeNumbers}: Props) => (
  <Box style={stylesTabBar}>
    {_tabs.map(tab => (
      <TabBarButton
        className="keybase-nav"
        badgeNumber={badgeNumbers[tab]}
        isNav={true}
        key={tab}
        label={_labels[tab]}
        onClick={() => onTabClick(tab)}
        selected={selectedTab === tab}
        source={iconForTab(tab, selectedTab)}
        style={stylesTabButton}
      />
    ))}
    <Box style={{flex: 1}} />
    <TabBarButton
      label={username}
      isNav={true}
      selected={selectedTab === Tabs.peopleTab}
      onClick={() => onTabClick(Tabs.peopleTab)}
      badgeNumber={badgeNumbers[Tabs.peopleTab]}
      source={{type: 'avatar', username}}
      style={stylesTabButton}
    />
  </Box>
)

const stylesTabBar = {
  ...globalStyles.flexBoxColumn,
  backgroundColor: globalColors.darkBlue2,
  justifyContent: 'flex-start',
  paddingTop: 15,
  paddingBottom: 15,
  width: 80,
}

const stylesTabButton = {
  height: 56,
}

export default TabBar
<|endoftext|>


<commit_before>define([
    './admin-user',
    './map-load',
    './main-controller',
    './show-problem',
    './add-problem',
    './socket',
    './resourcesCtrl',
    './editorCtrl',
    './socket-user',
    './not-approved',
    './slider-controller',
    './register',
    './stats',
    './datepicker',
    './map-controller',
    './change-password'
], function () {});
<commit_msg>Update index.js<commit_after>define([
    './admin-user',
    './map-load',
    './main-controller',
    './show-problem',
    './add-problem',
    './socket',
    './resourcesCtrl',
    './editorCtrl',
    './socket-user',
    './not-approved',
    './slider-controller',
    './register',
    './stats',
    './datepicker',
    './change-password'
], function () {});
<|endoftext|>


<commit_before>/* canvas course group javascript */

$(document).ready(function() {

    if (window.course_groups.hasOwnProperty('validation_error')) {
        return;
    }

    // prep for api post/put
    var csrfSafeMethod = function(method) {
        // these HTTP methods do not require CSRF protection
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    };

    $.ajaxSetup({
        crossDomain: false, // obviates need for sameOrigin test
        beforeSend: function(xhr, settings) {
            if (window.course_groups.session_id) {
                xhr.setRequestHeader("X-SessionId", window.course_groups.session_id);
            }
            if (!csrfSafeMethod(settings.type)) {
                xhr.setRequestHeader("X-CSRFToken", window.course_groups.csrftoken);
            }
        }
    });

    var groupDataFromJSON = function (group) {
        var when,
            is_provisioned,
            in_process = false;

        if (group.provisioned_date && group.provisioned_date.length) {
            is_provisioned = true;
            when = group.provisioned_date;
        } else {
            is_provisioned = false;
            when = group.added_date;
        }

        if (group.queue_id && group.queue_id.length) {
            in_process = true;
        }

        return {
            id: group.id,
            group_id: group.group_id,
            course_id: group.course_id,
            role: group.role,
            added_by: group.added_by,
            priority: group.priority,
            when: when ? $.datepicker.formatDate('MM d, yy', new Date(when)) : null,
            is_provisioned: is_provisioned,
            in_process: in_process
        };
    };

    var newGroupInput = function () {
        var tpl = Handlebars.compile($('#new-group-item').html()),
            e = $(tpl({group_id: '', roles: window.course_groups.roles})),
            input = $('input', e),
            typeahead;

        $('select', e).change(lightSaveButton);

        input.attr('typeahead', 'off');
        typeahead = input.typeahead({
            minLength: 4,
            items: 50,
            source: function (query, process) {
                return $.get('api/v1/uw/group/',
                             {
                                 name: query
                             },
                             function (data) {
                                 var matches = [],
                                     i;

                                 for (i in data.groups) {
                                     matches.push(data.groups[i].name);
                                 }

                                 return process(matches);
                             });
            },
            updater: function (item) {
                this.$element.focus();
                return item;
            }
        });

        input.keyup(function (evt) {
            var group = tidyGroupId($(this).val()),
                l = (group.match(/^cou/) !== null) ? 17 :
                    (group.match(/^uw_/) !== null) ? 5 : 4;

            validateGroupInput.call(this, group);
            typeahead.data('typeahead').options.minLength = l;
        });

        input.focus(clearEmptyGroupName);
        input.blur(validateGroupName);

        $('div.new-group-list > ul').append(e);
        setEmptyGroupName.call(input);
    };

    var tidyGroupId = function (group_id) {
        return group_id.replace(/(^\s*)|(\s*$)/gi, "").toLowerCase();
    };

    var setEmptyGroupName = function () {
        var input = $(this),
            div = input.parent();

        if (tidyGroupId(input.val()).length < 1) {
            input.val('type or paste UW Group ID');
            div.addClass('no-value');
        }
    };

    var clearEmptyGroupName = function () {
        var input = $(this),
            div = input.parent();

        if (div.hasClass('no-value')) {
            div.removeClass('no-value');
            input.val('');
        }
    };

    var validGroupName = function (group) {
        return (group.match(/^[A-Za-z0-9\-\.\_]+$/) !== null);
    };

    var validateGroupName = function () {
        var group,
            div,
            span;

        if ($(this).next('ul.typeahead').is(":visible")) {
            return;
        }

        group = tidyGroupId($(this).val());
        div = $(this).parent();
        span = $('> span', div);

        // look like a reasonable group?
        validateGroupInput.call(this);

        if (group.length) {
            if (!div.hasClass('invalid')) {
                var me = this,
                    i;

                $.ajax({
                    type: 'GET',
                    url: 'api/v1/uw/group/' + group + '/membership',
                    async: false
                }).done(function(data) {
                    validateGroupMembers(group, data.invalid, warnBadNewGroupMembers);
                }).fail(function (xhr, textStatus, errorThrown) {
                    var errstr;

                    try {
                        if (xhr.status == 401) {
                            errstr = warnPermissionDenied();
                        } else{
                            errstr = $.parseJSON(xhr.responseText).error;
                        }
                    } catch (e) {
                        errstr = xhr.responseText;
                    }

                    setGroupInputValidity.call(me, errstr);
                });
            }
        } else {
            setEmptyGroupName.call(this);
        }
    };

    var validateGroupMembers = function (group, invalid, warning) {
        var exceptions = [],
            member,
            i;

        for (i in invalid) {
            exceptions.push({ member: invalid[i] });
        }

        if (exceptions.length) {
            return warning.call(this, group, exceptions);
        }

        return null;
    };

    var warnBadExistingGroupMembers = function (group, exceptions) {
        var tpl = Handlebars.compile($('#group-member-exceptions').html());

        return tpl({
            count: exceptions.length,
            plural: (exceptions.length > 1) ? 's' : '',
            members: exceptions
        });
    };

    var warnBadNewGroupMembers = function (group, exceptions) {
        window.course_groups.member_exceptions[group] = {
            group: group,
            count: exceptions.length,
            plural: (exceptions.length > 1) ? 's' : '',
            members: exceptions
        };
    };

    var warnPermissionDenied = function (group, exceptions) {
        var tpl = Handlebars.compile($('#permission-denied-exception').html());

        return tpl({
            group: group
        });
    };

    var validateGroupInput = function () {
        var group = tidyGroupId($(this).val());

        clearGroupInputValidity.call(this);
        if (group.length > 0) {
            if (!validGroupName(group)) {
                setGroupInputValidity.call(this, 'Invalid character in UW Group name');
            }
        }

        lightSaveButton();
    };

    var setGroupInputValidity = function (errstr) {
        var parent;

        if (errstr && errstr.length) {
            parent = $(this).parent();
            parent.addClass('invalid');
            $('> span', parent).html(errstr);
        }
    };

    var clearGroupInputValidity = function () {
        var div = $(this).parent();

        if (div.hasClass('valid') || div.hasClass('invalid') ||
                div.hasClass('warning') || div.hasClass('loading')) {
            $('> span', div).remove();
            div.removeClass('valid invalid warning loading');
            div.append('');
        }
    };

    var lightSaveButton = function () {
        var existing = ($('div.existing-groups table tr').length > 1),
            valid = ($('div.new-group-list .invalid').length === 0),
            enable = ($('div.existing-groups .is-deleted').length > 0),
            button = $('button');

        if (enable) {
            button.prev('p').show();
        } else {
            button.prev('p').hide();
        }

        $('div.new-group-list > ul > li').each(function (i, e) {
            if (!$('div', e).hasClass('no-value') &&
                    tidyGroupId($('input', e).val()).length > 0) {
                if ($('option:selected', e).val().length > 0) {
                    enable = true;
                } else {
                    valid = false;
                }
            }
        });

        //button.html('Save ' + ((existing) ? ' changes' : 'all groups to Canvas'));
        button.html('Save');

        if (enable && valid) {
            button.removeAttr('disabled');
        } else {
            button.attr('disabled', 'disabled');
        }
    };

    var submitGroupChanges = function () {
        var failures = [];

        // add groups
        $('div.new-group-list > ul > li').each(function(i, e) {
            var group_id = $('input', e).val(),
                role = $('option:selected', e).val();

            if (role.length > 0 && group_id.length > 0) {
                $.ajax({
                    type: 'POST',
                    url: 'api/v1/group/',
                    async: false,
                    processData: false,
                    contentType: 'application/json',
                    data: '{ "course_id": "' +
                        window.course_groups.sis_course_id +
                        '", "canvas_id": "' +
                        window.course_groups.canvas_course_id +
                        '", "group_id": "' + group_id +
                        '", "role": "' + role + '" }'
                }).fail(function (xhr, textStatus, errorThrown) {
                    try {
                        failures.push($.parseJSON(xhr.responseText).error);
                    } catch (e) {
                        failures.push(xhr.responseText);
                    }
                });
            }
        });

        // delete groups
        $('div.existing-groups table tr.is-deleted').each(function(i, e) {
            $.ajax({
                type: 'DELETE',
                url: 'api/v1/group/' + $('input#group-model-id', e).val(),
                async: false
            }).fail(function (xhr, textStatus, errorThrown) {
                try {
                    failures.push($.parseJSON(xhr.responseText).error);
                } catch (e) {
                    failures.push(xhr.responseText);
                }
            });
        });

        if (failures.length > 0) {
            var bod = '
',
                fail;

            for (fail in failures) {
                bod += failures[fail];
            }

            bod += '
';

            $('#closing-failure .modal-body div').html(bod);

            $('#closing-failure').modal();

            return false;
        }

        return true;
    };

    $(window).on('beforeunload', function(){
        if ($('button').attr('disabled') !== 'disabled') {
            return $('#beforeunload-warning').html();
        }

        return null;
    });

    $('#closing-success .modal-footer > a').click(function () {
        loadExistingGroups();
        initializeNewGroups();
        lightSaveButton();
    });

    $('#closing-success .modal-footer > a + a').click(function () {
        $(window).off('beforeunload');
        top.location =  window.course_groups.launch_presentation_return_url;
    });

    $('button').click(function () {
        var exceptions = window.course_groups.member_exceptions,
            ex = [],
            tpl,
            i;

        $('div.new-group-list > ul > li').each(function(i, e) {
            var group_id = tidyGroupId($('input', e).val());

            if (exceptions.hasOwnProperty(group_id)) {
                ex.push(exceptions[group_id]);
            }
        });

        if (ex.length) {
            tpl = Handlebars.compile($('#closing-modal-exceptions').html());
            $('#closing-success .modal-body div').html(tpl({
                exceptions: ex
            }));
        } else {
            $('#closing-success .modal-body div').html('');
        }

        if (submitGroupChanges()) {
            $('#closing-success').modal();
        }
    });

    var loadCourseRoles = function (account_id) {
        $.ajax({
            type: 'GET',
            dataType: 'json',
            url: 'api/v1/account/' + account_id + '/course_roles',
        }).done(function (data) {
            window.course_groups.roles = data.roles;
            newGroupInput();
            $('div.new-group-list a').click(newGroupInput).show();
        }).fail(function (msg) {
            $('div.new-group-list').html('Error loading course roles: ' + msg);
        }).always(function () {
            $('.loading_roles').hide();
        });
    };

    var initializeNewGroups = function () {
        window.course_groups.member_exceptions = {};
        $('div.new-group-list ul').html('');

        if (!window.course_groups.roles.length) {
            loadCourseRoles(window.course_groups.canvas_account_id);
        } else {
            newGroupInput();
        }
    };

    var loadExistingGroups = function () {
        // clear table
        $('div.existing-groups table').find('tr:gt(0)').remove();

        $.ajax({
            url: 'api/v1/group/?course_id=' +
                encodeURIComponent(window.course_groups.sis_course_id),
            dataType: 'json',
            success: function (data) {
                var tpl = Handlebars.compile($('#existing-group').html()),
                    table = $('div.existing-groups table');

                if (data.hasOwnProperty('groups') && data.groups.length) {
                    $.each(data.groups, function (i) {
                        var j = groupDataFromJSON(data.groups[i]),
                            e = $(tpl(j)),
                            del_link = $('span.group-delete', e),
                            undel_link = $('span.group-undelete', e);

                        table.append(e);

                        $('span.group-delete a', e).click(function (evt) {
                            $(evt.target).closest('tr').addClass('is-deleted');
                            del_link.hide();
                            undel_link.show();
                            lightSaveButton();
                        });

                        $('span.group-undelete a', e).click(function (evt) {
                            $(evt.target).closest('tr').removeClass('is-deleted');
                            del_link.show();
                            undel_link.hide();
                            lightSaveButton();
                        });

                        $(e).hover(function (evt) {
                            if ($(evt.target).closest('tr').hasClass('is-deleted')) {
                                del_link.hide();
                            } else {
                                del_link.show();
                            }
                        }, function (evt) {
                            del_link.hide();
                        });

                        // validate membership
                        $.ajax({
                            type: 'GET',
                            url: 'api/v1/uw/group/' + j.id + '/membership',
                            success: function (data) {
                                var content = validateGroupMembers(
                                        j.group_id, data.invalid,
                                        warnBadExistingGroupMembers),
                                    span;

                                if (content) {
                                    span = $('');
                                    span.popover({
                                        'content': content,
                                        'html': true,
                                        'placement': 'right',
                                        'trigger': 'hover',
                                        'delay': 0
                                    });
                                    $('td:first', e).append(span);
                                }
                            },
                            error: function (xhr, textStatus, errorThrown) {
                                var errstr,
                                    span;

                                try {
                                    errstr = $.parseJSON(xhr.responseText).error;
                                } catch (e) {
                                    errstr = 'Error: ' + xhr.responseText;
                                }

                                span = $('');
                                span.popover({
                                    'content': errstr,
                                    'html': true,
                                    'placement': 'right',
                                    'trigger': 'hover',
                                    'delay': 0
                                });
                                $('td:first', e).append(span);
                            }
                        });
                    });
                    $('div.existing-groups').show();
                } else {
                    $('div.existing-groups').hide();
                }

            },
            error: function (xhr, textStatus, errorThrown) {
                var json;
                try {
                    json = $.parseJSON(xhr.responseText);
                    // console.log('Group Search Error:' + json.error);
                } catch (e) {
                    // console.log('Unknown error: ' + xhr.responseText);
                }
            }
        });
    };

    // init existing groups
    loadExistingGroups();

    // init new group list
    initializeNewGroups();
});
<commit_msg>fix api urls<commit_after>/* canvas course group javascript */

$(document).ready(function() {

    if (window.course_groups.hasOwnProperty('validation_error')) {
        return;
    }

    // prep for api post/put
    var csrfSafeMethod = function(method) {
        // these HTTP methods do not require CSRF protection
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    };

    $.ajaxSetup({
        crossDomain: false, // obviates need for sameOrigin test
        beforeSend: function(xhr, settings) {
            if (window.course_groups.session_id) {
                xhr.setRequestHeader("X-SessionId", window.course_groups.session_id);
            }
            if (!csrfSafeMethod(settings.type)) {
                xhr.setRequestHeader("X-CSRFToken", window.course_groups.csrftoken);
            }
        }
    });

    var groupDataFromJSON = function (group) {
        var when,
            is_provisioned,
            in_process = false;

        if (group.provisioned_date && group.provisioned_date.length) {
            is_provisioned = true;
            when = group.provisioned_date;
        } else {
            is_provisioned = false;
            when = group.added_date;
        }

        if (group.queue_id && group.queue_id.length) {
            in_process = true;
        }

        return {
            id: group.id,
            group_id: group.group_id,
            course_id: group.course_id,
            role: group.role,
            added_by: group.added_by,
            priority: group.priority,
            when: when ? $.datepicker.formatDate('MM d, yy', new Date(when)) : null,
            is_provisioned: is_provisioned,
            in_process: in_process
        };
    };

    var newGroupInput = function () {
        var tpl = Handlebars.compile($('#new-group-item').html()),
            e = $(tpl({group_id: '', roles: window.course_groups.roles})),
            input = $('input', e),
            typeahead;

        $('select', e).change(lightSaveButton);

        input.attr('typeahead', 'off');
        typeahead = input.typeahead({
            minLength: 4,
            items: 50,
            source: function (query, process) {
                return $.get('api/v1/uwgroup/',
                             {
                                 name: query
                             },
                             function (data) {
                                 var matches = [],
                                     i;

                                 for (i in data.groups) {
                                     matches.push(data.groups[i].name);
                                 }

                                 return process(matches);
                             });
            },
            updater: function (item) {
                this.$element.focus();
                return item;
            }
        });

        input.keyup(function (evt) {
            var group = tidyGroupId($(this).val()),
                l = (group.match(/^cou/) !== null) ? 17 :
                    (group.match(/^uw_/) !== null) ? 5 : 4;

            validateGroupInput.call(this, group);
            typeahead.data('typeahead').options.minLength = l;
        });

        input.focus(clearEmptyGroupName);
        input.blur(validateGroupName);

        $('div.new-group-list > ul').append(e);
        setEmptyGroupName.call(input);
    };

    var tidyGroupId = function (group_id) {
        return group_id.replace(/(^\s*)|(\s*$)/gi, "").toLowerCase();
    };

    var setEmptyGroupName = function () {
        var input = $(this),
            div = input.parent();

        if (tidyGroupId(input.val()).length < 1) {
            input.val('type or paste UW Group ID');
            div.addClass('no-value');
        }
    };

    var clearEmptyGroupName = function () {
        var input = $(this),
            div = input.parent();

        if (div.hasClass('no-value')) {
            div.removeClass('no-value');
            input.val('');
        }
    };

    var validGroupName = function (group) {
        return (group.match(/^[A-Za-z0-9\-\.\_]+$/) !== null);
    };

    var validateGroupName = function () {
        var group,
            div,
            span;

        if ($(this).next('ul.typeahead').is(":visible")) {
            return;
        }

        group = tidyGroupId($(this).val());
        div = $(this).parent();
        span = $('> span', div);

        // look like a reasonable group?
        validateGroupInput.call(this);

        if (group.length) {
            if (!div.hasClass('invalid')) {
                var me = this,
                    i;

                $.ajax({
                    type: 'GET',
                    url: 'api/v1/uwgroup/' + group + '/members',
                    async: false
                }).done(function(data) {
                    validateGroupMembers(group, data.invalid, warnBadNewGroupMembers);
                }).fail(function (xhr, textStatus, errorThrown) {
                    var errstr;

                    try {
                        if (xhr.status == 401) {
                            errstr = warnPermissionDenied();
                        } else{
                            errstr = $.parseJSON(xhr.responseText).error;
                        }
                    } catch (e) {
                        errstr = xhr.responseText;
                    }

                    setGroupInputValidity.call(me, errstr);
                });
            }
        } else {
            setEmptyGroupName.call(this);
        }
    };

    var validateGroupMembers = function (group, invalid, warning) {
        var exceptions = [],
            member,
            i;

        for (i in invalid) {
            exceptions.push({ member: invalid[i] });
        }

        if (exceptions.length) {
            return warning.call(this, group, exceptions);
        }

        return null;
    };

    var warnBadExistingGroupMembers = function (group, exceptions) {
        var tpl = Handlebars.compile($('#group-member-exceptions').html());

        return tpl({
            count: exceptions.length,
            plural: (exceptions.length > 1) ? 's' : '',
            members: exceptions
        });
    };

    var warnBadNewGroupMembers = function (group, exceptions) {
        window.course_groups.member_exceptions[group] = {
            group: group,
            count: exceptions.length,
            plural: (exceptions.length > 1) ? 's' : '',
            members: exceptions
        };
    };

    var warnPermissionDenied = function (group, exceptions) {
        var tpl = Handlebars.compile($('#permission-denied-exception').html());

        return tpl({
            group: group
        });
    };

    var validateGroupInput = function () {
        var group = tidyGroupId($(this).val());

        clearGroupInputValidity.call(this);
        if (group.length > 0) {
            if (!validGroupName(group)) {
                setGroupInputValidity.call(this, 'Invalid character in UW Group name');
            }
        }

        lightSaveButton();
    };

    var setGroupInputValidity = function (errstr) {
        var parent;

        if (errstr && errstr.length) {
            parent = $(this).parent();
            parent.addClass('invalid');
            $('> span', parent).html(errstr);
        }
    };

    var clearGroupInputValidity = function () {
        var div = $(this).parent();

        if (div.hasClass('valid') || div.hasClass('invalid') ||
                div.hasClass('warning') || div.hasClass('loading')) {
            $('> span', div).remove();
            div.removeClass('valid invalid warning loading');
            div.append('');
        }
    };

    var lightSaveButton = function () {
        var existing = ($('div.existing-groups table tr').length > 1),
            valid = ($('div.new-group-list .invalid').length === 0),
            enable = ($('div.existing-groups .is-deleted').length > 0),
            button = $('button');

        if (enable) {
            button.prev('p').show();
        } else {
            button.prev('p').hide();
        }

        $('div.new-group-list > ul > li').each(function (i, e) {
            if (!$('div', e).hasClass('no-value') &&
                    tidyGroupId($('input', e).val()).length > 0) {
                if ($('option:selected', e).val().length > 0) {
                    enable = true;
                } else {
                    valid = false;
                }
            }
        });

        //button.html('Save ' + ((existing) ? ' changes' : 'all groups to Canvas'));
        button.html('Save');

        if (enable && valid) {
            button.removeAttr('disabled');
        } else {
            button.attr('disabled', 'disabled');
        }
    };

    var submitGroupChanges = function () {
        var failures = [];

        // add groups
        $('div.new-group-list > ul > li').each(function(i, e) {
            var group_id = $('input', e).val(),
                role = $('option:selected', e).val();

            if (role.length > 0 && group_id.length > 0) {
                $.ajax({
                    type: 'POST',
                    url: 'api/v1/group/',
                    async: false,
                    processData: false,
                    contentType: 'application/json',
                    data: '{ "course_id": "' +
                        window.course_groups.sis_course_id +
                        '", "canvas_id": "' +
                        window.course_groups.canvas_course_id +
                        '", "group_id": "' + group_id +
                        '", "role": "' + role + '" }'
                }).fail(function (xhr, textStatus, errorThrown) {
                    try {
                        failures.push($.parseJSON(xhr.responseText).error);
                    } catch (e) {
                        failures.push(xhr.responseText);
                    }
                });
            }
        });

        // delete groups
        $('div.existing-groups table tr.is-deleted').each(function(i, e) {
            $.ajax({
                type: 'DELETE',
                url: 'api/v1/group/' + $('input#group-model-id', e).val(),
                async: false
            }).fail(function (xhr, textStatus, errorThrown) {
                try {
                    failures.push($.parseJSON(xhr.responseText).error);
                } catch (e) {
                    failures.push(xhr.responseText);
                }
            });
        });

        if (failures.length > 0) {
            var bod = '
',
                fail;

            for (fail in failures) {
                bod += failures[fail];
            }

            bod += '
';

            $('#closing-failure .modal-body div').html(bod);

            $('#closing-failure').modal();

            return false;
        }

        return true;
    };

    $(window).on('beforeunload', function(){
        if ($('button').attr('disabled') !== 'disabled') {
            return $('#beforeunload-warning').html();
        }

        return null;
    });

    $('#closing-success .modal-footer > a').click(function () {
        loadExistingGroups();
        initializeNewGroups();
        lightSaveButton();
    });

    $('#closing-success .modal-footer > a + a').click(function () {
        $(window).off('beforeunload');
        top.location =  window.course_groups.launch_presentation_return_url;
    });

    $('button').click(function () {
        var exceptions = window.course_groups.member_exceptions,
            ex = [],
            tpl,
            i;

        $('div.new-group-list > ul > li').each(function(i, e) {
            var group_id = tidyGroupId($('input', e).val());

            if (exceptions.hasOwnProperty(group_id)) {
                ex.push(exceptions[group_id]);
            }
        });

        if (ex.length) {
            tpl = Handlebars.compile($('#closing-modal-exceptions').html());
            $('#closing-success .modal-body div').html(tpl({
                exceptions: ex
            }));
        } else {
            $('#closing-success .modal-body div').html('');
        }

        if (submitGroupChanges()) {
            $('#closing-success').modal();
        }
    });

    var loadCourseRoles = function (account_id) {
        $.ajax({
            type: 'GET',
            dataType: 'json',
            url: 'api/v1/course-roles',
        }).done(function (data) {
            window.course_groups.roles = data.roles;
            newGroupInput();
            $('div.new-group-list a').click(newGroupInput).show();
        }).fail(function (msg) {
            $('div.new-group-list').html('Error loading course roles: ' + msg);
        }).always(function () {
            $('.loading_roles').hide();
        });
    };

    var initializeNewGroups = function () {
        window.course_groups.member_exceptions = {};
        $('div.new-group-list ul').html('');

        if (!window.course_groups.roles.length) {
            loadCourseRoles(window.course_groups.canvas_account_id);
        } else {
            newGroupInput();
        }
    };

    var loadExistingGroups = function () {
        // clear table
        $('div.existing-groups table').find('tr:gt(0)').remove();

        $.ajax({
            url: 'api/v1/group/?course_id=' +
                encodeURIComponent(window.course_groups.sis_course_id),
            dataType: 'json',
            success: function (data) {
                var tpl = Handlebars.compile($('#existing-group').html()),
                    table = $('div.existing-groups table');

                if (data.hasOwnProperty('groups') && data.groups.length) {
                    $.each(data.groups, function (i) {
                        var j = groupDataFromJSON(data.groups[i]),
                            e = $(tpl(j)),
                            del_link = $('span.group-delete', e),
                            undel_link = $('span.group-undelete', e);

                        table.append(e);

                        $('span.group-delete a', e).click(function (evt) {
                            $(evt.target).closest('tr').addClass('is-deleted');
                            del_link.hide();
                            undel_link.show();
                            lightSaveButton();
                        });

                        $('span.group-undelete a', e).click(function (evt) {
                            $(evt.target).closest('tr').removeClass('is-deleted');
                            del_link.show();
                            undel_link.hide();
                            lightSaveButton();
                        });

                        $(e).hover(function (evt) {
                            if ($(evt.target).closest('tr').hasClass('is-deleted')) {
                                del_link.hide();
                            } else {
                                del_link.show();
                            }
                        }, function (evt) {
                            del_link.hide();
                        });

                        // validate membership
                        $.ajax({
                            type: 'GET',
                            url: 'api/v1/uwgroup/' + j.id + '/members',
                            success: function (data) {
                                var content = validateGroupMembers(
                                        j.group_id, data.invalid,
                                        warnBadExistingGroupMembers),
                                    span;

                                if (content) {
                                    span = $('');
                                    span.popover({
                                        'content': content,
                                        'html': true,
                                        'placement': 'right',
                                        'trigger': 'hover',
                                        'delay': 0
                                    });
                                    $('td:first', e).append(span);
                                }
                            },
                            error: function (xhr, textStatus, errorThrown) {
                                var errstr,
                                    span;

                                try {
                                    errstr = $.parseJSON(xhr.responseText).error;
                                } catch (e) {
                                    errstr = 'Error: ' + xhr.responseText;
                                }

                                span = $('');
                                span.popover({
                                    'content': errstr,
                                    'html': true,
                                    'placement': 'right',
                                    'trigger': 'hover',
                                    'delay': 0
                                });
                                $('td:first', e).append(span);
                            }
                        });
                    });
                    $('div.existing-groups').show();
                } else {
                    $('div.existing-groups').hide();
                }

            },
            error: function (xhr, textStatus, errorThrown) {
                var json;
                try {
                    json = $.parseJSON(xhr.responseText);
                    // console.log('Group Search Error:' + json.error);
                } catch (e) {
                    // console.log('Unknown error: ' + xhr.responseText);
                }
            }
        });
    };

    // init existing groups
    loadExistingGroups();

    // init new group list
    initializeNewGroups();
});
<|endoftext|>


<commit_before>'use strict';

var BrowsableTextArea = function(game, text) {
  Phaser.Sprite.call(this, game, game.world.centerX - 288, 360, 'question-background');
  this.inputEnabled = true;
  this.events.onInputDown.add(this.browseText, this);
  this.textString = text;
  this.splitText = [];
  this.splitTextToPages(this.textString);
  this.visibleTextIndex = 0;

  var textStyle = {font: '14px Arial', fill: 'white', align: 'left', wordWrap: true, wordWrapWidth: 574};
  this.currentVisibleText = game.add.text(5, 5, this.splitText[this.visibleTextIndex],  textStyle);
  this.addChild(this.currentVisibleText);

  var pageNumberTextStyle = {font: 'bold 14pt Arial', fill: 'red', align: 'right'};
  var pageNumberString = (this.visibleTextIndex + 1) + '/' + this.splitText.length;
  this.pageNumberText = game.add.text(576, 154, pageNumberString, pageNumberTextStyle);
  this.pageNumberText.anchor.setTo(1, 1);
  if (this.splitText.length === 1) {
    this.pageNumberText.visible = false;
  }
  this.addChild(this.pageNumberText);
};

BrowsableTextArea.prototype = Object.create(Phaser.Sprite.prototype);
BrowsableTextArea.prototype.constructor = BrowsableTextArea;

BrowsableTextArea.prototype.update = function() {
};

BrowsableTextArea.prototype.browseText = function() {
  this.visibleTextIndex = (this.visibleTextIndex + 1) % this.splitText.length;
  this.currentVisibleText.text = this.splitText[this.visibleTextIndex];
  this.pageNumberText.text = (this.visibleTextIndex + 1) + '/' + this.splitText.length;
};

BrowsableTextArea.prototype.splitTextToPages = function(text) {
  if (text.length < 537) {
    this.splitText.push(text);
  } else {
    var i = 537;
    while (text[i] !== ' ') {
      i--;
    }
    var pageOfText = text.slice(0, i);
    this.splitText.push(pageOfText);
    this.splitTextToPages(text.slice(i));
  }
};

module.exports = BrowsableTextArea;
<commit_msg>Make it more clear that there is more text.<commit_after>'use strict';

var BrowsableTextArea = function(game, text) {
  Phaser.Sprite.call(this, game, game.world.centerX - 288, 360, 'question-background');
  this.inputEnabled = true;
  this.events.onInputDown.add(this.browseText, this);
  this.textString = text;
  this.splitText = [];
  this.splitTextToPages(this.textString);
  this.visibleTextIndex = 0;

  var textStyle = {font: '14px Arial', fill: 'white', align: 'left', wordWrap: true, wordWrapWidth: 574};
  this.currentVisibleText = game.add.text(3, 5, this.splitText[this.visibleTextIndex],  textStyle);
  this.addChild(this.currentVisibleText);

  var pageNumberTextStyle = {font: 'bold 14pt Arial', fill: 'red', align: 'right'};
  var pageNumberString = 'jatkuu... ' + (this.visibleTextIndex + 1) + '/' + this.splitText.length;
  this.pageNumberText = game.add.text(576, 154, pageNumberString, pageNumberTextStyle);
  this.pageNumberText.anchor.setTo(1, 1);
  if (this.splitText.length === 1) {
    this.pageNumberText.visible = false;
  }
  this.addChild(this.pageNumberText);
};

BrowsableTextArea.prototype = Object.create(Phaser.Sprite.prototype);
BrowsableTextArea.prototype.constructor = BrowsableTextArea;

BrowsableTextArea.prototype.update = function() {
};

BrowsableTextArea.prototype.browseText = function() {
  this.visibleTextIndex = (this.visibleTextIndex + 1) % this.splitText.length;
  this.currentVisibleText.text = this.splitText[this.visibleTextIndex];

  if (this.visibleTextIndex + 1 < this.splitText.length) {
    this.pageNumberText.text = 'jatkuu... ' + (this.visibleTextIndex + 1) + '/' + this.splitText.length;
  } else {
    this.pageNumberText.text = (this.visibleTextIndex + 1) + '/' + this.splitText.length;
  }
};

BrowsableTextArea.prototype.splitTextToPages = function(text) {
  if (text.length < 537) {
    this.splitText.push(text);
  } else {
    var i = 537;
    while (text[i] !== ' ') {
      i--;
    }
    var pageOfText = text.slice(0, i);
    this.splitText.push(pageOfText);
    this.splitTextToPages(text.slice(i));
  }
};

module.exports = BrowsableTextArea;
<|endoftext|>


<commit_before>/**
 * Joint abstract class.
 * A Joint represents a node in the hierarchy.
 */
define([
    'events-emitter/EventsEmitter',
    'services/broadcaster',
    '../util/extend',
    'mout/array/insert',
    'mout/array/remove',
    'has'
], function (EventsEmitter, broadcaster, extend, insert, remove, has) {

    'use strict';

    /**
     * Constructor.
     */
    function Joint() {
        this._downlinks = [];
        this._emitter = new EventsEmitter();
    }

    Joint.extend = extend;

    /**
     * Adds a listener for an upcast or broadcast event.
     * Duplicate listeners for the same event will be discarded.
     *
     * @param {String}   event     The event name
     * @param {Function} fn        The handler
     * @param {Object}   [context] The context to be used to call the handler, defaults to the joint instance
     *
     * @return {Joint} The instance itself to allow chaining
     */
    Joint.prototype.on = function (event, fn, context) {
        this._emitter.on(event, fn, context);
        broadcaster.on(event, fn, context);

        return this;
    };

    /**
     * Adds a one time listener for an upcast or broadcast event.
     * Duplicate listeners for the same event will be discarded.
     *
     * @param {String}   event     The event name
     * @param {Function} fn        The handler
     * @param {Object}   [context] The context to be used to call the handler, defaults to the joint instance
     *
     * @return {Joint} The instance itself to allow chaining
     */
    Joint.prototype.once = function (event, fn, context) {
        this._emitter.once(event, fn, context);
        broadcaster.once(event, fn, context);

        return this;
    };

    Joint.prototype.one = Joint.prototype.once;

    /**
     * Removes a previously added listener.
     *
     * @param {String}   event     The event name
     * @param {Function} fn        The handler
     * @param {Object}   [context] The context passed to the on() method
     *
     * @return {Joint} The instance itself to allow chaining
     */
    Joint.prototype.off = function (event, fn, context) {
        this._emitter.off(event, fn, context);
        broadcaster.off(event, fn, context);

        return this;
    };

    /**
     * Destroys the instance, releasing all of its resources.
     * Note that all downlinks will also be destroyed.
     */
    Joint.prototype.destroy = function () {
        if (!this._destroyed) {
            this._onDestroy();
            this._destroyed = true;
        }
    };

    // --------------------------------------------

    /**
     * Creates a link between this joint and another one.
     *
     * @param {Joint} joint Another joint to link to this one
     *
     * @return {Joint} The joint passed in as the argument
     */
    Joint.prototype._link = function (joint) {
        if (has('debug') && joint._uplink && joint._uplink !== this) {
            throw new Error('"' + joint.$name + '" is already linked to other joint');
        }

        if (joint._uplink !== this) {
            joint._uplink = this;
            insert(this._downlinks, joint);
            joint._emitter.emit('link', this);
        }

        return joint;
    };

    /**
     * Removes a previously created link between this joint and another one.
     *
     * @param {Joint} joint Another joint to link to this one
     *
     * @return {Joint} The instance itself to allow chaining
     */
    Joint.prototype._unlink = function (joint) {
        remove(this._downlinks, joint);

        if (joint._uplink === this) {
            joint._uplink = null;
            joint._emitter.emit('unlink', this);
        }

        return this;
    };

    /**
     * Fires an event.
     *
     * @param {String}   event  The event name
     * @param {...mixed} [args] The arguments to pass along with the event
     *
     * @return {Boolean} True if it was handled, false otherwise
     */
    Joint.prototype._emit = function (event, args) {
        if (this._emitter.has(event)) {
            this._emitter.emit.apply(this._emitter, arguments);
            return true;
        }

        return false;
    };

    /**
     * Fires an event upwards the chain, starting in this Joint.
     *
     * @param {String}   event  The event name
     * @param {...mixed} [args] The arguments to pass along with the event
     *
     * @return {Boolean} True if it was handled, false otherwise
     */
    Joint.prototype._upcast = function (event, args) {
        // Check if the event will be handled locally
        if (this._emitter.has(event)) {
            this._emitter.emit.apply(this._emitter, arguments);
            return true;
        }

        // Otherwise we will keep upcasting upwards the chain
        if (this._uplink) {
            return this._uplink._upcast.apply(this._uplink, arguments);
        }

        if (has('debug')) {
            console.warn('Unhandled upcast event "' + event + '".');
        }

        return false;
    };

    /**
     * Fires an event downwards the chain, starting in this Joint.
     *
     * @param {String}   event  The event name
     * @param {...mixed} [args] The arguments to pass along with the event
     *
     * @return {Boolean} True if it was handled, false otherwise
     */
    Joint.prototype._downcast = function (event, args) {
        var x,
            length,
            last,
            curr,
            currHandled,
            handled = false;

        // Check if the event will be handled locally
        if (this._emitter.has(event)) {
            this._emitter.emit.apply(this._emitter, arguments);
            return true;
        }

        // Cycle each downlink
        length = this._downlinks.length;
        for (x = 0; x < length; x += 1) {
            curr = this._downlinks[x];

            // Protect against triggered events that cause the destruction of links
            if (!curr || curr === last) {
                continue;
            }

            currHandled = curr._downcast.apply(curr, arguments);
            if (currHandled) {
                handled = true;
            }
        }

        return handled;
    };

    /**
     * Fires an event to all the joints.
     *
     * @param {String}   event  The event name
     * @param {...mixed} [args] The arguments to pass along with the event
     *
     * @return {Boolean} True if it was handled, false otherwise
     */
    Joint.prototype._broadcast = function (event, args) {
        return broadcaster.broadcast.apply(broadcaster, arguments);
    };

    /**
     * Function called by destroy().
     * Subclasses should override this method to release additional resources.
     *
     * The default implementation will also destroy any linked joints.
     */
    Joint.prototype._onDestroy = function () {
        var x,
            curr;

        // Remove the listeners from the broadcaster
        this._emitter.forEach(broadcaster.off, broadcaster);

        // Clear the listeners
        this._emitter.off();

        // Foreach uplink, automatically unlink this instance
        if (this._uplink) {
            this._uplink._unlink(this);
            this._uplink = null;
        }

        // Foreach downlink, automatically unlink it and destroy
        for (x = this._downlinks.length - 1; x >= 0; x -= 1) {
            curr = this._downlinks[x];
            this._unlink(curr);
            curr.destroy();
        }

        this._downlinks = null;
    };

    return Joint;
});
<commit_msg>Modify destroy order so that listeners are still fired.<commit_after>/**
 * Joint abstract class.
 * A Joint represents a node in the hierarchy.
 */
define([
    'events-emitter/EventsEmitter',
    'services/broadcaster',
    '../util/extend',
    'mout/array/insert',
    'mout/array/remove',
    'has'
], function (EventsEmitter, broadcaster, extend, insert, remove, has) {

    'use strict';

    /**
     * Constructor.
     */
    function Joint() {
        this._downlinks = [];
        this._emitter = new EventsEmitter();
    }

    Joint.extend = extend;

    /**
     * Adds a listener for an upcast or broadcast event.
     * Duplicate listeners for the same event will be discarded.
     *
     * @param {String}   event     The event name
     * @param {Function} fn        The handler
     * @param {Object}   [context] The context to be used to call the handler, defaults to the joint instance
     *
     * @return {Joint} The instance itself to allow chaining
     */
    Joint.prototype.on = function (event, fn, context) {
        this._emitter.on(event, fn, context);
        broadcaster.on(event, fn, context);

        return this;
    };

    /**
     * Adds a one time listener for an upcast or broadcast event.
     * Duplicate listeners for the same event will be discarded.
     *
     * @param {String}   event     The event name
     * @param {Function} fn        The handler
     * @param {Object}   [context] The context to be used to call the handler, defaults to the joint instance
     *
     * @return {Joint} The instance itself to allow chaining
     */
    Joint.prototype.once = function (event, fn, context) {
        this._emitter.once(event, fn, context);
        broadcaster.once(event, fn, context);

        return this;
    };

    Joint.prototype.one = Joint.prototype.once;

    /**
     * Removes a previously added listener.
     *
     * @param {String}   event     The event name
     * @param {Function} fn        The handler
     * @param {Object}   [context] The context passed to the on() method
     *
     * @return {Joint} The instance itself to allow chaining
     */
    Joint.prototype.off = function (event, fn, context) {
        this._emitter.off(event, fn, context);
        broadcaster.off(event, fn, context);

        return this;
    };

    /**
     * Destroys the instance, releasing all of its resources.
     * Note that all downlinks will also be destroyed.
     */
    Joint.prototype.destroy = function () {
        if (!this._destroyed) {
            this._onDestroy();
            this._destroyed = true;
        }
    };

    // --------------------------------------------

    /**
     * Creates a link between this joint and another one.
     *
     * @param {Joint} joint Another joint to link to this one
     *
     * @return {Joint} The joint passed in as the argument
     */
    Joint.prototype._link = function (joint) {
        if (has('debug') && joint._uplink && joint._uplink !== this) {
            throw new Error('"' + joint.$name + '" is already linked to other joint');
        }

        if (joint._uplink !== this) {
            joint._uplink = this;
            insert(this._downlinks, joint);
            joint._emitter.emit('link', this);
        }

        return joint;
    };

    /**
     * Removes a previously created link between this joint and another one.
     *
     * @param {Joint} joint Another joint to link to this one
     *
     * @return {Joint} The instance itself to allow chaining
     */
    Joint.prototype._unlink = function (joint) {
        remove(this._downlinks, joint);

        if (joint._uplink === this) {
            joint._uplink = null;
            joint._emitter.emit('unlink', this);
        }

        return this;
    };

    /**
     * Fires an event.
     *
     * @param {String}   event  The event name
     * @param {...mixed} [args] The arguments to pass along with the event
     *
     * @return {Boolean} True if it was handled, false otherwise
     */
    Joint.prototype._emit = function (event, args) {
        if (this._emitter.has(event)) {
            this._emitter.emit.apply(this._emitter, arguments);
            return true;
        }

        return false;
    };

    /**
     * Fires an event upwards the chain, starting in this Joint.
     *
     * @param {String}   event  The event name
     * @param {...mixed} [args] The arguments to pass along with the event
     *
     * @return {Boolean} True if it was handled, false otherwise
     */
    Joint.prototype._upcast = function (event, args) {
        // Check if the event will be handled locally
        if (this._emitter.has(event)) {
            this._emitter.emit.apply(this._emitter, arguments);
            return true;
        }

        // Otherwise we will keep upcasting upwards the chain
        if (this._uplink) {
            return this._uplink._upcast.apply(this._uplink, arguments);
        }

        if (has('debug')) {
            console.warn('Unhandled upcast event "' + event + '".');
        }

        return false;
    };

    /**
     * Fires an event downwards the chain, starting in this Joint.
     *
     * @param {String}   event  The event name
     * @param {...mixed} [args] The arguments to pass along with the event
     *
     * @return {Boolean} True if it was handled, false otherwise
     */
    Joint.prototype._downcast = function (event, args) {
        var x,
            length,
            last,
            curr,
            currHandled,
            handled = false;

        // Check if the event will be handled locally
        if (this._emitter.has(event)) {
            this._emitter.emit.apply(this._emitter, arguments);
            return true;
        }

        // Cycle each downlink
        length = this._downlinks.length;
        for (x = 0; x < length; x += 1) {
            curr = this._downlinks[x];

            // Protect against triggered events that cause the destruction of links
            if (!curr || curr === last) {
                continue;
            }

            currHandled = curr._downcast.apply(curr, arguments);
            if (currHandled) {
                handled = true;
            }
        }

        return handled;
    };

    /**
     * Fires an event to all the joints.
     *
     * @param {String}   event  The event name
     * @param {...mixed} [args] The arguments to pass along with the event
     *
     * @return {Boolean} True if it was handled, false otherwise
     */
    Joint.prototype._broadcast = function (event, args) {
        return broadcaster.broadcast.apply(broadcaster, arguments);
    };

    /**
     * Function called by destroy().
     * Subclasses should override this method to release additional resources.
     *
     * The default implementation will also destroy any linked joints.
     */
    Joint.prototype._onDestroy = function () {
        var x,
            curr;

        // Foreach downlink, automatically destroy
        for (x = this._downlinks.length - 1; x >= 0; x -= 1) {
            curr = this._downlinks[x];
            curr.destroy();
        }
        this._downlinks = null;

        // Foreach uplink, automatically unlink this instance
        if (this._uplink) {
            this._uplink._unlink(this);
            this._uplink = null;
        }

        // Remove the listeners from the broadcaster
        this._emitter.forEach(broadcaster.off, broadcaster);

        // Clear the listeners
        this._emitter.off();
    };

    return Joint;
});
<|endoftext|>


<commit_before>// This file is developed in ECMA 6 based JavaScript for some reason, and we're trying to use that in your typescript code

export class EcmaBasedClass {
	static show() {
		let msg = 'This is a ECMA 6 based JavaScript file';
		alert(msg);
	}
}<commit_msg>Enhanced index.js<commit_after>// This file is developed in ECMA 6 based JavaScript for some reason, and we're trying to use that in our typescript code
// Use any ECMA 6 & 7 features which are supported by Typescript here.

export class EcmaBasedClass {
	static show() {
		let msg = 'This is a ECMA 6 based JavaScript file';
		alert(msg);
	}
}
<|endoftext|>