<commit_before>// dependencies: fav.js, display.js, history.js, suggest.js, icon.js, pin.js

var getSearchQueryURL = function () {
  var parameters = []
  if ($('#searchbox').val() != null) {
    parameters.push('search=' + $('#searchbox').val())
  }
  if ($('#semester').val() != null) {
    parameters.push('semester=' + $('#semester').val())
  }
  if ($('#sort').val() != null) {
    parameters.push('sort=' + $('#sort').val())
  }
  if ($('#advanced-grad-hide').is(':checked')) {
    parameters.push('track=UGRD')
  }
  if ($('#advanced-filter-clashes').is(':checked')) {
    parameters.push('filterClashes=true')
  }
  return '?' + parameters.join('&')

  // search += '&track=' + 'UGRD'
}

// update search results from the search box
var searchFromBox = function(noswipe) {
  // query url
  var queryURL = getSearchQueryURL()

  var query = encodeURIComponent($('#searchbox').val())
  var semester = $('#semester').val()
  var sort = $('#sort').val()
  var track = ($('#advanced-grad-hide').is(':checked') ? 'UGRD' : '')
  var filterClashes = $('#advanced-filter-clashes').is(':checked')

  // save search into history
  history_search(queryURL)

  searchForCourses(query, semester, sort, track, filterClashes, noswipe)
}

// update search results from a URL
var searchFromURL = function(query, semester, sort, track, filterClashes, noswipe) {
  // display search
  if (query) $('#searchbox').val(decodeURIComponent(query))
  if (semester) $('#semester').val(semester)
  if (sort) $('#sort').val(sort)
  $('#advanced-grad-hide')[0].checked = (track === 'UGRD')
  $('#advanced-filter-clashes')[0].checked = (filterClashes === 'true')

  searchForCourses(query, semester, sort, track, filterClashes, noswipe)
}

// function for updating search results
// -- noswipe to prevent swiping if on mobile
var searchForCourses = function (query, semester, sort, track, filterClashes, noswipe) {
  if (query === undefined || query === null) query = ''

  // construct search query
  var search = '/api/search/' + query
  search += '?semester=' + semester
  search += '&sort=' + sort
  search += (track !== undefined && track !== '') ? '&track=' + track : ''
  search += '&detectClashes=' + (filterClashes ? 'filter' : 'true')
  // search += '&track=' + 'UGRD'

  // stop if no query
  if (query === '') {
    $('#results').children().remove();
    $('#search-title').text('0 Search Results')
    document.lastSearch = ''
    $('#search-load-indicator').hide()
    $('#search-results').stop().css('opacity', '')
    updateSuggest()
    return false
  }

  // go to search pane for mobile and hide favorites
  if (document.isMobile && noswipe !== true) {
    $('#main-pane').slick('slickGoTo', 1)
    // if ($('#fav-display-toggle').hasClass('fa-minus')) $('#fav-display-toggle').click()
  }

  // store search value used
  localStorage.setItem("sort", $('#sort').val())

  $('#search-load-indicator').show()
  $('#search-results').stop().animate({'opacity': '0.5'})

  // search!
  $.get(search, function (results, success, xhr) {
    if (!success) {
      window.alert('An error occured and your search could not be completed.')
      return false
    }

    // Discard the response if the query does not match the text currently in the search box
    if (decodeURIComponent(query) !== $('#searchbox').val()) {
      return false
    }

    // Check whether there is a clash among the favorite courses
    if (results.length > 0 && results[0].hasOwnProperty('favoritesClash') && results[0].favoritesClash) {
      $('#fav-clash-indicator').show()
    } else {
      $('#fav-clash-indicator').hide()
    }

    // Remove any search results already in the results pane
    $('#results').children().remove()

    var len = results.length

    // Update the search results sub-heading
    $('#search-title').text(len + ' Search Result' + (len !== 1 ? 's' : ''))

    // List the returned courses in the search results pane
    for (var index in results) {
      var result = results[index]
      if (result) {
        $('#results').append(newDOMResult(result, {"tags": 1}))
      }
    }

    displayActive() // update highlighting of active course
    updateSuggest()

    $('#search-load-indicator').hide()
    $('#search-results').stop().css('opacity', '')
  })

}

// returns a DOM object for a search result
function newDOMResult(result, props) {
  if (result.type === 'instructor') return newDOMinstructorResult(result, props)
  /*if (result.type === 'course')*/ return newDOMcourseResult(result, props)
}

// returns a DOM object for a search result of an instructor
function newDOMinstructorResult(instructor, props) {
  var name = instructor.name.first + ' ' + instructor.name.last

  // html string for the DOM object
  var htmlString = (
    '
'
    + '
'
      + '
'
        + '' + name + ''
      + '
'
      + '
'
        + '' + instructor.courses.length + ' '
        + ''
      + '
'
    + '
'
    + '
'
    + '
'
  + '
'
  )

  var entry = $.parseHTML(htmlString)[0]  // create DOM object
  var icon = $(entry).find('i')[0]        // find icon
  var title = $(entry).find('.instructor-title')    // instructor name
  icon.instructorId = instructor._id      // attach instructor id
  var body = $(entry).find('ul')[0]       // body of instructor result
  $(icon).click(function() {toggleInstructor(icon, body, entry); return false})
  $(entry).click(function() {toggleInstructor(icon, body, entry); return false})

  return entry
}

// handles clicking the button to toggle instructors
// - icon: DOM object of toggling icon
// - body: DOM object of place to insert courses
// - entry: DOM object of whole entry
function toggleInstructor(icon, body, entry) {
  var isEmpty = $(body).is(':empty')

  if (isEmpty) {
    loadInstructor(icon, body, entry)
    return
  }

  var isVisible = $(body).is(':visible')

  $(icon).removeClass(isVisible ? 'fa-caret-up' : 'fa-caret-down')
  $(icon).addClass(isVisible ? 'fa-caret-down' : 'fa-caret-up')
  if (isVisible) $(entry).removeClass('instructor-list-item-opened')
  else $(entry).addClass('instructor-list-item-opened')
  $(body).slideToggle()
}

// handles loading instructor courses
// - icon: DOM object of toggling icon
// - body: DOM object of place to insert courses
// - entry: DOM object of whole entry
function loadInstructor(icon, body, entry) {
  $.get('/api/instructor/' + icon.instructorId, function (instructor) {
    // Stop if already loaded
    if (!$(body).is(':empty')) return;

    var courses = instructor.courses;
    for (var index in courses) {
      var course = courses[index]
      $(body).append(newDOMcourseResult(course, {'tags' : 1, 'semester': 1}))
    }

    $(icon).removeClass('fa-caret-down')
    $(icon).addClass('fa-caret-up')
    $(entry).addClass('instructor-list-item-opened')
    displayActive()
    $(body).slideToggle()
  })
}

// returns a DOM object for a search or favorite result of a course
// includes:
//   -- course object linking
//   -- clicking to favorite/unfavorite (+ course id linking for icon)
// props: properties for conditional rendering:
//  - 'semester' is defined => displays semester name too
//  - 'pin' is defined => displays pin to select courses for course clash
//  - 'tags' is defined => displays pdf/audit tags
function newDOMcourseResult(course, props) {
  // append semester if appropriate
  var semester = props.hasOwnProperty('semester') ? ' ' + course.semester.name + '' : ''

  // tags: dist / pdf / audit
  var tags = ''
  if (props.hasOwnProperty('tags')) tags = '' + newHTMLtags(course) + ''

  // clash icon
  var clashIcon = ''
  if (course.clash) clashIcon = ''

  // pin icon for selecting courses (only in fav list)
  var hasPinIcon = (props.hasOwnProperty('pin') && !course.clash)
  var pinIcon = ''
  if (hasPinIcon) pinIcon = ''

  // dot to indicate openness
  var dot = ''
  if (course.hasOwnProperty('open')) dot = newHTMLlock(course)

  // html string for the DOM object
  var htmlString = (
    '
'
    + '
'
      + '
'
        + dot + ' '
        + '' + newHTMLlistings(course) + ' ' + tags
      + '
'
      + '
'
        + ' '
        + pinIcon + ' '
        + clashIcon + ' '
        + newHTMLfavIcon(course._id) + ' '
        + newHTMLscoreBadge(course)
      + '
'
    + '
'
    + '
'
      + '
' + course.title + '
'
      + '
' + semester + '
'
    + '
'
  + '
'
  )

  var entry = $.parseHTML(htmlString)[0]                                     // create DOM object
  var icon = $(entry).find('i.fa-heart')[0]                                  // favorite icon
  entry.courseId = course._id                                                // attach course id to entry
  icon.courseId = course._id                                                 // attach course id to icon
  $(icon).click(toggleFav)                                                   // handle click to fav/unfav
  $(entry).click(displayResult)                                              // enable click to display

  // bind pin icons
  if (hasPinIcon) {
    var pin = $(entry).find('i.fa-thumb-tack')[0]
    pin.courseId = course._id
    $(pin).click(togglePin)
  }

  return entry
}
<commit_msg>update suggest before search finishes<commit_after>// dependencies: fav.js, display.js, history.js, suggest.js, icon.js, pin.js

var getSearchQueryURL = function () {
  var parameters = []
  if ($('#searchbox').val() != null) {
    parameters.push('search=' + $('#searchbox').val())
  }
  if ($('#semester').val() != null) {
    parameters.push('semester=' + $('#semester').val())
  }
  if ($('#sort').val() != null) {
    parameters.push('sort=' + $('#sort').val())
  }
  if ($('#advanced-grad-hide').is(':checked')) {
    parameters.push('track=UGRD')
  }
  if ($('#advanced-filter-clashes').is(':checked')) {
    parameters.push('filterClashes=true')
  }
  return '?' + parameters.join('&')

  // search += '&track=' + 'UGRD'
}

// update search results from the search box
var searchFromBox = function(noswipe) {
  // query url
  var queryURL = getSearchQueryURL()

  var query = encodeURIComponent($('#searchbox').val())
  var semester = $('#semester').val()
  var sort = $('#sort').val()
  var track = ($('#advanced-grad-hide').is(':checked') ? 'UGRD' : '')
  var filterClashes = $('#advanced-filter-clashes').is(':checked')

  // save search into history
  history_search(queryURL)

  searchForCourses(query, semester, sort, track, filterClashes, noswipe)
}

// update search results from a URL
var searchFromURL = function(query, semester, sort, track, filterClashes, noswipe) {
  // display search
  if (query) $('#searchbox').val(decodeURIComponent(query))
  if (semester) $('#semester').val(semester)
  if (sort) $('#sort').val(sort)
  $('#advanced-grad-hide')[0].checked = (track === 'UGRD')
  $('#advanced-filter-clashes')[0].checked = (filterClashes === 'true')

  searchForCourses(query, semester, sort, track, filterClashes, noswipe)
}

// function for updating search results
// -- noswipe to prevent swiping if on mobile
var searchForCourses = function (query, semester, sort, track, filterClashes, noswipe) {
  if (query === undefined || query === null) query = ''

  // construct search query
  var search = '/api/search/' + query
  search += '?semester=' + semester
  search += '&sort=' + sort
  search += (track !== undefined && track !== '') ? '&track=' + track : ''
  search += '&detectClashes=' + (filterClashes ? 'filter' : 'true')
  // search += '&track=' + 'UGRD'

  // stop if no query
  if (query === '') {
    $('#results').children().remove();
    $('#search-title').text('0 Search Results')
    document.lastSearch = ''
    $('#search-load-indicator').hide()
    $('#search-results').stop().css('opacity', '')
    updateSuggest()
    return false
  }

  // go to search pane for mobile and hide favorites
  if (document.isMobile && noswipe !== true) {
    $('#main-pane').slick('slickGoTo', 1)
    // if ($('#fav-display-toggle').hasClass('fa-minus')) $('#fav-display-toggle').click()
  }

  // store search value used
  localStorage.setItem("sort", $('#sort').val())

  $('#search-load-indicator').show()
  $('#search-results').stop().animate({'opacity': '0.5'})

  updateSuggest()

  // search!
  $.get(search, function (results, success, xhr) {
    if (!success) {
      window.alert('An error occured and your search could not be completed.')
      return false
    }

    // Discard the response if the query does not match the text currently in the search box
    if (decodeURIComponent(query) !== $('#searchbox').val()) {
      return false
    }

    // Check whether there is a clash among the favorite courses
    if (results.length > 0 && results[0].hasOwnProperty('favoritesClash') && results[0].favoritesClash) {
      $('#fav-clash-indicator').show()
    } else {
      $('#fav-clash-indicator').hide()
    }

    // Remove any search results already in the results pane
    $('#results').children().remove()

    var len = results.length

    // Update the search results sub-heading
    $('#search-title').text(len + ' Search Result' + (len !== 1 ? 's' : ''))

    // List the returned courses in the search results pane
    for (var index in results) {
      var result = results[index]
      if (result) {
        $('#results').append(newDOMResult(result, {"tags": 1}))
      }
    }

    displayActive() // update highlighting of active course

    $('#search-load-indicator').hide()
    $('#search-results').stop().css('opacity', '')
  })

}

// returns a DOM object for a search result
function newDOMResult(result, props) {
  if (result.type === 'instructor') return newDOMinstructorResult(result, props)
  /*if (result.type === 'course')*/ return newDOMcourseResult(result, props)
}

// returns a DOM object for a search result of an instructor
function newDOMinstructorResult(instructor, props) {
  var name = instructor.name.first + ' ' + instructor.name.last

  // html string for the DOM object
  var htmlString = (
    '
'
    + '
'
      + '
'
        + '' + name + ''
      + '
'
      + '
'
        + '' + instructor.courses.length + ' '
        + ''
      + '
'
    + '
'
    + '
'
    + '
'
  + '
'
  )

  var entry = $.parseHTML(htmlString)[0]  // create DOM object
  var icon = $(entry).find('i')[0]        // find icon
  var title = $(entry).find('.instructor-title')    // instructor name
  icon.instructorId = instructor._id      // attach instructor id
  var body = $(entry).find('ul')[0]       // body of instructor result
  $(icon).click(function() {toggleInstructor(icon, body, entry); return false})
  $(entry).click(function() {toggleInstructor(icon, body, entry); return false})

  return entry
}

// handles clicking the button to toggle instructors
// - icon: DOM object of toggling icon
// - body: DOM object of place to insert courses
// - entry: DOM object of whole entry
function toggleInstructor(icon, body, entry) {
  var isEmpty = $(body).is(':empty')

  if (isEmpty) {
    loadInstructor(icon, body, entry)
    return
  }

  var isVisible = $(body).is(':visible')

  $(icon).removeClass(isVisible ? 'fa-caret-up' : 'fa-caret-down')
  $(icon).addClass(isVisible ? 'fa-caret-down' : 'fa-caret-up')
  if (isVisible) $(entry).removeClass('instructor-list-item-opened')
  else $(entry).addClass('instructor-list-item-opened')
  $(body).slideToggle()
}

// handles loading instructor courses
// - icon: DOM object of toggling icon
// - body: DOM object of place to insert courses
// - entry: DOM object of whole entry
function loadInstructor(icon, body, entry) {
  $.get('/api/instructor/' + icon.instructorId, function (instructor) {
    // Stop if already loaded
    if (!$(body).is(':empty')) return;

    var courses = instructor.courses;
    for (var index in courses) {
      var course = courses[index]
      $(body).append(newDOMcourseResult(course, {'tags' : 1, 'semester': 1}))
    }

    $(icon).removeClass('fa-caret-down')
    $(icon).addClass('fa-caret-up')
    $(entry).addClass('instructor-list-item-opened')
    displayActive()
    $(body).slideToggle()
  })
}

// returns a DOM object for a search or favorite result of a course
// includes:
//   -- course object linking
//   -- clicking to favorite/unfavorite (+ course id linking for icon)
// props: properties for conditional rendering:
//  - 'semester' is defined => displays semester name too
//  - 'pin' is defined => displays pin to select courses for course clash
//  - 'tags' is defined => displays pdf/audit tags
function newDOMcourseResult(course, props) {
  // append semester if appropriate
  var semester = props.hasOwnProperty('semester') ? ' ' + course.semester.name + '' : ''

  // tags: dist / pdf / audit
  var tags = ''
  if (props.hasOwnProperty('tags')) tags = '' + newHTMLtags(course) + ''

  // clash icon
  var clashIcon = ''
  if (course.clash) clashIcon = ''

  // pin icon for selecting courses (only in fav list)
  var hasPinIcon = (props.hasOwnProperty('pin') && !course.clash)
  var pinIcon = ''
  if (hasPinIcon) pinIcon = ''

  // dot to indicate openness
  var dot = ''
  if (course.hasOwnProperty('open')) dot = newHTMLlock(course)

  // html string for the DOM object
  var htmlString = (
    '
'
    + '
'
      + '
'
        + dot + ' '
        + '' + newHTMLlistings(course) + ' ' + tags
      + '
'
      + '
'
        + ' '
        + pinIcon + ' '
        + clashIcon + ' '
        + newHTMLfavIcon(course._id) + ' '
        + newHTMLscoreBadge(course)
      + '
'
    + '
'
    + '
'
      + '
' + course.title + '
'
      + '
' + semester + '
'
    + '
'
  + '
'
  )

  var entry = $.parseHTML(htmlString)[0]                                     // create DOM object
  var icon = $(entry).find('i.fa-heart')[0]                                  // favorite icon
  entry.courseId = course._id                                                // attach course id to entry
  icon.courseId = course._id                                                 // attach course id to icon
  $(icon).click(toggleFav)                                                   // handle click to fav/unfav
  $(entry).click(displayResult)                                              // enable click to display

  // bind pin icons
  if (hasPinIcon) {
    var pin = $(entry).find('i.fa-thumb-tack')[0]
    pin.courseId = course._id
    $(pin).click(togglePin)
  }

  return entry
}
<|endoftext|>


<commit_before>// Pony.fm - A community for pony fan music.
// Copyright (C) 2016 Josef Citrine
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

var urlsToCache = [
  '/offline.html',
  '/styles/offline.css',
  '/images/ponyfm-logo-white.svg'
];

var CACHE_NAME = 'pfm-offline-v1';

var notifUrlCache = {};

function getChromeVersion () {
  var raw = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);

  return raw ? parseInt(raw[2], 10) : false;
}

// Set the callback for the install step
self.addEventListener('install', function(event) {
  // Perform install steps
  event.waitUntil(
    caches.open(CACHE_NAME)
    .then(function(cache) {
      cache.addAll(urlsToCache);
    })
  );
});

// Delete old caches
self.addEventListener('activate', function (event) {
  event.waitUntil(caches.keys().then(function (cacheNames) {
    return Promise.all(cacheNames.map(function (cacheName) {
      if (cacheName != CACHE_NAME) {
        return caches.delete(cacheName);
      }
    }));
  }));
});

// Basic offline mode
// Just respond with an offline error page for now
self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request).then(function(response) {
      return response || fetch(event.request);
    }).catch(function () {
      if (event.request.mode == 'navigate') {
        return caches.match('/offline.html');
      }
    })
  )
});

self.addEventListener('push', function(event) {
  console.log(event);
  var data = {};

  if (event.data) {
    console.log(event.data.json());
    data = JSON.parse(event.data.text());
  }

  notifUrlCache['pfm-' + data.id] = data.url;

  self.registration.showNotification(data.title, {
    body: data.text,
    icon: data.image,
    tag: 'pfm-' + data.id
  })
});

self.addEventListener('notificationclick', function(event) {
  event.notification.close();

  event.waitUntil(
    clients.matchAll({
      type: "window"
    })
    .then(function(clientList) {
      var url = notifUrlCache[event.notification.tag];
      for (var i = 0; i < clientList.length; i++) {
        var client = clientList[i];
        if (client.url == url && 'focus' in client)
          return client.focus();
      }

      if (clients.openWindow) {
        return clients.openWindow(url);
      }
    })
  );
});<commit_msg>Attempt to fix page load issues on staging server<commit_after>// Pony.fm - A community for pony fan music.
// Copyright (C) 2016 Josef Citrine
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

var urlsToCache = [
  '/offline.html',
  '/styles/offline.css',
  '/images/ponyfm-logo-white.svg'
];

var CACHE_NAME = 'pfm-offline-v1';

var notifUrlCache = {};

function getChromeVersion () {
  var raw = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);

  return raw ? parseInt(raw[2], 10) : false;
}

// Set the callback for the install step
self.addEventListener('install', function(event) {
  // Perform install steps
  event.waitUntil(
    caches.open(CACHE_NAME)
    .then(function(cache) {
      cache.addAll(urlsToCache);
    })
  );
});

// Delete old caches
self.addEventListener('activate', function (event) {
  event.waitUntil(caches.keys().then(function (cacheNames) {
    return Promise.all(cacheNames.map(function (cacheName) {
      if (cacheName != CACHE_NAME) {
        return caches.delete(cacheName);
      }
    }));
  }));
});

// Basic offline mode
// Just respond with an offline error page for now
self.addEventListener('fetch', function(event) {
  if (event.request.url.indexOf('stage.pony.fm') > -1) {
    event.respondWith(fetch(event.request));
  } else {
    event.respondWith(
        caches.match(event.request).then(function (response) {
          return response || fetch(event.request);
        }).catch(function () {
          if (event.request.mode == 'navigate') {
            return caches.match('/offline.html');
          }
        })
    )
  }
});

self.addEventListener('push', function(event) {
  console.log(event);
  var data = {};

  if (event.data) {
    console.log(event.data.json());
    data = JSON.parse(event.data.text());
  }

  notifUrlCache['pfm-' + data.id] = data.url;

  self.registration.showNotification(data.title, {
    body: data.text,
    icon: data.image,
    tag: 'pfm-' + data.id
  })
});

self.addEventListener('notificationclick', function(event) {
  event.notification.close();

  event.waitUntil(
    clients.matchAll({
      type: "window"
    })
    .then(function(clientList) {
      var url = notifUrlCache[event.notification.tag];
      for (var i = 0; i < clientList.length; i++) {
        var client = clientList[i];
        if (client.url == url && 'focus' in client)
          return client.focus();
      }

      if (clients.openWindow) {
        return clients.openWindow(url);
      }
    })
  );
});<|endoftext|>


<commit_before>/*
 * debugger.io: An interactive web scripting sandbox
 *
 * mirrors.js: CodeMirror instances
 */

define([
  'config', 'utils', 'jquery', 'underscore',
  'bus', 'codemirror', 'dom'
],
function(config, utils, $, _, bus, CodeMirror, dom) {
  'use strict';

  var mirrors = utils.module('mirrors');

  var instances = [];
  var last_focused;

  bus.init(function(av) {
    utils.log('init mirrors module');

    _.each(av.$input_panels, function(panel) {
      var $panel = $(panel);
      var $textarea = $panel.children('textarea');
      var mode = $panel.children('.mode').val();

      var cm = CodeMirror.fromTextArea($textarea[0], {
        lineNumbers: true,
        lineWrapping: true,
        mode: mode
      });

      var mirror = {
        panel: $panel.attr('id'),
        $panel: $panel,
        $textarea: $textarea,
        cm: cm,
        mode: mode
      };

      cm.on('focus', function() {
        bus.trigger('mirror:focus', mirror);
        last_focused = mirror;
      });

      mirrors.scrollable(mirror);
      instances.push(mirror);
    });

    bus.on('cdn:result:select', function(uri) {
      mirrors.add_lib_to_markup(uri);
      mirrors.refocus();
    });
  });

  /**
   * Get a mirror by its panel id
   *
   * @param {String} id - panel id
   * @return {CodeMirror} mirror with matching panel id, null otherwise
   */
  mirrors.get_by_id = function(id) {
    var mirror = _.find(instances, function(mirror) {
      return mirror.panel === id;
    });

    return mirror && mirror.cm instanceof CodeMirror ? mirror : null;
  };

  /**
   * Get a mirror for either its panel id or the mirror itself
   *
   * @param {String | Object} m - panel id or mirror
   * @return {CodeMirror} - null if requested mirror does not exist
   */
  mirrors.get_instance = function(m) {
    return m && m.cm instanceof CodeMirror ? m : mirrors.get_by_id(m);
  };

  /**
   * Hack for letting a scrollbar at least be a visual scroll indicator
   *
   * @param {String | Object} m - panel id or mirror
   */
  mirrors.scrollable = function(m) {
    var mirror = mirrors.get_instance(m);
    if (!mirror) { return null; }

    var $scroll = mirror.$panel.find('.CodeMirror-vscrollbar').first();
    $scroll.addClass('nano').css({ 'overflow': 'visible', 'width': '10px' });
    $scroll.children().first().addClass('content');

    dom.init_scrollbar($scroll);
    var $slider = $scroll.find('.pane > .slider');

    var track_remainder = function() {
      return $scroll.height() - $slider.height() - 4; // - margin
    };

    // update the scrollbar to match the current mirror position
    var update_scrollbar = function(info, remainder) {
      info = info || mirror.cm.getScrollInfo();
      remainder = remainder || track_remainder();

      var multiplier = (info.top / (info.height - info.clientHeight)) || 0;

      $slider.css({ 'top': multiplier * remainder });
      $scroll.css({
        'display': info.height > info.clientHeight ? 'block' : 'none'
      });
    };

    // update the mirror position to match the current scrollbar position
    var update_mirror_scroll = function(info, remainder) {
      info = info || mirror.cm.getScrollInfo();
      remainder = remainder || track_remainder();

      var top = parseInt($slider.css('top'), 10);
      var multiplier = top / remainder;
      mirror.cm.scrollTo(null, multiplier * (info.height - info.clientHeight));
    };

    (function() {
      var mde; // mousedown event
      var top = 0;
      var info;
      var remainder;

      var bind_scroll = function(e) {
        mde = e;
        top = parseInt($slider.css('top'), 10);
        info = mirror.cm.getScrollInfo();
        remainder = track_remainder();

        $(document).on('mousemove', do_scroll);
        $(document).on('mouseup', unbind_scroll);
      };

      var unbind_scroll = function(e) {
        $(document).off('mousemove', do_scroll);
        $(document).off('mouseup', unbind_scroll);
      };

      var do_scroll = function(e) {
        var distanceY = e.pageY - mde.pageY;
        $slider.css('top', utils.clamp(top + distanceY, 0, remainder));

        update_mirror_scroll(info, remainder);
      };

      // let the user drag the scrollbars
      $slider.on('mousedown', bind_scroll);
    })();

    // or, click on the track to move the scrollbar
    $scroll.on('click', function(e) {
      if ($slider.is(e.target)) { return; }

      var midPoint = e.offsetY - $slider.height() / 2;
      var newTop = utils.clamp(midPoint, 0, track_remainder());
      $slider.css('top', newTop);

      update_mirror_scroll();
    });

    mirror.cm.on('change', function() {
      $scroll[0].nanoscroller.reset();
      update_scrollbar();
    });

    mirror.cm.on('scroll', function() {
      update_scrollbar();
    });

    bus.on('panels:resizing', function() {
      _.defer(function() { CodeMirror.signal(mirror.cm, 'change'); });
    });

    bus.on('window:resize panels:resized', function() {
      _.defer(function() { mirrors.simulate_change(mirror); });
    });
  };

  var mirror_mode_sets = {
    'markup': [
      { label: 'HTML', mode: 'htmlmixed' },
      { label: 'Markdown', mode: 'gfm' }
    ],
    'style': [
      { label: 'CSS', mode: 'css' },
      { label: 'LESS', mode: 'less' },
      { label: 'SCSS', mode: 'scss', cm_mode: 'text/x-scss' }
    ],
    'script': [
      { label: 'JavaScript', mode: 'javascript' },
      { label: 'CoffeeScript', mode: 'coffeescript' },
      {
        label: 'TypeScript', mode: 'typescript',
        cm_mode: 'application/typescript'
      }, {
        label: 'GorillaScript', mode: 'gorillascript',
        cm_mode: 'javascript'
      }
    ]
  };

  var get_mode_set = function(panel, mode) {
    return _.find(mirror_mode_sets[panel], function(set) {
      return set.mode === mode || set.cm_mode === mode;
    });
  };

  /**
   * Get the mode for a mirror
   *
   * @param {String | Object} m - panel id or mirror
   * @return {String} current mirror mode
   */
  mirrors.get_mode = function(m) {
    var mirror = mirrors.get_instance(m);
    if (!mirror) { return null; }

    return mirror.mode;
  };

  /**
   * Set the mode for a mirror
   *
   * @param {String | Object} m - panel id or mirror
   * @param {String} mode - new mode to set
   */
  mirrors.set_mode = function(m, mode) {
    var mirror = mirrors.get_instance(m);
    if (!mirror || !_.isString(mode)) { return; }

    var set = get_mode_set(mirror.panel, mode);
    if (!set) { return; }

    mirror.cm.setOption('mode', set.cm_mode || set.mode);
    mirror.mode = set.mode;

    var eventName = _.sprintf('mirrors:%s:mode', mirror.panel);
    bus.trigger(eventName, set.mode, set.label);
  };

  /**
   * Rotate a mirror through available modes
   *
   * @param {String | Object} m - panel id or mirror
   */
  mirrors.cycle_mode = function(m) {
    var mirror = mirrors.get_instance(m);
    var panel = mirror.panel;

    var modes = mirror_mode_sets[panel];
    var mode = mirrors.get_mode(panel);
    if (!modes) { return; }

    var set = get_mode_set(panel, mode);
    var i = _.indexOf(modes, set);

    var newMode = modes[++i % modes.length];
    mirrors.set_mode(panel, newMode.mode);
  };

  /**
   * Get the theme for a mirror
   *
   * @param {String | Object} m - panel id or mirror
   * @return {String} current mirror theme
   */
  mirrors.get_theme = function(m) {
    var mirror = mirrors.get_instance(m);
    if (!mirror) { return null; }

    return mirror.cm.getOption('theme');
  };

  /**
   * Set the theme for a mirror
   *
   * @param {String | Object} m - panel id or mirror
   * @param {String} theme - new theme to set
   */
  mirrors.set_theme = function(m, theme) {
    var mirror = mirrors.get_instance(m);
    if (!mirror || !_.isString(theme)) { return; }

    mirror.cm.setOption('theme', theme);
  };

  /**
   * Set the theme for all mirrors
   *
   * @param {String} theme - new theme to set
   */
  mirrors.set_theme_all = function(theme) {
    _.each(instances, function(mirror) {
      mirrors.set_theme(mirror, theme);
    });
  };

  /**
   * Set the cursor focus on a mirror
   *
   * @param {String | Object} m - panel id or mirror
   */
  mirrors.focus = function(m) {
    var mirror = mirrors.get_instance(m);
    if (!mirror) { return; }

    mirror.cm.focus();
  };

  /**
   * Refocus the last focused mirror
   */
  mirrors.refocus = function() {
    mirrors.focus(last_focused);
  };

  /**
   * Search a mirror for the first occurrence of a string
   *
   * @param {String | Object} m - panel id or mirror
   * @param {String | RegExp} str - string to search for
   * @param {Boolean} ci - if true, search is case-insensitive
   * @return {Object} position map { line, ch } if found, null otherwise
   */
  mirrors.search_first = function(m, str, ci) {
    var mirror = mirrors.get_instance(m);
    if (!mirror || (!_.isString(str) && !_.isRegExp(str))) { return null; }

    var cur = mirror.cm.getSearchCursor(str, null, !!ci);
    return (cur && cur.find()) ? { from: cur.from(), to: cur.to() } : null;
  };

  /**
   * Search a mirror for the last occurrence of a string
   *
   * @param {String | Object} m - panel id or mirror
   * @param {String | RegExp} str - string to search for
   * @param {Boolean} ci - if true, search is case-insensitive
   * @return {Object} position map { line, ch } if found, null otherwise
   */
  mirrors.search_last = function(m, str, ci) {
    var mirror = mirrors.get_instance(m);
    if (!mirror || (!_.isString(str) && !_.isRegExp(str))) { return null; }

    var cur = mirror.cm.getSearchCursor(str, null, !!ci);

    var pos;
    while (cur && cur.find()) {
      pos = { from: cur.from(), to: cur.to() };
    }

    return pos || null;
  };

  /**
   * Add content to a mirror at a specific position
   *
   * @param {String | Object} m - panel id or mirror
   * @param {String} str - content to add
   * @param {Object} pos - position map { line, ch } to insert at
   */
  mirrors.add_content_at = function(m, str, pos) {
    var mirror = mirrors.get_instance(m);
    if (!mirror || !_.isString(str)) { return; }

    mirror.cm.replaceRange(str, pos);
  };

  /**
   * Add content to a mirror as the first line(s)
   *
   * @param {String | Object} m - panel id or mirror
   * @param {String} str - content to add
   */
  mirrors.add_content_start = function(m, str) {
    if (!_.isString(str)) { return; }
    return mirrors.add_content_at(m, str + '\n', { line: 0, ch: 0 });
  };

  /**
   * Add content to a mirror as the last line(s)
   *
   * @param {String | Object} m - panel id or mirror
   * @param {String} str - content to add
   */
  mirrors.add_content_end = function(m, str) {
    var mirror = mirrors.get_instance(m);
    if (!mirror || !_.isString(str)) { return; }

    var lastLine = mirror.cm.lastLine();
    var lastLineContent = mirror.cm.getLine(lastLine);
    var nlStr = !lastLineContent ? str : '\n' + str;

    return mirrors.add_content_at(m, nlStr, { line: lastLine });
  };

  /**
   * Trigger a real change event by inserting and then removing a character
   *
   * @param {String | Object} m - panel id or mirror
   */
  mirrors.simulate_change = function(m) {
    var mirror = mirrors.get_instance(m);
    if (!mirror) { return; }

    mirror.cm.replaceRange(' ', { line: 0, ch: 0 });
    mirror.cm.replaceRange('',  { line: 0, ch: 0 }, { line: 0, ch: 1 });
  };

  /**
   * Add a library element string at the best position that can be found
   *
   * @param {String} uri - URI of the library to be added
   */
  mirrors.add_lib_to_markup = function(uri) {
    var markup = mirrors.get_by_id('markup');
    if (!markup || !uri) { return; }

    var indent = markup.cm.getOption('indentUnit'); // default 2
    var tag = utils.resource_tag(uri);
    var lib = utils.resource_element_string(uri); // <script ...> or <link ...>
    var indentLib = _.sprintf('%s%s', indent, lib);

    var scriptPos, linkPos, headPos, htmlPos;

    // put the new script element after the last script element in the document
    if (scriptPos = mirrors.search_last(markup, /<script [^>]*><\/script>/i)) {
      if (tag === 'script') {
        lib = _.sprintf('\n%s%s', _.repeat(' ', scriptPos.from.ch), lib);
        return mirrors.add_content_at(markup, lib, scriptPos.to);
      }
    }

    // put the new link element after the last link element in the document
    if (linkPos = mirrors.search_last(markup, /<link [^>]*>/i)) {
      if (tag === 'link') {
        lib = _.sprintf('\n%s%s', _.repeat(' ', linkPos.from.ch), lib);
        return mirrors.add_content_at(markup, lib, linkPos.to);
      }
    }

    // put the new element as the last item in <head>
    if (headPos = mirrors.search_first(markup, '</head>', true)) {
      lib = _.sprintf('%s%s\n', _.repeat(' ', indent), lib);
      return mirrors.add_content_at(markup, lib, headPos.from);
    }

    // put the new element as the first item in <head>
    if (headPos = mirrors.search_first(markup, '<head>', true)) {
      lib = _.sprintf('\n%s%s', _.repeat(' ', headPos.from.ch + indent), lib);
      return mirrors.add_content_at(markup, lib, headPos.to);
    }

    // put the new element as the first item in <html>
    if (htmlPos = mirrors.search_first(markup, '<html>', true)) {
      lib = _.sprintf('\n%s%s', _.repeat(' ', htmlPos.from.ch + indent), lib);
      return mirrors.add_content_at(markup, lib, htmlPos.to);
    }

    // last resort: just prepend the entire document
    mirrors.add_content_start(markup, lib);
  };

  return mirrors;
});
<commit_msg>Add mirrors.get_all<commit_after>/*
 * debugger.io: An interactive web scripting sandbox
 *
 * mirrors.js: CodeMirror instances
 */

define([
  'config', 'utils', 'jquery', 'underscore',
  'bus', 'codemirror', 'dom'
],
function(config, utils, $, _, bus, CodeMirror, dom) {
  'use strict';

  var mirrors = utils.module('mirrors');

  var instances = [];
  var last_focused;

  bus.init(function(av) {
    utils.log('init mirrors module');

    _.each(av.$input_panels, function(panel) {
      var $panel = $(panel);
      var $textarea = $panel.children('textarea');
      var mode = $panel.children('.mode').val();

      var cm = CodeMirror.fromTextArea($textarea[0], {
        lineNumbers: true,
        lineWrapping: true,
        mode: mode
      });

      var mirror = {
        panel: $panel.attr('id'),
        $panel: $panel,
        $textarea: $textarea,
        cm: cm,
        mode: mode
      };

      cm.on('focus', function() {
        bus.trigger('mirror:focus', mirror);
        last_focused = mirror;
      });

      mirrors.scrollable(mirror);
      instances.push(mirror);
    });

    bus.on('cdn:result:select', function(uri) {
      mirrors.add_lib_to_markup(uri);
      mirrors.refocus();
    });
  });

  /**
   * Get all active mirrors
   *
   * @return {Array} of CodeMirror instances
   */
  mirrors.get_all = function() { return instances; };

  /**
   * Get a mirror by its panel id
   *
   * @param {String} id - panel id
   * @return {CodeMirror} mirror with matching panel id, null otherwise
   */
  mirrors.get_by_id = function(id) {
    var mirror = _.find(instances, function(mirror) {
      return mirror.panel === id;
    });

    return mirror && mirror.cm instanceof CodeMirror ? mirror : null;
  };

  /**
   * Get a mirror for either its panel id or the mirror itself
   *
   * @param {String | Object} m - panel id or mirror
   * @return {CodeMirror} - null if requested mirror does not exist
   */
  mirrors.get_instance = function(m) {
    return m && m.cm instanceof CodeMirror ? m : mirrors.get_by_id(m);
  };

  /**
   * Hack for letting a scrollbar at least be a visual scroll indicator
   *
   * @param {String | Object} m - panel id or mirror
   */
  mirrors.scrollable = function(m) {
    var mirror = mirrors.get_instance(m);
    if (!mirror) { return null; }

    var $scroll = mirror.$panel.find('.CodeMirror-vscrollbar').first();
    $scroll.addClass('nano').css({ 'overflow': 'visible', 'width': '10px' });
    $scroll.children().first().addClass('content');

    dom.init_scrollbar($scroll);
    var $slider = $scroll.find('.pane > .slider');

    var track_remainder = function() {
      return $scroll.height() - $slider.height() - 4; // - margin
    };

    // update the scrollbar to match the current mirror position
    var update_scrollbar = function(info, remainder) {
      info = info || mirror.cm.getScrollInfo();
      remainder = remainder || track_remainder();

      var multiplier = (info.top / (info.height - info.clientHeight)) || 0;

      $slider.css({ 'top': multiplier * remainder });
      $scroll.css({
        'display': info.height > info.clientHeight ? 'block' : 'none'
      });
    };

    // update the mirror position to match the current scrollbar position
    var update_mirror_scroll = function(info, remainder) {
      info = info || mirror.cm.getScrollInfo();
      remainder = remainder || track_remainder();

      var top = parseInt($slider.css('top'), 10);
      var multiplier = top / remainder;
      mirror.cm.scrollTo(null, multiplier * (info.height - info.clientHeight));
    };

    (function() {
      var mde; // mousedown event
      var top = 0;
      var info;
      var remainder;

      var bind_scroll = function(e) {
        mde = e;
        top = parseInt($slider.css('top'), 10);
        info = mirror.cm.getScrollInfo();
        remainder = track_remainder();

        $(document).on('mousemove', do_scroll);
        $(document).on('mouseup', unbind_scroll);
      };

      var unbind_scroll = function(e) {
        $(document).off('mousemove', do_scroll);
        $(document).off('mouseup', unbind_scroll);
      };

      var do_scroll = function(e) {
        var distanceY = e.pageY - mde.pageY;
        $slider.css('top', utils.clamp(top + distanceY, 0, remainder));

        update_mirror_scroll(info, remainder);
      };

      // let the user drag the scrollbars
      $slider.on('mousedown', bind_scroll);
    })();

    // or, click on the track to move the scrollbar
    $scroll.on('click', function(e) {
      if ($slider.is(e.target)) { return; }

      var midPoint = e.offsetY - $slider.height() / 2;
      var newTop = utils.clamp(midPoint, 0, track_remainder());
      $slider.css('top', newTop);

      update_mirror_scroll();
    });

    mirror.cm.on('change', function() {
      $scroll[0].nanoscroller.reset();
      update_scrollbar();
    });

    mirror.cm.on('scroll', function() {
      update_scrollbar();
    });

    bus.on('panels:resizing', function() {
      _.defer(function() { CodeMirror.signal(mirror.cm, 'change'); });
    });

    bus.on('window:resize panels:resized', function() {
      _.defer(function() { mirrors.simulate_change(mirror); });
    });
  };

  var mirror_mode_sets = {
    'markup': [
      { label: 'HTML', mode: 'htmlmixed' },
      { label: 'Markdown', mode: 'gfm' }
    ],
    'style': [
      { label: 'CSS', mode: 'css' },
      { label: 'LESS', mode: 'less' },
      { label: 'SCSS', mode: 'scss', cm_mode: 'text/x-scss' }
    ],
    'script': [
      { label: 'JavaScript', mode: 'javascript' },
      { label: 'CoffeeScript', mode: 'coffeescript' },
      {
        label: 'TypeScript', mode: 'typescript',
        cm_mode: 'application/typescript'
      }, {
        label: 'GorillaScript', mode: 'gorillascript',
        cm_mode: 'javascript'
      }
    ]
  };

  var get_mode_set = function(panel, mode) {
    return _.find(mirror_mode_sets[panel], function(set) {
      return set.mode === mode || set.cm_mode === mode;
    });
  };

  /**
   * Get the mode for a mirror
   *
   * @param {String | Object} m - panel id or mirror
   * @return {String} current mirror mode
   */
  mirrors.get_mode = function(m) {
    var mirror = mirrors.get_instance(m);
    if (!mirror) { return null; }

    return mirror.mode;
  };

  /**
   * Set the mode for a mirror
   *
   * @param {String | Object} m - panel id or mirror
   * @param {String} mode - new mode to set
   */
  mirrors.set_mode = function(m, mode) {
    var mirror = mirrors.get_instance(m);
    if (!mirror || !_.isString(mode)) { return; }

    var set = get_mode_set(mirror.panel, mode);
    if (!set) { return; }

    mirror.cm.setOption('mode', set.cm_mode || set.mode);
    mirror.mode = set.mode;

    var eventName = _.sprintf('mirrors:%s:mode', mirror.panel);
    bus.trigger(eventName, set.mode, set.label);
  };

  /**
   * Rotate a mirror through available modes
   *
   * @param {String | Object} m - panel id or mirror
   */
  mirrors.cycle_mode = function(m) {
    var mirror = mirrors.get_instance(m);
    var panel = mirror.panel;

    var modes = mirror_mode_sets[panel];
    var mode = mirrors.get_mode(panel);
    if (!modes) { return; }

    var set = get_mode_set(panel, mode);
    var i = _.indexOf(modes, set);

    var newMode = modes[++i % modes.length];
    mirrors.set_mode(panel, newMode.mode);
  };

  /**
   * Get the theme for a mirror
   *
   * @param {String | Object} m - panel id or mirror
   * @return {String} current mirror theme
   */
  mirrors.get_theme = function(m) {
    var mirror = mirrors.get_instance(m);
    if (!mirror) { return null; }

    return mirror.cm.getOption('theme');
  };

  /**
   * Set the theme for a mirror
   *
   * @param {String | Object} m - panel id or mirror
   * @param {String} theme - new theme to set
   */
  mirrors.set_theme = function(m, theme) {
    var mirror = mirrors.get_instance(m);
    if (!mirror || !_.isString(theme)) { return; }

    mirror.cm.setOption('theme', theme);
  };

  /**
   * Set the theme for all mirrors
   *
   * @param {String} theme - new theme to set
   */
  mirrors.set_theme_all = function(theme) {
    _.each(instances, function(mirror) {
      mirrors.set_theme(mirror, theme);
    });
  };

  /**
   * Set the cursor focus on a mirror
   *
   * @param {String | Object} m - panel id or mirror
   */
  mirrors.focus = function(m) {
    var mirror = mirrors.get_instance(m);
    if (!mirror) { return; }

    mirror.cm.focus();
  };

  /**
   * Refocus the last focused mirror
   */
  mirrors.refocus = function() {
    mirrors.focus(last_focused);
  };

  /**
   * Search a mirror for the first occurrence of a string
   *
   * @param {String | Object} m - panel id or mirror
   * @param {String | RegExp} str - string to search for
   * @param {Boolean} ci - if true, search is case-insensitive
   * @return {Object} position map { line, ch } if found, null otherwise
   */
  mirrors.search_first = function(m, str, ci) {
    var mirror = mirrors.get_instance(m);
    if (!mirror || (!_.isString(str) && !_.isRegExp(str))) { return null; }

    var cur = mirror.cm.getSearchCursor(str, null, !!ci);
    return (cur && cur.find()) ? { from: cur.from(), to: cur.to() } : null;
  };

  /**
   * Search a mirror for the last occurrence of a string
   *
   * @param {String | Object} m - panel id or mirror
   * @param {String | RegExp} str - string to search for
   * @param {Boolean} ci - if true, search is case-insensitive
   * @return {Object} position map { line, ch } if found, null otherwise
   */
  mirrors.search_last = function(m, str, ci) {
    var mirror = mirrors.get_instance(m);
    if (!mirror || (!_.isString(str) && !_.isRegExp(str))) { return null; }

    var cur = mirror.cm.getSearchCursor(str, null, !!ci);

    var pos;
    while (cur && cur.find()) {
      pos = { from: cur.from(), to: cur.to() };
    }

    return pos || null;
  };

  /**
   * Add content to a mirror at a specific position
   *
   * @param {String | Object} m - panel id or mirror
   * @param {String} str - content to add
   * @param {Object} pos - position map { line, ch } to insert at
   */
  mirrors.add_content_at = function(m, str, pos) {
    var mirror = mirrors.get_instance(m);
    if (!mirror || !_.isString(str)) { return; }

    mirror.cm.replaceRange(str, pos);
  };

  /**
   * Add content to a mirror as the first line(s)
   *
   * @param {String | Object} m - panel id or mirror
   * @param {String} str - content to add
   */
  mirrors.add_content_start = function(m, str) {
    if (!_.isString(str)) { return; }
    return mirrors.add_content_at(m, str + '\n', { line: 0, ch: 0 });
  };

  /**
   * Add content to a mirror as the last line(s)
   *
   * @param {String | Object} m - panel id or mirror
   * @param {String} str - content to add
   */
  mirrors.add_content_end = function(m, str) {
    var mirror = mirrors.get_instance(m);
    if (!mirror || !_.isString(str)) { return; }

    var lastLine = mirror.cm.lastLine();
    var lastLineContent = mirror.cm.getLine(lastLine);
    var nlStr = !lastLineContent ? str : '\n' + str;

    return mirrors.add_content_at(m, nlStr, { line: lastLine });
  };

  /**
   * Trigger a real change event by inserting and then removing a character
   *
   * @param {String | Object} m - panel id or mirror
   */
  mirrors.simulate_change = function(m) {
    var mirror = mirrors.get_instance(m);
    if (!mirror) { return; }

    mirror.cm.replaceRange(' ', { line: 0, ch: 0 });
    mirror.cm.replaceRange('',  { line: 0, ch: 0 }, { line: 0, ch: 1 });
  };

  /**
   * Add a library element string at the best position that can be found
   *
   * @param {String} uri - URI of the library to be added
   */
  mirrors.add_lib_to_markup = function(uri) {
    var markup = mirrors.get_by_id('markup');
    if (!markup || !uri) { return; }

    var indent = markup.cm.getOption('indentUnit'); // default 2
    var tag = utils.resource_tag(uri);
    var lib = utils.resource_element_string(uri); // <script ...> or <link ...>
    var indentLib = _.sprintf('%s%s', indent, lib);

    var scriptPos, linkPos, headPos, htmlPos;

    // put the new script element after the last script element in the document
    if (scriptPos = mirrors.search_last(markup, /<script [^>]*><\/script>/i)) {
      if (tag === 'script') {
        lib = _.sprintf('\n%s%s', _.repeat(' ', scriptPos.from.ch), lib);
        return mirrors.add_content_at(markup, lib, scriptPos.to);
      }
    }

    // put the new link element after the last link element in the document
    if (linkPos = mirrors.search_last(markup, /<link [^>]*>/i)) {
      if (tag === 'link') {
        lib = _.sprintf('\n%s%s', _.repeat(' ', linkPos.from.ch), lib);
        return mirrors.add_content_at(markup, lib, linkPos.to);
      }
    }

    // put the new element as the last item in <head>
    if (headPos = mirrors.search_first(markup, '</head>', true)) {
      lib = _.sprintf('%s%s\n', _.repeat(' ', indent), lib);
      return mirrors.add_content_at(markup, lib, headPos.from);
    }

    // put the new element as the first item in <head>
    if (headPos = mirrors.search_first(markup, '<head>', true)) {
      lib = _.sprintf('\n%s%s', _.repeat(' ', headPos.from.ch + indent), lib);
      return mirrors.add_content_at(markup, lib, headPos.to);
    }

    // put the new element as the first item in <html>
    if (htmlPos = mirrors.search_first(markup, '<html>', true)) {
      lib = _.sprintf('\n%s%s', _.repeat(' ', htmlPos.from.ch + indent), lib);
      return mirrors.add_content_at(markup, lib, htmlPos.to);
    }

    // last resort: just prepend the entire document
    mirrors.add_content_start(markup, lib);
  };

  return mirrors;
});
<|endoftext|>


<commit_before>define(function (require) {
  var moment = require('moment');
  var dateMath = require('ui/utils/dateMath');
  var module = require('ui/modules').get('kibana/kibana-time-plugin', ['kibana', 'BootstrapAddons']);
  var _ = require('lodash');
  require('ui/timepicker/quick_ranges');
  require('ui/timepicker/time_units');

  module.controller('KbnTimeVisController', function (quickRanges, timeUnits, $scope, $rootScope, Private, $filter, $timeout) {
    $rootScope.plugin = {
      timePlugin: {}
    };
    $scope.config = {
        title: ""
    };

    $rootScope.$watchMulti([
      '$$timefilter.time.from',
      '$$timefilter.time.to',
      '$$timefilter.time.mode'
    ], setTime);

    var changeVisOff = $rootScope.$on('change:vis', function () {
      $scope.$broadcast('timesliderForceRender');
      //_.debounce(resize, 250);
    });
    $scope.$on('$destroy', function() {
      changeVisOff();
    });

    $scope.quickLists = quickRanges;
    $scope.units = timeUnits;
    $scope.relativeOptions = [
      {text: 'Seconds ago', value: 's'},
      {text: 'Minutes ago', value: 'm'},
      {text: 'Hours ago', value: 'h'},
      {text: 'Days ago', value: 'd'},
      {text: 'Weeks ago', value: 'w'},
      {text: 'Months ago', value: 'M'},
      {text: 'Years ago', value: 'y'},
    ];
    $scope.relative = {
      count: 1,
      unit: 'm',
      preview: undefined,
      round: false
    };
    $scope.time = {
      from: moment(),
      to: moment(),
      mode: ""
    };

    function setTime(rangeA) {
      var from = rangeA[0];
      var to = rangeA[1];
      var mode = rangeA[2];
      var ours_ms = {
        from: dateMath.parse($scope.time.from).toDate().getTime(),
        to: dateMath.parse($scope.time.to).toDate().getTime()
      }
      var theirs_ms = {
        from: dateMath.parse(from).toDate().getTime(),
        to: dateMath.parse(to).toDate().getTime()
      }
      console.log("from, ours: " + ours_ms.from + ", theirs: " + theirs_ms.from);
      console.log("to, ours: " + ours_ms.to + ", theirs: " + theirs_ms.to);
      console.log("mode, ours: " + $scope.time.mode + ", theirs: " + mode);

      //setTime is called from watching kibana's timefilter
      //Avoid updating our $scope if the timefilter change is triggered by us
      if($scope.time.mode !== mode
        || Math.abs(ours_ms.from - theirs_ms.from) > 500
        || Math.abs(ours_ms.to - theirs_ms.to) > 500) {
        console.log("updating KbnTimeVisController.$scope stay in sync with kibana timefilter");
        //clean up old selections
        $scope.activeSlide = {
          absolute: false,
          quick: false,
          relative: false
        };

        //set new selections based on new time
        $scope.time = {
          from: from,
          to: to,
          mode: mode,
          absolute_from: dateMath.parse(from),
          absolute_to: dateMath.parse(to, true)
        }
        setRelativeParts(to, from);
        if('quick' === $rootScope.$$timefilter.time.mode) {
          $scope.activeSlide.quick = true;
          for(var i=0; i<quickRanges.length; i++) {
            if(quickRanges[i].from === from && quickRanges[i].to === to) {
              $scope.selectedQuick = quickRanges[i];
              $scope.time.title = quickRanges[i].display;
              break;
            }
          }
        } else if ('relative' === $rootScope.$$timefilter.time.mode) {
          $scope.activeSlide.relative = true;
          $scope.time.title = "";
        } else {
          $scope.activeSlide.absolute = true;
          $scope.time.title = "";
        }
      }
    }
    setTime([
      $rootScope.$$timefilter.time.from,
      $rootScope.$$timefilter.time.to,
      $rootScope.$$timefilter.time.mode]);

    $scope.filterByTime = function() {
      console.log('filterByTime not implemented');
    }

    $scope.removeTimeFilter = function() {
      console.log('removeTimeFilter not implemented');
    }

    $scope.setAbsolute = function() {
      $scope.time.mode = 'absolute';
      $scope.time.from = $scope.time.absolute_from;
      $scope.time.to = $scope.time.absolute_to;
      updateKbnTime();
    };

    $scope.setRelative = function () {
      $scope.time.title = 'relative title';
      $scope.time.from = getRelativeString();
      $scope.time.to = 'now';
      $scope.time.mode = 'relative';
      updateKbnTime();
    };

    $scope.setQuick = function (selectedQuick) {
      $scope.time.title = selectedQuick.display;
      $scope.time.from = selectedQuick.from;
      $scope.time.to = selectedQuick.to;
      $scope.time.mode = 'quick';
      updateKbnTime();
    };

    function updateKbnTime() {
      $rootScope.$$timefilter.time.from = $scope.time.from;
      $rootScope.$$timefilter.time.to = $scope.time.to;
      $rootScope.$$timefilter.time.mode = $scope.time.mode;

      //keep other carousel slides in sync with new values
      if($scope.time.mode !== 'absolute') {
        $scope.time.absolute_from = dateMath.parse($scope.time.from);
        $scope.time.absolute_to = dateMath.parse($scope.time.to, true);
      }
      if($scope.time.mode !== 'relative') {
        //wrapped in $timeout to avoid calling $apply while all ready in progress
        $timeout(setRelativeParts($scope.time.to, $scope.time.from), 0);
      }
    }

    $scope.$watch('vis.params.title', function (title) {
      $scope.config.title = title;
    });

    //Relative date logic copied from https://github.com/elastic/kibana/blob/4.4/src/ui/public/timepicker/timepicker.js

    //convert to and from into pieces needed for relative inputs
    function setRelativeParts(to, from) {
      var fromParts = from.toString().split('-');
      var relativeParts = [];

      // Try to parse the relative time, if we can't use moment duration to guestimate
      if (to.toString() === 'now' && fromParts[0] === 'now' && fromParts[1]) {
        relativeParts = fromParts[1].match(/([0-9]+)([smhdwMy]).*/);
      }
      if (relativeParts[1] && relativeParts[2]) {
        $scope.relative.count = parseInt(relativeParts[1], 10);
        $scope.relative.unit = relativeParts[2];
      } else {
        var duration = moment.duration(moment().diff(dateMath.parse(from)));
        var units = _.pluck(_.clone($scope.relativeOptions).reverse(), 'value');
        if (from.toString().split('/')[1]) $scope.relative.round = true;
        for (var i = 0; i < units.length; i++) {
          var as = duration.as(units[i]);
          if (as > 1) {
            $scope.relative.count = Math.round(as);
            $scope.relative.unit = units[i];
            break;
          }
        }
      }

      if (from.toString().split('/')[1]) $scope.relative.round = true;
      formatRelative();
    }
    function formatRelative() {
      var parsed = dateMath.parse(getRelativeString());
      $scope.relative.preview =  parsed ? parsed.format($scope.format) : undefined;
      return parsed;
    }
    $scope.formatRelative = formatRelative;

    function getRelativeString() {
      return 'now-' + $scope.relative.count + $scope.relative.unit + ($scope.relative.round ? '/' + $scope.relative.unit : '');
    }
  });
});
<commit_msg>add handlers for timeslider<commit_after>define(function (require) {
  var moment = require('moment');
  var dateMath = require('ui/utils/dateMath');
  var module = require('ui/modules').get('kibana/kibana-time-plugin', ['kibana', 'BootstrapAddons']);
  var _ = require('lodash');
  require('ui/timepicker/quick_ranges');
  require('ui/timepicker/time_units');

  module.controller('KbnTimeVisController', function (quickRanges, timeUnits, $scope, $rootScope, Private, $filter, $timeout) {
    $rootScope.plugin = {
      timePlugin: {}
    };
    $scope.config = {
        title: ""
    };

    $rootScope.$watchMulti([
      '$$timefilter.time.from',
      '$$timefilter.time.to'
    ], setTime);

    var changeVisOff = $rootScope.$on('change:vis', function () {
      $scope.$broadcast('timesliderForceRender');
      //_.debounce(resize, 250);
    });
    $scope.$on('$destroy', function() {
      changeVisOff();
    });

    var expectedFrom = moment();
    var expectedTo = moment();
    $scope.quickLists = quickRanges;
    $scope.units = timeUnits;
    $scope.relativeOptions = [
      {text: 'Seconds ago', value: 's'},
      {text: 'Minutes ago', value: 'm'},
      {text: 'Hours ago', value: 'h'},
      {text: 'Days ago', value: 'd'},
      {text: 'Weeks ago', value: 'w'},
      {text: 'Months ago', value: 'M'},
      {text: 'Years ago', value: 'y'},
    ];
    $scope.relative = {
      count: 1,
      unit: 'm',
      preview: undefined,
      round: false
    };
    $scope.time = {
      from: moment(),
      to: moment()
    };

    function setTime(rangeA) {
      var from = rangeA[0];
      var to = rangeA[1];
      var ours_ms = {
        from: expectedFrom.toDate().getTime(),
        to: expectedTo.toDate().getTime()
      }
      var theirs_ms = {
        from: dateMath.parse(from).toDate().getTime(),
        to: dateMath.parse(to).toDate().getTime()
      }
      console.log("from, ours: " + ours_ms.from + ", theirs: " + theirs_ms.from);
      console.log("to, ours: " + ours_ms.to + ", theirs: " + theirs_ms.to);

      //setTime is called from watching kibana's timefilter
      //Avoid updating our $scope if the timefilter change is triggered by us
      if(Math.abs(ours_ms.from - theirs_ms.from) > 500
        || Math.abs(ours_ms.to - theirs_ms.to) > 500) {
        console.log("updating KbnTimeVisController.$scope stay in sync with kibana timefilter");
        //clean up old selections
        $scope.activeSlide = {
          absolute: false,
          quick: false,
          relative: false
        };

        //set new selections based on new time
        $scope.time = {
          from: from,
          to: to,
          absolute_from: dateMath.parse(from),
          absolute_to: dateMath.parse(to, true)
        }
        setRelativeParts(to, from);
        if('quick' === $rootScope.$$timefilter.time.mode) {
          $scope.activeSlide.quick = true;
          for(var i=0; i<quickRanges.length; i++) {
            if(quickRanges[i].from === from && quickRanges[i].to === to) {
              $scope.selectedQuick = quickRanges[i];
              $scope.time.title = quickRanges[i].display;
              break;
            }
          }
        } else if ('relative' === $rootScope.$$timefilter.time.mode) {
          $scope.activeSlide.relative = true;
          $scope.time.title = "";
        } else {
          $scope.activeSlide.absolute = true;
          $scope.time.title = "";
        }
        updateTimeslider();
      }
    }
    setTime([
      $rootScope.$$timefilter.time.from,
      $rootScope.$$timefilter.time.to]);

    $scope.filterByTime = function(start, end) {
      console.log("timeslider - Filtering by time");
      $scope.time.mode = 'absolute';
      expectedFrom = moment(start);
      expectedTo = moment(end);
      updateKbnTime();
    }

    $scope.removeTimeFilter = function() {
      console.log("timeslider - removing time filter");
      expectedFrom = dateMath.parse($scope.time.from);
      expectedTo = dateMath.parse($scope.time.to, true);
      updateKbnTime();
    }

    $scope.setAbsolute = function() {
      $scope.time.mode = 'absolute';
      $scope.time.from = $scope.time.absolute_from;
      $scope.time.to = $scope.time.absolute_to;
      expectedFrom = dateMath.parse($scope.time.from);
      expectedTo = dateMath.parse($scope.time.to, true);
      updateKbnTime();
    };

    $scope.setRelative = function () {
      $scope.time.title = 'relative title';
      $scope.time.from = getRelativeString();
      $scope.time.to = 'now';
      $scope.time.mode = 'relative';
      expectedFrom = dateMath.parse($scope.time.from);
      expectedTo = dateMath.parse($scope.time.to, true);
      updateKbnTime();
    };

    $scope.setQuick = function (selectedQuick) {
      $scope.time.title = selectedQuick.display;
      $scope.time.from = selectedQuick.from;
      $scope.time.to = selectedQuick.to;
      $scope.time.mode = 'quick';
      expectedFrom = dateMath.parse($scope.time.from);
      expectedTo = dateMath.parse($scope.time.to, true);
      updateKbnTime();
    };

    function updateKbnTime() {
      $rootScope.$$timefilter.time.from = expectedFrom;
      $rootScope.$$timefilter.time.to = expectedTo;
      $rootScope.$$timefilter.time.mode = $scope.time.mode;
      console.log("updated kibana mode to " + $scope.time.mode);
      $timeout(function() {
        console.log("double check mode: " + $scope.time.mode);
      }, 0);

      //keep other carousel slides in sync with new values
      if($scope.time.mode !== 'absolute') {
        $scope.time.absolute_from = dateMath.parse($scope.time.from);
        $scope.time.absolute_to = dateMath.parse($scope.time.to, true);
      }
      if($scope.time.mode !== 'relative') {
        //wrapped in $timeout to avoid calling $apply while all ready in progress
        $timeout(setRelativeParts($scope.time.to, $scope.time.from), 0);
      }
      //updateTimeslider();
    }

    function updateTimeslider() {
      $timeout(function() {
        $scope.$broadcast('timesliderForceRender');
      }, 0);
    }

    $scope.$watch('vis.params.title', function (title) {
      $scope.config.title = title;
    });

    //Relative date logic copied from https://github.com/elastic/kibana/blob/4.4/src/ui/public/timepicker/timepicker.js

    //convert to and from into pieces needed for relative inputs
    function setRelativeParts(to, from) {
      var fromParts = from.toString().split('-');
      var relativeParts = [];

      // Try to parse the relative time, if we can't use moment duration to guestimate
      if (to.toString() === 'now' && fromParts[0] === 'now' && fromParts[1]) {
        relativeParts = fromParts[1].match(/([0-9]+)([smhdwMy]).*/);
      }
      if (relativeParts[1] && relativeParts[2]) {
        $scope.relative.count = parseInt(relativeParts[1], 10);
        $scope.relative.unit = relativeParts[2];
      } else {
        var duration = moment.duration(moment().diff(dateMath.parse(from)));
        var units = _.pluck(_.clone($scope.relativeOptions).reverse(), 'value');
        if (from.toString().split('/')[1]) $scope.relative.round = true;
        for (var i = 0; i < units.length; i++) {
          var as = duration.as(units[i]);
          if (as > 1) {
            $scope.relative.count = Math.round(as);
            $scope.relative.unit = units[i];
            break;
          }
        }
      }

      if (from.toString().split('/')[1]) $scope.relative.round = true;
      formatRelative();
    }
    function formatRelative() {
      var parsed = dateMath.parse(getRelativeString());
      $scope.relative.preview =  parsed ? parsed.format($scope.format) : undefined;
      return parsed;
    }
    $scope.formatRelative = formatRelative;

    function getRelativeString() {
      return 'now-' + $scope.relative.count + $scope.relative.unit + ($scope.relative.round ? '/' + $scope.relative.unit : '');
    }
  });
});
<|endoftext|>


<commit_before>/**
 * Search the index of an object in an array of objects.
 *
 * @param {Array} array - The array where the function will search.
 * @param {String} searchTerm - The string that the function needs to find in the array of objects.
 * @param {String} property - The property of every object where the function will search.
 * @returns {Number} If the object was found the functions returns a number greater than -1; otherwise, the function returns -1.
 */
var arrayObjectIndexOf = function (array, searchTerm, property) {
        for (var i = 0, len = array.length; i < len; i++) {
            if (array[i][property] === searchTerm) {
                return i;
            }
        }
        return -1;
    };
	<commit_msg>Added lastindexof<commit_after>/**
 * Search the index of an object in an array of objects.
 *
 * @param {Array} array - The array where the function will search.
 * @param {String} searchTerm - The string that the function needs to find in the array of objects.
 * @param {String} property - The property of an object where the function will search.
 * @returns {Number} If the object was found the functions returns a number greater than -1; otherwise, the function returns -1.
 */
var indexOf = function (array, searchTerm, property) {
        for (var i = 0, len = array.length; i < len; i++) {
            if (array[i][property] === searchTerm) {
                return i;
            }
        }
        return -1;
    };

/**
 * Search the last index of an object in an array of objects.
 *
 * @param {Array} array - The array where the function will search.
 * @param {String} searchTerm - The string that the function needs to find in the array of objects.
 * @param {String} property - The property of an object where the function will search.
 * @param {String} alternativeProperty - The alternative property of an object where the function will search.
 * @returns {Number} If the object was found the functions returns a number greater than -1; otherwise, the function returns -1.
 */
var lastIndexOf = function (array, searchTerm, property, alternativeProperty) {
        for (var i = array.length - 1 ; i >= 0 ; i--) {
            if (array[i][property] === searchTerm) {
                return i;
            } else if (array[i][alternativeProperty] === searchTerm) {
                return i;
            }
        }
        return -1;
    };<|endoftext|>


<commit_before>(function () {
	'use strict';

	const View = window.View;

	class PlayView extends View {

		constructor() {
			super('js-play');
		}

		init() {
			this._el.innerHTML = '';
		}
	}

	window.PlayView = PlayView;
})();
<commit_msg>Предзащита<commit_after>(function () {
	'use strict';

	const View = window.View;

	class PlayView extends View {

		constructor() {
			super('js-play');
		}

		init() {
			this._el.innerHTML = '';
			this._el.addEventListener('click', () => {
				window.location.href = 'https://share.proto.io/GBTQEN/';
			});
			this._el.style = 'cursor:pointer;';
		}
	}

	window.PlayView = PlayView;
})();
<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');

var acquireRefs = require('../lib/acquireRefs');
var Command = require('../lib/command');
var deploy = require('../lib/deploy');
var previews = require('../lib/previews');
var requireConfig = require('../lib/requireConfig');
var scopes = require('../lib/scopes');

// in order of least time-consuming to most time-consuming
var VALID_TARGETS = ['database', 'storage', 'functions', 'hosting'];
if (!previews.functions) {
  VALID_TARGETS.splice(2, 1);
}

var deployScopes = previews.functions ? [scopes.CLOUD_PLATFORM] : [];

module.exports = new Command('deploy')
  .description('deploy code and assets to your Firebase project')
  .option('-p, --public <path>', 'override the Hosting public directory specified in firebase.json')
  .option('-m, --message <message>', 'an optional message describing this deploy')
  .option('--only <targets>', 'only deploy to specified, comma-separated targets (e.g. "hosting,storage")')
  .before(requireConfig)
  .before(acquireRefs, deployScopes)
  .action(function(options) {
    var targets = VALID_TARGETS;
    if (options.only) {
      targets = _.intersection(targets, options.only.split(','));
    }
    return deploy(targets, options);
  });
<commit_msg>Adds --except to deploy (#90)<commit_after>'use strict';

var _ = require('lodash');

var acquireRefs = require('../lib/acquireRefs');
var Command = require('../lib/command');
var deploy = require('../lib/deploy');
var previews = require('../lib/previews');
var requireConfig = require('../lib/requireConfig');
var scopes = require('../lib/scopes');
var utils = require('../lib/utils');

// in order of least time-consuming to most time-consuming
var VALID_TARGETS = ['database', 'storage', 'functions', 'hosting'];
if (!previews.functions) {
  VALID_TARGETS.splice(2, 1);
}

var deployScopes = previews.functions ? [scopes.CLOUD_PLATFORM] : [];

module.exports = new Command('deploy')
  .description('deploy code and assets to your Firebase project')
  .option('-p, --public <path>', 'override the Hosting public directory specified in firebase.json')
  .option('-m, --message <message>', 'an optional message describing this deploy')
  .option('--only <targets>', 'only deploy to specified, comma-separated targets (e.g. "hosting,storage")')
  .option('--except <targets>', 'deploy to all targets except specified (e.g. "database")')
  .before(requireConfig)
  .before(acquireRefs, deployScopes)
  .action(function(options) {
    var targets = VALID_TARGETS;
    if (options.only && options.except) {
      return utils.reject('Cannot specify both --only and --except', {exit: 1});
    }

    if (options.only) {
      targets = _.intersection(targets, options.only.split(','));
    } else if (options.except) {
      targets = _.difference(targets, options.except.split(','));
    }

    return deploy(targets, options);
  });
<|endoftext|>


<commit_before>// registers all event listeners and logic for the user portal dashboard
$(document).ready(function () {
  // initialize the dashboard with none of the tabs showing
  $('#contactsTab').hide();
  $('#composeTab').hide();
  $('#messagesTab').hide();

  // Event Listener for Home NavBar Button
  $('#home').on('click', function () {
    $('.tab').hide();
    $('#homeTab').show();
    $('.table').empty();

    $.getJSON("/dashboard/userInfo", function (userInfo) {
		$('#userName').html("Username: " + userInfo.username);
		$('#userEmail').html("Email: " + userInfo.email);
		$('#userTitle').html("Title: " +userInfo.job_title);
		$('#homeTitle').html("Profile Info");
    });

    $('#homeTab').show();
  });

  // Event Listener for Message NavBar Button
  $('#messages').on('click', function () {
    // Hides all tabs that are not the message tab
    $('.tab:not(#messagesTab)').hide();

    // Empties all of the tables that are not the messages table
    $('.table:not(#messagesTable)').empty();

    // if the message tab is not currently displayed fetch the data and display it
    if ($('#messagesTab').css('display') == 'none') {
      $.getJSON("/dashboard/messages", function (messages) {
        $("#messagesTable").append ("
  Sender 	  Receiver 	  Content
");
        $.each (messages, function (index, message) {
          $("#messagesTable").append ("
" + message.sender + "	" + message.receiver + "	" + message.content + "
");
        });
      });

      $('#messagesTab').show();
    }
  });

  // Event Listener for Compose Message NavBar Button
  $('#compose').on('click', function () {
    $('.tab:not(#composeTab)').hide();
    $('.table').empty();
    $('#composeTab').show();
  });

  // Event Listener for the close compose message tab
  $('#closeComposeButton').on ('click', function () {
    $('#composeTab').hide();
  });

  // Event Listener for send message button
  $('#send').on ('click', function () {
	  var messageText = $('#messageText').val();
	  var recipient = $('userRecipient').val();
	  var messageTitle = $('composeTitle').val();
	  var data = {
		  val: messageText,
		  title: messageTitle,
		  user: recipient,
	}
    $.post ('/dashboard/compose/send', data, function (message) {
      console.log (messageText);
      $('#closeComposeButton').trigger('click');
    })
    .fail(function (err) {
      console.log (err);
    });
  });

  // Event Listener for Contacts NavBar button
  $('.contacts').on('click', function () {
    $('.tab:not(#contactsTab)').hide();
    $('.table:not(#contactsTable)').empty();

    if ($('#contactsTab').css('display') == 'none') {
      $.getJSON("/dashboard/contacts", function (contacts) {
        $("#contactsTable").append("
  UserName 	  Email 	  Job Title
");
        $.each(contacts, function (index, contact) {
          $("#contactsTable").append("
" + contact.username + "	" + contact.email + "	" + contact.job_title + "
");
        });
      });

      $('#contactsTab').show();
    }
  });

  // Event Listener for the close contacts tab
  $('#closeContactsButton').on ('click', function () {
    $('#contactsTab').hide();
  });
});
<commit_msg>Update dashboard.js<commit_after>// registers all event listeners and logic for the user portal dashboard
$(document).ready(function () {
  // initialize the dashboard with none of the tabs showing
  $('#contactsTab').hide();
  $('#composeTab').hide();
  $('#messagesTab').hide();

  // Event Listener for Home NavBar Button
  $('#home').on('click', function () {
    $('.tab').hide();
    $('#homeTab').show();
    $('.table').empty();

    $.getJSON("/dashboard/userInfo", function (userInfo) {
		$('#userName').html("Username: " + userInfo.username);
		$('#userEmail').html("Email: " + userInfo.email);
		$('#userTitle').html("Title: " +userInfo.job_title);
		$('#homeTitle').html("Profile Info");
    });

    $('#homeTab').show();
  });

  // Event Listener for Message NavBar Button
  $('#messages').on('click', function () {
    // Hides all tabs that are not the message tab
    $('.tab:not(#messagesTab)').hide();

    // Empties all of the tables that are not the messages table
    $('.table:not(#messagesTable)').empty();

    // if the message tab is not currently displayed fetch the data and display it
    if ($('#messagesTab').css('display') == 'none') {
      $.getJSON("/dashboard/messages", function (messages) {
        $("#messagesTable").append ("
  Sender 	  Receiver 	  Content
");
        $.each (messages, function (index, message) {
          $("#messagesTable").append ("
" + message.sender + "	" + message.receiver + "	" + message.content + "
");
        });
      });

      $('#messagesTab').show();
    }
  });

  // Event Listener for Compose Message NavBar Button
  $('#compose').on('click', function () {
    $('.tab:not(#composeTab)').hide();
    $('.table').empty();
    $('#composeTab').show();
  });

  // Event Listener for the close compose message tab
  $('#closeComposeButton').on ('click', function () {
    $('#composeTab').hide();
  });

  // Event Listener for send message button
  $('#send').on ('click', function () {
	  var messageText = $('#messageText').val();
	  var recipient = $('#userRecipient').val();
	  var messageTitle = $('#composeTitle').val();
	  var data = {
		  val: messageText,
		  title: messageTitle,
		  user: recipient
	}
    $.post ('/dashboard/compose/send', data, function (message) {
      console.log (messageText);
      $('#closeComposeButton').trigger('click');
    })
    .fail(function (err) {
      console.log (err);
    });
  });

  // Event Listener for Contacts NavBar button
  $('.contacts').on('click', function () {
    $('.tab:not(#contactsTab)').hide();
    $('.table:not(#contactsTable)').empty();

    if ($('#contactsTab').css('display') == 'none') {
      $.getJSON("/dashboard/contacts", function (contacts) {
        $("#contactsTable").append("
  UserName 	  Email 	  Job Title
");
        $.each(contacts, function (index, contact) {
          $("#contactsTable").append("
" + contact.username + "	" + contact.email + "	" + contact.job_title + "
");
        });
      });

      $('#contactsTab').show();
    }
  });

  // Event Listener for the close contacts tab
  $('#closeContactsButton').on ('click', function () {
    $('#contactsTab').hide();
  });
});
<|endoftext|>


<commit_before>
var augur = (function () {
  'use strict';

  function dotProduct(element1, element2) {
    return element1.reduce(function (prev, current, idx) {
      return prev * (idx - 1 ? 1 : element2[idx - 1]) + current * element2[idx];
    });
  }

  function selfDotProduct(element) {
    return dotProduct(element, element);
  }

  /**
   * SVR kernel RBF
   * config:
   * - supportVectors ([float])
   * - dualCoefs ([float]): dual_coefs_ are values used by scikit-learn
   * - epsilon (float)
   * - bias (float)
   * - Xmins ([float])
   * - Xmaxs ([float])
   * - Xmeans ([float])
   * - ymin (float)
   * - ymax (float)
   * - ymean (float)
   */

  function SVR(config) {
    this.supportVectors = config.supportVectors;
    this.dualCoefs = config.dualCoefs;
    this.epsilon = config.epsilon;
    this.bias = config.bias;

    this.Xmins = config.Xmins;
    this.Xmaxs = config.Xmaxs;
    this.Xmeans = config.Xmeans;

    this.ymin = config.ymin;
    this.ymax = config.ymax;
    this.ymean = config.ymean;
  }

  /**
   * predict:
   * - element ([float]): values you want to predict
   */
  SVR.prototype.predict = function (element) {
    var sum = 0.0,
        scaledElement = this._normalize(element),
        x1Square = selfDotProduct(scaledElement),
        x2Square, dot;

    for (var i = 0; i < this.supportVectors.length; i++) {
      x2Square = selfDotProduct(this.supportVectors[i]);
      dot = dotProduct(scaledElement, this.supportVectors[i]);
      sum += this.dualCoefs[i] * Math.exp(-this.epsilon * (x1Square + x2Square - 2 * dot));
    }

    return this._unNormalize(sum + this.bias);
  };

  SVR.prototype._normalize = function (values) {
    return values.map(function (value, idx) {
      return (value - this.Xmeans[idx]) / (this.Xmaxs[idx] - this.Xmins[idx]);
    });
  };

  SVR.prototype._unNormalize = function (value) {
    return value * (this.ymax - this.ymin) + this.ymean;
  };

  return {
    SVR: SVR
  };

})();<commit_msg>Made it isomorphic<commit_after>
var augur = (function (canExport) {
  'use strict';

  function dotProduct(element1, element2) {
    return element1.reduce(function (prev, current, idx) {
      return prev * (idx - 1 ? 1 : element2[idx - 1]) + current * element2[idx];
    });
  }

  function selfDotProduct(element) {
    return dotProduct(element, element);
  }

  /**
   * SVR kernel RBF
   * config:
   * - supportVectors ([float])
   * - dualCoefs ([float]): dual_coefs_ are values used by scikit-learn
   * - epsilon (float)
   * - bias (float)
   * - Xmins ([float])
   * - Xmaxs ([float])
   * - Xmeans ([float])
   * - ymin (float)
   * - ymax (float)
   * - ymean (float)
   */

  function SVR(config) {
    this.supportVectors = config.supportVectors;
    this.dualCoefs = config.dualCoefs;
    this.epsilon = config.epsilon;
    this.bias = config.bias;

    this.Xmins = config.Xmins;
    this.Xmaxs = config.Xmaxs;
    this.Xmeans = config.Xmeans;

    this.ymin = config.ymin;
    this.ymax = config.ymax;
    this.ymean = config.ymean;
  }

  /**
   * predict:
   * - element ([float]): values you want to predict
   */
  SVR.prototype.predict = function (element) {
    var sum = 0.0,
        scaledElement = this._normalize(element),
        x1Square = selfDotProduct(scaledElement),
        x2Square, dot;

    for (var i = 0; i < this.supportVectors.length; i++) {
      x2Square = selfDotProduct(this.supportVectors[i]);
      dot = dotProduct(scaledElement, this.supportVectors[i]);
      sum += this.dualCoefs[i] * Math.exp(-this.epsilon * (x1Square + x2Square - 2 * dot));
    }

    return this._unNormalize(sum + this.bias);
  };

  SVR.prototype._normalize = function (values) {
    return values.map(function (value, idx) {
      return (value - this.Xmeans[idx]) / (this.Xmaxs[idx] - this.Xmins[idx]);
    });
  };

  SVR.prototype._unNormalize = function (value) {
    return value * (this.ymax - this.ymin) + this.ymean;
  };

  if (canExport) {
    module.exports({ SVR: SVR });
  }
  return { SVR: SVR };

})(typeof module !== 'undefined' && module.exports);<|endoftext|>


<commit_before>/*!
 *
 *  # Pipi: BiB/i Putter
 *
 *  - "Putting EPUBs in Web Page with BiB/i."
 *  - (c) Satoru MATSUSHIMA - http://bibi.epub.link/
 *  - Licensed under the MIT license. - http://www.opensource.org/licenses/mit-license.php
 *
 *  - Sat May 2 00:19:00 2015 +0900 */
Pipi={Version:"0.998.0",Build:20150502},function(a){window["bibi-pipi"]||(window["bibi-pipi"]={Status:"waiting"},"undefined"==typeof window.CustomEvent&&(window.CustomEvent=function(a,b){b=b||{bubbles:!1,cancelable:!1,detail:void 0};var c=document.createEvent("CustomEvent");return c.initCustomEvent(a,b.bubbles,b.cancelable,b.detail),c},window.CustomEvent.prototype=window.Event.prototype),document.addEventListener("DOMContentLoaded",a,!1),window.addEventListener("load",a,!1))}(function(){if("waiting"==window["bibi-pipi"].Status){window["bibi-pipi"].Status="processing";var a=document.querySelectorAll?document.querySelectorAll("a[data-bibi]"):function(a,b){for(var c=a.length,d=0;c>d;d++)a[d].getAttribute("data-bibi")&&b.push(a[d]);return b}(document.body.getElementsByTagName("a"),[]);if(a.length){var b=function(a,b){var c=document.createElement(a);for(var d in b)c[d]=b[d];return c},c=document.querySelector('script[src$="bib/i.js"]').src.replace(/\.js$/,""),d=function(a){return a.requestFullscreen||a.requestFullScreen?!0:a.webkitRequestFullscreen||a.webkitRequestFullScreen?!0:a.mozRequestFullscreen||a.mozRequestFullScreen?!0:a.msRequestFullscreen?!0:!1}(document.body);d&&(window["bibi-pipi"].requestFullscreen=function(a){return a.requestFullscreen?a.requestFullscreen():a.requestFullScreen?a.requestFullScreen():a.webkitRequestFullscreen?a.webkitRequestFullscreen():a.webkitRequestFullScreen?a.webkitRequestFullScreen():a.mozRequestFullscreen?a.mozRequestFullscreen():a.mozRequestFullScreen?a.mozRequestFullScreen():a.msRequestFullscreen?a.msRequestFullscreen():void 0},window["bibi-pipi"].exitFullscreen=function(a){return a.exitFullscreen?a.exitFullscreen():a.cencelFullScreen?a.cancelFullScreen():a.webkitExitFullscreen?a.webkitExitFullscreen():a.webkitCancelFullScreen?a.webkitCancelFullScreen():a.mozExitFullscreen?a.mozExitFullscreen():a.mozCancelFullScreen?a.mozCancelFullScreen():a.msExitFullscreen?a.msExitFullscreen():void 0},window["bibi-pipi"].getFullscreenElement=function(a){return a.fullscreenElement?a.fullscreenElement:a.fullScreenElement?a.fullScreenElement:a.webkitFullscreenElement?a.webkitFullscreenElement:a.webkitFullScreenElement?a.webkitFullScreenElement:a.mozFullscreenElement?a.mozFullscreenElement:a.mozFullScreenElement?a.mozFullScreenElement:a.msFullscreenElement?a.msFullscreenElement:null}),document.getElementsByTagName("head")[0].appendChild(b("link",{rel:"stylesheet",id:"bibi-css",href:c+".css"})),window["bibi-pipi"].Holders=[];for(var e=a.length,f=0;e>f;f++)if(a[f].getAttribute("href")){var g=b("span",{className:"bibi-holder "+(d?"bibi-fullscreen-enabled":"bibi-fullscreen-not-enabled"),title:(a[f].innerText?a[f].innerText+" ":"")+"(powered by BiB/i)"}),h=a[f].getAttribute("href"),i=h,j=a[f].getAttribute("data-bibi-class"),k=a[f].getAttribute("data-bibi-id"),l=a[f].getAttribute("data-bibi-style"),m=a[f].getAttribute("data-bibi-poster"),n=a[f].getAttribute("data-bibi-autostart");if(j&&(g.className+=" "+j),k&&(g.id=k),l&&g.setAttribute("style",l),n&&!/^(false|no)$/.test(n))i+=(/#/.test(i)?",":"#")+"pipi(autostart:true)";else if(m){var o=b("link",{href:m});m=o.href,delete o,i+=(/#/.test(i)?",":"#")+"pipi(poster:"+encodeURIComponent(m).replace("(","_BibiKakkoOpen_").replace(")","_BibiKakkoClose_")+")"}a[f].style.display="none",a[f].parentNode.insertBefore(g,a[f]),g.appendChild(b("iframe",{className:"bibi-frame",frameborder:"0",scrolling:"auto",allowfullscreen:"true",webkitallowfullscreen:"true",mozallowfullscreen:"true",src:i})),g.SwitchNewWindow=g.appendChild(b("a",{className:"bibi-icon bibi-switch-newwindow",title:"Open in New Window",target:"_blank",href:h})),d&&(g.className+=" bibi-fullscreen-enabled",g.SwitchFullscreen=g.appendChild(b("span",{className:"bibi-icon bibi-switch-fullscreen",title:"Enter Fullscreen",Holder:g,onclick:function(){window["bibi-pipi"].getFullscreenElement(document)?(window["bibi-pipi"].exitFullscreen(document),this.title="Enter Fullscreen"):(window["bibi-pipi"].requestFullscreen(this.Holder),this.title="Exit Fullscreen")}}))),window["bibi-pipi"].Holders.push(g),a[f].dispatchEvent(new CustomEvent("bibi:holderadded",{bubbles:!0,cancelable:!0,detail:{holder:g}}))}}window["bibi-pipi"].Status="processed"}});<commit_msg>Dispatch events during embedding on document and a[data-bibi] elements. (Compiled CSS)<commit_after>/*!
 *
 *  # Pipi: BiB/i Putter
 *
 *  - "Putting EPUBs in a Web Page with BiB/i."
 *  - (c) Satoru MATSUSHIMA - http://bibi.epub.link/
 *  - Licensed under the MIT license. - http://www.opensource.org/licenses/mit-license.php
 *
 *  - Fri May 15 19:13:00 2015 +0900
 */
Pipi={Version:"0.999.0",Build:20150515},function(a){window["bibi:pipi"]||(window["bibi:pipi"]={Status:"",Bibis:[],Anchors:[],Holders:[],Frames:[],Loaded:0},document.addEventListener("bibi:started",function(){console.log("BiB/i: Started.")},!1),document.addEventListener("bibi:ended",function(){console.log("BiB/i: Ended.")},!1),document.addEventListener("bibi:readied",function(a){console.log("BiB/i: Readied. - "+a.detail.Bibis.length+" Bibi(s).")},!1),document.addEventListener("bibi:loaded",function(a){console.log("BiB/i: Loaded. - "+a.detail.Bibis.length+" Bibi(s).")},!1),document.addEventListener("bibi:timeouted",function(a){console.log("BiB/i: Timeouted. - "+a.detail.Bibis.length+" Bibi(s).")},!1),document.addEventListener("DOMContentLoaded",a,!1),window.addEventListener("load",a,!1))}(function(){if(!window["bibi:pipi"].Status){window["bibi:pipi"].Status="started",document.dispatchEvent(new CustomEvent("bibi:started",{detail:window["bibi:pipi"]}));for(var a=document.body.querySelectorAll("a[data-bibi]"),b=a.length,c=0;b>c;c++)a[c].getAttribute("href")&&window["bibi:pipi"].Anchors.push(a[c]);if(window["bibi:pipi"].Anchors.length){var d=function(a,b){var c=document.createElement(a);for(var d in b)c[d]=b[d];return c};if("undefined"==typeof window.CustomEvent&&(window.CustomEvent=function(a,b){b=b||{bubbles:!1,cancelable:!1,detail:void 0};var c=document.createEvent("CustomEvent");return c.initCustomEvent(a,b.bubbles,b.cancelable,b.detail),c},window.CustomEvent.prototype=window.Event.prototype),document.body.requestFullscreen||document.body.requestFullScreen||document.body.webkitRequestFullscreen||document.body.webkitRequestFullScreen||document.body.mozRequestFullscreen||document.body.mozRequestFullScreen||document.body.msRequestFullscreen){window["bibi:pipi"].FullscreenEnabled=!0;var e=function(a){var b=function(b){return function(c){return c||(c=a),c[b]()}};return a.requestFullscreen?b("requestFullscreen"):a.requestFullScreen?b("requestFullScreen"):a.webkitRequestFullscreen?b("webkitRequestFullscreen"):a.webkitRequestFullScreen?b("webkitRequestFullScreen"):a.mozRequestFullscreen?b("mozRequestFullscreen"):a.mozRequestFullScreen?b("mozRequestFullScreen"):a.msRequestFullscreen?b("msRequestFullscreen"):function(){return!1}}(document.documentElement),f=function(a){var b=function(b){return function(c){return c||(c=a),c[b]()}};return a.exitFullscreen?b("exitFullscreen"):a.cencelFullScreen?b("cencelFullScreen"):a.webkitExitFullscreen?b("webkitExitFullscreen"):a.webkitCancelFullScreen?b("webkitCancelFullScreen"):a.mozExitFullscreen?b("mozExitFullscreen"):a.mozRequestFullScreen?b("mozRequestFullScreen"):a.msExitFullscreen?b("msExitFullscreen"):function(){return!1}}(document),g=function(a){var b=function(b){return function(c){return c||(c=a),c[b]}};return"undefined"!=typeof a.fullscreenElement?b("fullscreenElement"):"undefined"!=typeof a.fullScreenElement?b("fullScreenElement"):"undefined"!=typeof a.webkitFullscreenElement?b("webkitFullscreenElement"):"undefined"!=typeof a.webkitFullScreenElement?b("webkitFullScreenElement"):"undefined"!=typeof a.mozFullscreenElement?b("mozFullscreenElement"):"undefined"!=typeof a.mozFullScreenElement?b("mozFullScreenElement"):"undefined"!=typeof a.msFullscreenElement?b("msFullscreenElement"):function(){return null}}(document)}window["bibi:pipi"].BibiPath=document.querySelector('script[src$="bib/i.js"]').src.replace(/\.js$/,""),document.getElementsByTagName("head")[0].appendChild(d("link",{rel:"stylesheet",id:"bibi-css",href:window["bibi:pipi"].BibiPath+".css"}));for(var b=window["bibi:pipi"].Anchors.length,c=0;b>c;c++){var h={Index:c,Number:c+1},i=h.Anchor=window["bibi:pipi"].Anchors[c];/ bibi-anchor /.test(" "+i.className+" ")||(i.className="bibi-anchor"+(i.className?" "+i.className:""));var j=h.Holder=d("span",{className:"bibi-holder",title:(i.innerText?i.innerText+" ":"")+"(powered by BiB/i)"}),k=i.getAttribute("href"),l=k,m=i.getAttribute("data-bibi-class"),n=i.getAttribute("data-bibi-id"),o=i.getAttribute("data-bibi-style"),p=i.getAttribute("data-bibi-poster"),q=i.getAttribute("data-bibi-autostart");if(m&&(j.className+=" "+m),n&&(j.id=n),o&&j.setAttribute("style",o),q&&!/^(false|no)$/.test(q))l+=(/#/.test(l)?",":"#")+"pipi(autostart:true)";else if(p){var r=d("link",{href:p});p=r.href,delete r,l+=(/#/.test(l)?",":"#")+"pipi(poster:"+encodeURIComponent(p).replace("(","_BibiKakkoOpen_").replace(")","_BibiKakkoClose_")+")"}window["bibi:pipi"].Holders.push(j);var s=h.Frame=j.appendChild(d("iframe",{className:"bibi-frame",frameborder:"0",scrolling:"auto",allowfullscreen:"true",webkitallowfullscreen:"true",mozallowfullscreen:"true",src:l}));window["bibi:pipi"].Frames.push(s);{h.SwitchNewWindow=j.appendChild(d("a",{className:"bibi-icon bibi-switch-newwindow",title:"Open in New Window",target:"_blank",href:k}))}if(window["bibi:pipi"].FullscreenEnabled){j.className+=" bibi-fullscreen-enabled";{h.SwitchFullscreen=j.appendChild(d("span",{className:"bibi-icon bibi-switch-fullscreen",title:"Enter Fullscreen",Holder:j,onclick:function(){g(document)?(f(document),this.title="Enter Fullscreen"):(e(this.Holder),this.title="Exit Fullscreen")}}))}}else j.className+=" bibi-fullscreen-not-enabled";window["bibi:pipi"].Bibis.push(h),s.Bibi=j.Bibi=i.Bibi=h,s.addEventListener("load",function(){window["bibi:pipi"].Loaded++,this.Bibi.Anchor.dispatchEvent(new CustomEvent("bibi:loaded",{detail:this.Bibi})),"timeouted"!=window["bibi:pipi"].Status&&window["bibi:pipi"].Loaded==window["bibi:pipi"].Anchors.length&&(window["bibi:pipi"].Status="loaded",document.dispatchEvent(new CustomEvent("bibi:loaded",{detail:window["bibi:pipi"]})))},!1),i.addEventListener("bibi:loaded",function(a){console.log("BiB/i: Loaded. - "+a.detail.Index+": "+a.detail.Anchor.href)},!1),i.style.display="none",i.parentNode.insertBefore(j,i),i.dispatchEvent(new CustomEvent("bibi:readied",{detail:h})),i.dispatchEvent(new CustomEvent("bibi:holderadded",{detail:{holder:j},bubbles:!0,cancelable:!0}))}setTimeout(function(){"loaded"!=window["bibi:pipi"].Status&&(window["bibi:pipi"].Status="timeouted",document.dispatchEvent(new CustomEvent("bibi:timeouted",{detail:window["bibi:pipi"]})))},12e3),window["bibi:pipi"].Status="readied",document.dispatchEvent(new CustomEvent("bibi:readied",{detail:window["bibi:pipi"]}))}else window["bibi:pipi"].Status="ended",document.dispatchEvent(new CustomEvent("bibi:ended",{detail:window["bibi:pipi"]}))}});<|endoftext|>