Commit 3c8efe89 authored by Jacob Schatz's avatar Jacob Schatz

Merge branch 'go-go-gadget-webpack-ee' into 'master'

Port "Integrate webpack for frontend asset compilation" to EE

See merge request !1138
parents d3c1f030 f137b3e0
/builds/
/coverage/
/coverage-javascript/
/node_modules/
/public/
/tmp/
/vendor/
/builds/
karma.config.js
webpack.config.js
......@@ -16,6 +16,8 @@
],
"rules": {
"filenames/match-regex": [2, "^[a-z0-9_]+(.js)?$"],
"no-multiple-empty-lines": ["error", { "max": 1 }]
"no-multiple-empty-lines": ["error", { "max": 1 }],
"import/no-extraneous-dependencies": "off",
"import/no-unresolved": "off"
}
}
......@@ -109,11 +109,13 @@ setup-test-env:
<<: *dedicated-runner
stage: prepare
script:
- bundle exec rake gitlab:assets:compile 2>/dev/null
- npm install
- bundle exec rake gitlab:assets:compile
- bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init'
artifacts:
expire_in: 7d
paths:
- node_modules
- public/assets
- tmp/tests
......@@ -273,18 +275,17 @@ rake db:seed_fu:
paths:
- log/development.log
teaspoon:
karma:
cache:
paths:
- vendor/ruby
- node_modules/
- node_modules
stage: test
<<: *use-db
<<: *dedicated-runner
script:
- npm install
- npm link istanbul
- rake teaspoon
- rake karma
artifacts:
name: coverage-javascript
expire_in: 31d
......@@ -426,7 +427,7 @@ pages:
<<: *dedicated-runner
dependencies:
- coverage
- teaspoon
- karma
- lint:javascript:report
script:
- mv public/ .public/
......
......@@ -17,6 +17,7 @@ AllCops:
# Exclude some GitLab files
Exclude:
- 'vendor/**/*'
- 'node_modules/**/*'
- 'db/*'
- 'db/fixtures/**/*'
- 'tmp/**/*'
......
......@@ -7,7 +7,6 @@ gem 'rails-deprecated_sanitizer', '~> 1.0.3'
gem 'responders', '~> 2.0'
gem 'sprockets', '~> 3.7.0'
gem 'sprockets-es6', '~> 0.9.2'
# Default values for AR models
gem 'default_value_for', '~> 3.0.0'
......@@ -229,6 +228,7 @@ gem 'oj', '~> 2.17.4'
gem 'chronic', '~> 0.10.2'
gem 'chronic_duration', '~> 0.10.6'
gem 'webpack-rails', '~> 0.9.9'
gem 'sass-rails', '~> 5.0.6'
gem 'coffee-rails', '~> 4.1.0'
gem 'uglifier', '~> 2.7.2'
......@@ -303,13 +303,9 @@ group :development, :test do
gem 'capybara-screenshot', '~> 1.0.0'
gem 'poltergeist', '~> 1.9.0'
gem 'teaspoon', '~> 1.1.0'
gem 'teaspoon-jasmine', '~> 2.2.0'
gem 'spring', '~> 1.7.0'
gem 'spring-commands-rspec', '~> 1.0.4'
gem 'spring-commands-spinach', '~> 1.1.0'
gem 'spring-commands-teaspoon', '~> 0.0.2'
gem 'rubocop', '~> 0.46.0', require: false
gem 'rubocop-rspec', '~> 1.9.1', require: false
......@@ -327,6 +323,8 @@ group :development, :test do
gem 'activerecord_sane_schema_dumper', '0.2'
gem 'stackprof', '~> 0.2.10'
gem 'rack-proxy', '~> 0.6.0'
end
group :test do
......
......@@ -72,10 +72,6 @@ GEM
descendants_tracker (~> 0.0.4)
ice_nine (~> 0.11.0)
thread_safe (~> 0.3, >= 0.3.1)
babel-source (5.8.35)
babel-transpiler (0.7.0)
babel-source (>= 4.0, < 6)
execjs (~> 2.0)
babosa (1.0.2)
base32 (0.3.2)
bcrypt (3.1.11)
......@@ -572,6 +568,8 @@ GEM
rack (>= 1.1)
rack-protection (1.5.3)
rack
rack-proxy (0.6.0)
rack
rack-test (0.6.3)
rack (>= 1.0)
rails (4.2.7.1)
......@@ -759,15 +757,9 @@ GEM
spring (>= 0.9.1)
spring-commands-spinach (1.1.0)
spring (>= 0.9.1)
spring-commands-teaspoon (0.0.2)
spring (>= 0.9.1)
sprockets (3.7.0)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-es6 (0.9.2)
babel-source (>= 5.8.11)
babel-transpiler
sprockets (>= 3.0.0)
sprockets-rails (3.1.1)
actionpack (>= 4.0)
activesupport (>= 4.0)
......@@ -785,10 +777,6 @@ GEM
sys-filesystem (1.1.6)
ffi
sysexits (1.2.0)
teaspoon (1.1.5)
railties (>= 3.2.5, < 6)
teaspoon-jasmine (2.2.0)
teaspoon (>= 1.0.0)
temple (0.7.7)
test_after_commit (1.1.0)
activerecord (>= 3.2)
......@@ -843,6 +831,8 @@ GEM
webmock (1.21.0)
addressable (>= 2.3.6)
crack (>= 0.3.2)
webpack-rails (0.9.9)
rails (>= 3.2.0)
websocket-driver (0.6.3)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2)
......@@ -988,6 +978,7 @@ DEPENDENCIES
rack-attack (~> 4.4.1)
rack-cors (~> 0.4.0)
rack-oauth2 (~> 1.2.1)
rack-proxy (~> 0.6.0)
rails (= 4.2.7.1)
rails-deprecated_sanitizer (~> 1.0.3)
rainbow (~> 2.1.0)
......@@ -1029,14 +1020,10 @@ DEPENDENCIES
spring (~> 1.7.0)
spring-commands-rspec (~> 1.0.4)
spring-commands-spinach (~> 1.1.0)
spring-commands-teaspoon (~> 0.0.2)
sprockets (~> 3.7.0)
sprockets-es6 (~> 0.9.2)
stackprof (~> 0.2.10)
state_machines-activerecord (~> 0.4.0)
sys-filesystem (~> 1.1.6)
teaspoon (~> 1.1.0)
teaspoon-jasmine (~> 2.2.0)
test_after_commit (~> 1.1)
thin (~> 1.7.0)
timecop (~> 0.8.0)
......@@ -1053,6 +1040,7 @@ DEPENDENCIES
vmstat (~> 2.3.0)
web-console (~> 2.0)
webmock (~> 1.21.0)
webpack-rails (~> 0.9.9)
wikicloth (= 0.8.1)
BUNDLED WITH
......
/* eslint-disable func-names, space-before-function-paren, no-var, quotes, consistent-return, prefer-arrow-callback, comma-dangle, object-shorthand, no-new, max-len */
/* eslint-disable func-names, space-before-function-paren, no-var, quotes, consistent-return, prefer-arrow-callback, comma-dangle, object-shorthand, no-new, max-len, no-multi-spaces, import/newline-after-import */
/* global bp */
/* global Cookies */
/* global Flash */
......@@ -6,64 +6,61 @@
/* global AwardsHandler */
/* global Aside */
// This is a manifest file that'll be compiled into including all the files listed below.
// Add new JavaScript code in separate files in this directory and they'll automatically
// be included in the compiled file accessible from http://example.com/assets/application.js
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
/*= require jquery2 */
/*= require jquery-ui/autocomplete */
/*= require jquery-ui/datepicker */
/*= require jquery-ui/draggable */
/*= require jquery-ui/effect-highlight */
/*= require jquery-ui/sortable */
/*= require jquery_ujs */
/*= require jquery.endless-scroll */
/*= require jquery.highlight */
/*= require jquery.waitforimages */
/*= require jquery.atwho */
/*= require jquery.scrollTo */
/*= require jquery.turbolinks */
/*= require jquery.tablesorter */
/*= require js.cookie */
/*= require turbolinks */
/*= require autosave */
/*= require bootstrap/affix */
/*= require bootstrap/alert */
/*= require bootstrap/button */
/*= require bootstrap/collapse */
/*= require bootstrap/dropdown */
/*= require bootstrap/modal */
/*= require bootstrap/scrollspy */
/*= require bootstrap/tab */
/*= require bootstrap/transition */
/*= require bootstrap/tooltip */
/*= require bootstrap/popover */
/*= require select2 */
/*= require underscore */
/*= require dropzone */
/*= require mousetrap */
/*= require mousetrap/pause */
/*= require shortcuts */
/*= require shortcuts_navigation */
/*= require shortcuts_dashboard_navigation */
/*= require shortcuts_issuable */
/*= require shortcuts_network */
/*= require jquery.nicescroll */
/*= require date.format */
/*= require geo/geo_bundle */
/*= require_directory ./behaviors */
/*= require_directory ./blob */
/*= require_directory ./templates */
/*= require_directory ./commit */
/*= require_directory ./extensions */
/*= require_directory ./lib/utils */
/*= require_directory ./u2f */
/*= require_directory ./droplab */
/*= require_directory . */
/*= require fuzzaldrin-plus */
/*= require es6-promise.auto */
function requireAll(context) { return context.keys().map(context); }
window.$ = window.jQuery = require('jquery');
require('jquery-ui/ui/autocomplete');
require('jquery-ui/ui/datepicker');
require('jquery-ui/ui/draggable');
require('jquery-ui/ui/effect-highlight');
require('jquery-ui/ui/sortable');
require('jquery-ujs');
require('vendor/jquery.endless-scroll');
require('vendor/jquery.highlight');
require('vendor/jquery.waitforimages');
require('vendor/jquery.caret');
require('vendor/jquery.atwho');
require('vendor/jquery.scrollTo');
require('vendor/jquery.turbolinks');
require('vendor/jquery.tablesorter');
window.Cookies = require('vendor/js.cookie');
require('vendor/turbolinks');
require('./autosave');
require('bootstrap/js/affix');
require('bootstrap/js/alert');
require('bootstrap/js/button');
require('bootstrap/js/collapse');
require('bootstrap/js/dropdown');
require('bootstrap/js/modal');
require('bootstrap/js/scrollspy');
require('bootstrap/js/tab');
require('bootstrap/js/transition');
require('bootstrap/js/tooltip');
require('bootstrap/js/popover');
require('select2/select2.js');
window._ = require('underscore');
window.Dropzone = require('dropzone');
require('mousetrap');
require('mousetrap/plugins/pause/mousetrap-pause');
require('./shortcuts');
require('./shortcuts_navigation');
require('./shortcuts_dashboard_navigation');
require('./shortcuts_issuable');
require('./shortcuts_network');
require('vendor/jquery.nicescroll');
require('./geo/geo_bundle');
requireAll(require.context('./behaviors', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./blob', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./templates', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./commit', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./extensions', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./lib/utils', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./u2f', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./droplab', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('.', false, /^\.\/(?!application\.js).*\.(js|es6)$/));
require('vendor/fuzzaldrin-plus');
window.ES6Promise = require('vendor/es6-promise.auto');
window.ES6Promise.polyfill();
(function () {
document.addEventListener('page:fetch', function () {
......
/* eslint-disable func-names, space-before-function-paren, wrap-iife, max-len, no-var, prefer-arrow-callback, consistent-return, one-var, one-var-declaration-per-line, no-unused-vars, no-else-return, prefer-template, quotes, comma-dangle, no-param-reassign, no-void, brace-style, no-underscore-dangle, no-return-assign, camelcase */
/* global Cookies */
var emojiAliases = require('emoji-aliases');
(function() {
this.AwardsHandler = (function() {
var FROM_SENTENCE_REGEX = /(?:, and | and |, )/; // For separating lists produced by ruby's Array#toSentence
function AwardsHandler() {
this.aliases = gl.emojiAliases();
this.aliases = emojiAliases;
$(document).off('click', '.js-add-award').on('click', '.js-add-award', (function(_this) {
return function(e) {
e.stopPropagation();
......
/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, no-var, consistent-return, max-len */
/* global autosize */
/*= require jquery.ba-resize */
/*= require autosize */
var autosize = require('vendor/autosize');
require('vendor/jquery.ba-resize');
(function() {
$(function() {
......
......@@ -6,7 +6,7 @@
// "Meta+Enter" (Mac) or "Ctrl+Enter" (Linux/Windows) key combination, the form
// is submitted.
//
/*= require extensions/jquery */
require('../extensions/jquery');
//
// ### Example Markup
......
......@@ -4,7 +4,7 @@
// When called on a form with input fields with the `required` attribute, the
// form's submit button will be disabled until all required fields have values.
//
/*= require extensions/jquery */
require('../extensions/jquery');
//
// ### Example Markup
......
/* eslint-disable no-param-reassign, comma-dangle */
/* global Api */
/*= require blob/template_selector */
require('./template_selector');
((global) => {
class BlobCiYamlSelector extends gl.TemplateSelector {
requestFile(query) {
......
/* global Api */
/*= require blob/template_selector */
require('./template_selector');
(() => {
const global = window.gl || (window.gl = {});
......
/* eslint-disable func-names, space-before-function-paren, max-len, one-var, no-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, prefer-rest-params */
/* global Api */
/*= require blob/template_selector */
require('./template_selector');
(function() {
var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
......
/* eslint-disable func-names, space-before-function-paren, max-len, one-var, no-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, prefer-rest-params, comma-dangle */
/* global Api */
/*= require blob/template_selector */
require('./template_selector');
(function() {
var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
......
......@@ -2,7 +2,7 @@
/* global EditBlob */
/* global NewCommitForm */
/*= require_tree . */
require('./edit_blob');
(function() {
$(function() {
......
/* eslint-disable one-var, quote-props, comma-dangle, space-before-function-paren */
/* eslint-disable one-var, quote-props, comma-dangle, space-before-function-paren, import/newline-after-import, no-multi-spaces, max-len */
/* global Vue */
/* global BoardService */
//= require vue
//= require vue-resource
//= require Sortable
//= require_tree ./models
//= require_tree ./stores
//= require_tree ./services
//= require_tree ./mixins
//= require_tree ./filters
//= require ./components/board
//= require ./components/boards_selector
//= require ./components/board_sidebar
//= require ./components/new_list_dropdown
//= require ./vue_resource_interceptor
function requireAll(context) { return context.keys().map(context); }
window.Vue = require('vue');
window.Vue.use(require('vue-resource'));
window.Sortable = require('vendor/Sortable');
requireAll(require.context('./models', true, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./stores', true, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./services', true, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./mixins', true, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./filters', true, /^\.\/.*\.(js|es6)$/));
require('./components/board');
require('./components/boards_selector');
require('./components/board_sidebar');
require('./components/new_list_dropdown');
require('./vue_resource_interceptor');
$(() => {
const $boardApp = document.getElementById('board-app');
......
......@@ -2,9 +2,9 @@
/* global Vue */
/* global Sortable */
//= require ./board_blank_state
//= require ./board_delete
//= require ./board_list
require('./board_blank_state');
require('./board_delete');
require('./board_list');
(() => {
const Store = gl.issueBoards.BoardsStore;
......
......@@ -2,8 +2,8 @@
/* global Vue */
/* global Sortable */
//= require ./board_card
//= require ./board_new_issue
require('./board_card');
require('./board_new_issue');
(() => {
const Store = gl.issueBoards.BoardsStore;
......
/* eslint-disable */
/* global Vue */
(() => {
window.gl = window.gl || {};
window.gl.issueBoards = window.gl.issueBoards || {};
......
/* eslint-disable */
//= require ./board_new_form
/* global Vue */
require('./board_new_form');
(() => {
window.gl = window.gl || {};
......
/* eslint-disable class-methods-use-this, object-shorthand, no-unused-vars, no-use-before-define, no-new, max-len, no-restricted-syntax, guard-for-in, no-continue */
/* jshint esversion: 6 */
/*= require lib/utils/common_utils */
require('./lib/utils/common_utils');
(() => {
const gfmRules = {
......
/* eslint-disable func-names, space-before-function-paren, one-var, no-var, one-var-declaration-per-line, prefer-template, quotes, no-unused-vars, prefer-arrow-callback, max-len */
/* global Clipboard */
/*= require clipboard */
window.Clipboard = require('vendor/clipboard');
(function() {
var genericError, genericSuccess, showTooltip;
......
......@@ -2,9 +2,12 @@
/* global Cookies */
/* global Flash */
//= require vue
//= require_tree ./svg
//= require_tree .
window.Vue = require('vue');
window.Cookies = require('vendor/js.cookie');
function requireAll(context) { return context.keys().map(context); }
requireAll(require.context('./svg', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('.', true, /^\.\/(?!cycle_analytics_bundle).*\.(js|es6)$/));
$(() => {
const OVERVIEW_DIALOG_COOKIE = 'cycle_analytics_help_dismissed';
......
/* eslint-disable class-methods-use-this */
//= require lib/utils/url_utility */
require('./lib/utils/url_utility');
(() => {
const UNFOLD_COUNT = 20;
......
/* eslint-disable func-names, comma-dangle, new-cap, no-new */
/* eslint-disable func-names, comma-dangle, new-cap, no-new, import/newline-after-import, no-multi-spaces, max-len */
/* global Vue */
/* global ResolveCount */
//= require_directory ./models
//= require_directory ./stores
//= require_directory ./services
//= require_directory ./mixins
//= require_directory ./components
function requireAll(context) { return context.keys().map(context); }
requireAll(require.context('./models', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./stores', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./services', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./mixins', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./components', false, /^\.\/.*\.(js|es6)$/));
$(() => {
const COMPONENT_SELECTOR = 'resolve-btn, resolve-discussion-btn, jump-to-discussion, comment-and-resolve-btn';
......
/* eslint-disable func-names, space-before-function-paren, wrap-iife, max-len, one-var, no-var, one-var-declaration-per-line, no-unused-vars, camelcase, quotes, no-useless-concat, prefer-template, quote-props, comma-dangle, object-shorthand, consistent-return, prefer-arrow-callback */
/* global Dropzone */
/*= require preview_markdown */
require('./preview_markdown');
(function() {
this.DropzoneInput = (function() {
......
......@@ -3,10 +3,10 @@
/* global EnvironmentsService */
/* global Flash */
//= require vue
//= require vue-resource
//= require_tree ../services/
//= require ./environment_item
window.Vue = require('vue');
window.Vue.use(require('vue-resource'));
require('../services/environments_service');
require('./environment_item');
(() => {
window.gl = window.gl || {};
......
/*= require vue */
/* global Vue */
window.Vue = require('vue');
(() => {
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
......
/*= require vue */
/* global Vue */
window.Vue = require('vue');
(() => {
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
......
/* global Vue */
/* global timeago */
/*= require timeago */
/*= require lib/utils/text_utility */
/*= require vue_common_component/commit */
/*= require ./environment_actions */
/*= require ./environment_external_url */
/*= require ./environment_stop */
/*= require ./environment_rollback */
/*= require ./environment_terminal_button */
window.Vue = require('vue');
window.timeago = require('vendor/timeago');
require('../../lib/utils/text_utility');
require('../../vue_common_component/commit');
require('./environment_actions');
require('./environment_external_url');
require('./environment_stop');
require('./environment_rollback');
require('./environment_terminal_button');
(() => {
/**
......
/*= require vue */
/* global Vue */
window.Vue = require('vue');
(() => {
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
......
/*= require vue */
/* global Vue */
window.Vue = require('vue');
(() => {
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
......
/*= require vue */
/* global Vue */
window.Vue = require('vue');
(() => {
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
......
//= require vue
//= require_tree ./stores/
//= require ./components/environment
//= require ./vue_resource_interceptor
window.Vue = require('vue');
require('./stores/environments_store');
require('./components/environment');
require('./vue_resource_interceptor');
$(() => {
window.gl = window.gl || {};
......
/* globals Vue */
/* eslint-disable no-unused-vars, no-param-reassign */
class EnvironmentsService {
constructor(root) {
......
/* eslint-disable no-extend-native, func-names, space-before-function-paren, space-infix-ops, max-len */
/* eslint-disable no-extend-native, func-names, space-before-function-paren, space-infix-ops, strict, max-len */
'use strict';
Array.prototype.first = function() {
return this[0];
};
......
/*= require filtered_search/filtered_search_dropdown */
require('./filtered_search_dropdown');
/* global droplabFilter */
......
/*= require filtered_search/filtered_search_dropdown */
require('./filtered_search_dropdown');
/* global droplabAjax */
/* global droplabFilter */
......
/*= require filtered_search/filtered_search_dropdown */
require('./filtered_search_dropdown');
/* global droplabAjaxFilter */
......
// This is a manifest file that'll be compiled into including all the files listed below.
// Add new JavaScript code in separate files in this directory and they'll automatically
// be included in the compiled file accessible from http://example.com/assets/application.js
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
/*= require_tree . */
function requireAll(context) { return context.keys().map(context); }
requireAll(require.context('./', true, /^\.\/(?!filtered_search_bundle).*\.(js|es6)$/));
/* global modal Vue */
/* global Vue */
(() => {
window.gl = window.gl || {};
window.gl.geo = window.gl.geo || {};
......
/* global modal Vue */
//= require vue
//= require ./components/geo_clone_dialog
/* global Vue */
window.Vue = require('vue');
require('./components/geo_clone_dialog');
$(document).ready(() => {
window.gl = window.gl || {};
......
......@@ -249,7 +249,7 @@
_this.fullData = data;
_this.parseData(_this.fullData);
_this.focusTextInput();
if (_this.options.filterable && _this.filter && _this.filter.input && _this.filter.input.val().trim() !== '') {
if (_this.options.filterable && _this.filter && _this.filter.input && _this.filter.input.val() && _this.filter.input.val().trim() !== '') {
return _this.filter.input.trigger('input');
}
};
......
/* eslint-disable comma-dangle, class-methods-use-this, max-len, space-before-function-paren, arrow-parens, no-param-reassign */
//= require gl_field_error
require('./gl_field_error');
((global) => {
const customValidationFlag = 'gl-field-error-ignore';
......
......@@ -3,6 +3,8 @@
/* global DropzoneInput */
/* global autosize */
var autosize = require('vendor/autosize');
(function() {
this.GLForm = (function() {
function GLForm(form) {
......
/* eslint-disable func-names, space-before-function-paren */
// This is a manifest file that'll be compiled into including all the files listed below.
// Add new JavaScript code in separate files in this directory and they'll automatically
// be included in the compiled file accessible from http://example.com/assets/application.js
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
/*= require_tree . */
(function() {
}).call(this);
// require everything else in this directory
function requireAll(context) { return context.keys().map(context); }
requireAll(require.context('.', false, /^\.\/(?!graphs_bundle).*\.(js|es6)$/));
......@@ -5,7 +5,7 @@
/* global ContributorsStatGraphUtil */
/* global d3 */
/*= require d3 */
window.d3 = require('d3');
(function() {
this.ContributorsStatGraph = (function() {
......
......@@ -2,7 +2,7 @@
/* global d3 */
/* global ContributorsGraph */
/*= require d3 */
window.d3 = require('d3');
(function() {
var bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; },
......
//= require ./time_tracking/time_tracking_bundle
require('./time_tracking/time_tracking_bundle');
/* global Vue */
//= require lib/utils/pretty_time
require('../../../lib/utils/pretty_time');
(() => {
Vue.component('time-tracking-collapsed-state', {
......@@ -39,4 +39,3 @@
`,
});
})();
/* global Vue */
//= require lib/utils/pretty_time
require('../../../lib/utils/pretty_time');
(() => {
const prettyTime = gl.utils.prettyTime;
......
/* global Vue */
//= require ./help_state
//= require ./collapsed_state
//= require ./spent_only_pane
//= require ./no_tracking_pane
//= require ./estimate_only_pane
//= require ./comparison_pane
require('./help_state');
require('./collapsed_state');
require('./spent_only_pane');
require('./no_tracking_pane');
require('./estimate_only_pane');
require('./comparison_pane');
(() => {
Vue.component('issuable-time-tracker', {
......
/* global Vue */
//= require ./components/time_tracker
//= require smart_interval
//= require subbable_resource
require('./components/time_tracker');
require('../../smart_interval');
require('../../subbable_resource');
(() => {
/* This Vue instance represents what will become the parent instance for the
......
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, one-var, no-underscore-dangle, one-var-declaration-per-line, object-shorthand, no-unused-vars, no-new, comma-dangle, consistent-return, quotes, dot-notation, quote-props, prefer-arrow-callback, max-len */
/* global Flash */
/*= require flash */
/*= require jquery.waitforimages */
/*= require task_list */
require('./flash');
require('vendor/jquery.waitforimages');
require('vendor/task_list');
(function() {
var bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; };
......
/* eslint-disable func-names, space-before-function-paren */
/*= require Chart */
(function() {
}).call(this);
window.Chart = require('vendor/Chart');
/* eslint-disable func-names, space-before-function-paren */
/*= require d3 */
(function() {
}).call(this);
window.d3 = require('d3');
......@@ -2,8 +2,8 @@
/* global timeago */
/* global dateFormat */
/*= require timeago */
/*= require date.format */
window.timeago = require('vendor/timeago');
window.dateFormat = require('vendor/date.format');
(function() {
(function(w) {
......
(function() {
gl.emojiAliases = function() {
return JSON.parse('<%= Gitlab::AwardEmoji.aliases.to_json %>');
};
}).call(this);
//= require vue
//= require vue-resource
window.Vue = require('vue');
window.Vue.use(require('vue-resource'));
......@@ -4,7 +4,7 @@
//
// Handles single- and multi-line selection and highlight for blob views.
//
/*= require jquery.scrollTo */
require('vendor/jquery.scrollTo');
//
// ### Example Markup
......
......@@ -2,14 +2,14 @@
/* global Vue */
/* global Flash */
//= require vue
//= require ./merge_conflict_store
//= require ./merge_conflict_service
//= require ./mixins/line_conflict_utils
//= require ./mixins/line_conflict_actions
//= require ./components/diff_file_editor
//= require ./components/inline_conflict_lines
//= require ./components/parallel_conflict_lines
window.Vue = require('vue');
require('./merge_conflict_store');
require('./merge_conflict_service');
require('./mixins/line_conflict_utils');
require('./mixins/line_conflict_actions');
require('./components/diff_file_editor');
require('./components/inline_conflict_lines');
require('./components/parallel_conflict_lines');
$(() => {
const INTERACTIVE_RESOLVE_MODE = 'interactive';
......
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, quotes, no-underscore-dangle, one-var, one-var-declaration-per-line, consistent-return, dot-notation, quote-props, comma-dangle, object-shorthand, max-len, prefer-arrow-callback */
/* global MergeRequestTabs */
/*= require jquery.waitforimages */
/*= require task_list */
/*= require merge_request_tabs */
require('vendor/jquery.waitforimages');
require('vendor/task_list');
require('./merge_request_tabs');
(function() {
var bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; };
......@@ -110,9 +110,8 @@
};
MergeRequest.prototype.initCommitMessageListeners = function() {
$(document).on('click', 'a.js-with-description-link', function(e) {
var textarea = $('textarea.js-commit-message');
$('a.js-with-description-link').on('click', function(e) {
e.preventDefault();
textarea.val(textarea.data('messageWithDescription'));
......@@ -120,7 +119,8 @@
$('p.js-without-description-hint').show();
});
$('a.js-without-description-link').on('click', function(e) {
$(document).on('click', 'a.js-without-description-link', function(e) {
var textarea = $('textarea.js-commit-message');
e.preventDefault();
textarea.val(textarea.data('messageWithoutDescription'));
......
/* eslint-disable no-new, class-methods-use-this */
/* global Breakpoints */
/* global Cookies */
/* global DiffNotesApp */
/* global Flash */
/*= require js.cookie */
/*= require breakpoints */
require('./breakpoints');
window.Cookies = require('vendor/js.cookie');
require('./flash');
/* eslint-disable max-len */
// MergeRequestTabs
......
......@@ -4,6 +4,8 @@
/* global merge_request_widget */
/* global Turbolinks */
require('./smart_interval');
((global) => {
var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i += 1) { if (i in this && this[i] === item) return i; } return -1; };
......
/* global Vue, Flash */
//= require ./approvals_store
/* global Vue */
/* global Flash */
require('./approvals_store');
(() => {
class ApprovalsApi {
......
//= require ./approvals_store
//= require ./approvals_api
//= require_directory ./components
function requireAll(context) { return context.keys().map(context); }
require('./approvals_store');
require('./approvals_api');
requireAll(require.context('./components', true, /^\.\/.*\.(js|es6)$/));
/* global Vue */
//= require ./approvals_api
require('./approvals_api');
(() => {
let singleton;
......@@ -62,4 +63,3 @@
}
gl.MergeRequestApprovalsStore = MergeRequestApprovalsStore;
})(window.gl || (window.gl = {}));
/* global Vue */
//= require ../approvals_store
//= require ../approvals_api
require('../approvals_store');
require('../approvals_api');
(() => {
Vue.component('approvals-body', {
......
/* global Vue */
//= require ../approvals_store
//= require vue_common_component/link_to_member_avatar
require('../approvals_store');
require('../../../vue_common_component/link_to_member_avatar');
(() => {
Vue.component('approvals-footer', {
......
......@@ -50,7 +50,7 @@
// getMergeStatus replaces the MR widget with new, updated HTML, which means any persistent
// event management gets clobbered. When the MR is approvable, MR status is already managed
// and breaks when the DOM is clobbered.
merge_request_widget.getMergeStatus();
setTimeout(() => merge_request_widget.getMergeStatus(), 200);
}
});
})();
/* global Vue */
//= require ./widget_store
//= require ./approvals/approvals_bundle
require('./widget_store');
require('./approvals/approvals_bundle');
(() => {
$(() => {
......
//= require ./approvals/approvals_store
require('./approvals/approvals_store');
(() => {
let singleton;
......
......@@ -2,13 +2,9 @@
/* global Network */
/* global ShortcutsNetwork */
// This is a manifest file that'll be compiled into including all the files listed below.
// Add new JavaScript code in separate files in this directory and they'll automatically
// be included in the compiled file accessible from http://example.com/assets/application.js
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
/*= require_tree . */
// require everything else in this directory
function requireAll(context) { return context.keys().map(context); }
requireAll(require.context('.', false, /^\.\/(?!network_bundle).*\.(js|es6)$/));
(function() {
$(function() {
......
......@@ -5,13 +5,14 @@
/* global ResolveService */
/* global mrRefreshWidgetUrl */
/*= require autosave */
/*= require autosize */
/*= require dropzone */
/*= require dropzone_input */
/*= require gfm_auto_complete */
/*= require jquery.atwho */
/*= require task_list */
require('./autosave');
window.autosize = require('vendor/autosize');
window.Dropzone = require('dropzone');
require('./dropzone_input');
require('./gfm_auto_complete');
require('vendor/jquery.caret'); // required by jquery.atwho
require('vendor/jquery.atwho');
require('vendor/task_list');
(function() {
var bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; };
......
/* eslint-disable no-new, guard-for-in, no-restricted-syntax, no-continue, no-param-reassign, max-len */
//= require lib/utils/bootstrap_linked_tabs
require('./lib/utils/bootstrap_linked_tabs');
((global) => {
class Pipelines {
......
/* eslint-disable func-names, space-before-function-paren */
/*= require_tree . */
(function() {
}).call(this);
// require everything else in this directory
function requireAll(context) { return context.keys().map(context); }
requireAll(require.context('.', false, /^\.\/(?!profile_bundle).*\.(js|es6)$/));
/*= require_tree . */
// require everything else in this directory
function requireAll(context) { return context.keys().map(context); }
requireAll(require.context('.', false, /^\.\/(?!protected_branches_bundle).*\.(js|es6)$/));
......@@ -2,7 +2,7 @@
/* global Shortcuts */
/* global Mousetrap */
/*= require shortcuts */
require('./shortcuts');
(function() {
var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
......
......@@ -2,7 +2,7 @@
/* global Mousetrap */
/* global Shortcuts */
/*= require shortcuts */
require('./shortcuts');
(function() {
var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
......
......@@ -2,7 +2,7 @@
/* global Mousetrap */
/* global ShortcutsNavigation */
/*= require shortcuts_navigation */
require('./shortcuts_navigation');
(function() {
var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
......
......@@ -4,8 +4,8 @@
/* global ShortcutsNavigation */
/* global sidebar */
/*= require mousetrap */
/*= require shortcuts_navigation */
require('mousetrap');
require('./shortcuts_navigation');
(function() {
var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
......
......@@ -2,7 +2,7 @@
/* global Mousetrap */
/* global Shortcuts */
/*= require shortcuts */
require('./shortcuts');
(function() {
var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
......
......@@ -2,7 +2,7 @@
/* global Mousetrap */
/* global ShortcutsNavigation */
/*= require shortcuts_navigation */
require('./shortcuts_navigation');
(function() {
var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
......
/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, no-var, quotes, max-len */
/* global ace */
/*= require_tree . */
// require everything else in this directory
function requireAll(context) { return context.keys().map(context); }
requireAll(require.context('.', false, /^\.\/(?!snippet_bundle).*\.(js|es6)$/));
(function() {
$(function() {
......
/* eslint-disable comma-dangle, max-len, no-useless-return, no-param-reassign, max-len */
/* global Api */
/*= require ../blob/template_selector */
require('../blob/template_selector');
((global) => {
class IssuableTemplateSelector extends gl.TemplateSelector {
......
//= require xterm/encoding-indexes
//= require xterm/encoding
//= require xterm/xterm.js
//= require xterm/fit.js
//= require ./terminal.js
require('vendor/xterm/encoding-indexes.js');
require('vendor/xterm/encoding.js');
window.Terminal = require('vendor/xterm/xterm.js');
require('vendor/xterm/fit.js');
require('./terminal.js');
$(() => new gl.Terminal({ selector: '#terminal' }));
......@@ -33,7 +33,7 @@
date.setDate(date.getDate() + i);
var day = date.getDay();
var count = timestamps[dateFormat(date, 'yyyy-mm-dd')];
var count = timestamps[date.format('yyyy-mm-dd')];
// Create a new group array if this is the first day of the week
// or if is first object
......@@ -122,7 +122,7 @@
if (stamp.count > 0) {
contribText = stamp.count + " contribution" + (stamp.count > 1 ? 's' : '');
}
dateText = dateFormat(date, 'mmm d, yyyy');
dateText = date.format('mmm d, yyyy');
return contribText + "<br />" + (gl.utils.getDayName(date)) + " " + dateText;
};
})(this)).attr('class', 'user-contrib-cell js-tooltip').attr('fill', (function(_this) {
......
/* eslint-disable func-names, space-before-function-paren */
/*= require_tree . */
(function() {
}).call(this);
// require everything else in this directory
function requireAll(context) { return context.keys().map(context); }
requireAll(require.context('.', false, /^\.\/(?!users_bundle).*\.(js|es6)$/));
/*= require vue */
/* global Vue */
window.Vue = require('vue');
(() => {
window.gl = window.gl || {};
......
/* global Vue, gl */
/* eslint-disable no-param-reassign, no-plusplus */
window.Vue = require('vue');
((gl) => {
const PAGINATION_UI_BUTTON_LIMIT = 4;
const UI_LIMIT = 6;
......
/* global Vue, VueResource, gl */
/*= require vue_common_component/commit */
/*= require vue_pagination/index */
/*= require vue-resource
/*= require boards/vue_resource_interceptor */
/*= require ./status.js.es6 */
/*= require ./store.js.es6 */
/*= require ./pipeline_url.js.es6 */
/*= require ./stage.js.es6 */
/*= require ./stages.js.es6 */
/*= require ./pipeline_actions.js.es6 */
/*= require ./time_ago.js.es6 */
/*= require ./pipelines.js.es6 */
window.Vue = require('vue');
window.Vue.use(require('vue-resource'));
require('../vue_common_component/commit');
require('../vue_pagination/index');
require('../boards/vue_resource_interceptor');
require('./status');
require('./store');
require('./pipeline_url');
require('./stage');
require('./stages');
require('./pipeline_actions');
require('./time_ago');
require('./pipelines');
(() => {
const project = document.querySelector('.pipelines');
const entry = document.querySelector('.vue-pipelines-index');
const svgs = document.querySelector('.pipeline-svgs');
Vue.use(VueResource);
if (!entry) return null;
return new Vue({
el: entry,
......
......@@ -28,7 +28,6 @@
data-toggle="dropdown"
title="Manual build"
data-placement="top"
data-toggle="dropdown"
aria-label="Manual build"
>
<span v-html='svgs.iconPlay' aria-hidden="true"></span>
......@@ -54,7 +53,6 @@
data-toggle="dropdown"
title="Artifacts"
data-placement="top"
data-toggle="dropdown"
aria-label="Artifacts"
>
<i class="fa fa-download" aria-hidden="true"></i>
......
/* global gl, Flash */
/* eslint-disable no-param-reassign, no-underscore-dangle */
/*= require vue_realtime_listener/index.js */
require('../vue_realtime_listener');
((gl) => {
const pageValues = (headers) => {
......
/* eslint-disable no-param-reassign */
/* global Breakpoints */
/*= require latinise */
/*= require breakpoints */
/*= require jquery.nicescroll */
require('vendor/latinise');
require('./breakpoints');
require('vendor/jquery.nicescroll');
((global) => {
const dasherize = str => str.replace(/[_\s]+/g, '-');
......
......@@ -6,11 +6,11 @@
//
/*= provides zen_mode:enter */
/*= provides zen_mode:leave */
//
/*= require jquery.scrollTo */
/*= require dropzone */
/*= require mousetrap */
/*= require mousetrap/pause */
require('vendor/jquery.scrollTo');
window.Dropzone = require('dropzone');
require('mousetrap');
require('mousetrap/plugins/pause/mousetrap-pause');
//
// ### Events
......
......@@ -2,4 +2,7 @@ module JavascriptHelper
def page_specific_javascript_tag(js)
javascript_include_tag asset_path(js), { "data-turbolinks-track" => true }
end
def page_specific_javascript_bundle_tag(js)
javascript_include_tag(*webpack_asset_paths(js), { "data-turbolinks-track" => true })
end
end
......@@ -28,7 +28,7 @@
= stylesheet_link_tag "application", media: "all"
= stylesheet_link_tag "print", media: "print"
= javascript_include_tag "application"
= javascript_include_tag(*webpack_asset_paths("application"))
- if content_for?(:page_specific_javascripts)
= yield :page_specific_javascripts
......
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/cropper.js')
= page_specific_javascript_tag('profile/profile_bundle.js')
= page_specific_javascript_bundle_tag('profile')
......@@ -2,7 +2,7 @@
- page_title "Edit", @blob.path, @ref
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/ace.js')
= page_specific_javascript_tag('blob_edit/blob_edit_bundle.js')
= page_specific_javascript_bundle_tag('blob_edit')
= render "projects/commits/head"
%div{ class: container_class }
......
- page_title "New File", @path.presence, @ref
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/ace.js')
= page_specific_javascript_tag('blob_edit/blob_edit_bundle.js')
= page_specific_javascript_bundle_tag('blob_edit')
%h3.page-title
New File
......
......@@ -4,8 +4,8 @@
- page_title "Boards"
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('boards/boards_bundle.js')
= page_specific_javascript_tag('boards/test_utils/simulate_drag.js') if Rails.env.test?
= page_specific_javascript_bundle_tag('boards')
= page_specific_javascript_bundle_tag('boards_test') if Rails.env.test?
%script#js-board-template{ type: "text/x-template" }= render "projects/boards/components/board"
%script#js-board-list-template{ type: "text/x-template" }= render "projects/boards/components/board_list"
......
- @no_container = true
- page_title "Cycle Analytics"
- content_for :page_specific_javascripts do
= page_specific_javascript_tag("cycle_analytics/cycle_analytics_bundle.js")
= page_specific_javascript_bundle_tag('cycle_analytics')
= render "projects/pipelines/head"
......
......@@ -3,7 +3,7 @@
= render "projects/pipelines/head"
- content_for :page_specific_javascripts do
= page_specific_javascript_tag("environments/environments_bundle.js")
= page_specific_javascript_bundle_tag("environments")
#environments-list-view{ data: { environments_data: environments_list_data,
"can-create-deployment" => can?(current_user, :create_deployment, @project).to_s,
......
......@@ -4,7 +4,7 @@
- content_for :page_specific_javascripts do
= stylesheet_link_tag "xterm/xterm"
= page_specific_javascript_tag("terminal/terminal_bundle.js")
= page_specific_javascript_bundle_tag("terminal")
%div{ class: container_class }
.top-area
......
......@@ -5,8 +5,8 @@
%ul{ class: (container_class) }
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/chart.js')
= page_specific_javascript_tag('graphs/graphs_bundle.js')
= page_specific_javascript_bundle_tag('lib_chart')
= page_specific_javascript_bundle_tag('graphs')
= nav_link(action: :show) do
= link_to 'Contributors', namespace_project_graph_path
= nav_link(action: :commits) do
......
......@@ -7,7 +7,7 @@
= render "projects/issues/head"
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('filtered_search/filtered_search_bundle.js')
= page_specific_javascript_bundle_tag('filtered_search')
= content_for :meta_tags do
- if current_user
......
......@@ -3,7 +3,7 @@
- page_description @issue.description
- page_card_attributes @issue.card_attributes
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/vue_resource.js')
= page_specific_javascript_bundle_tag('lib_vue')
.clearfix.detail-page-header
.issuable-header
......
......@@ -3,8 +3,8 @@
- page_description @merge_request.description
- page_card_attributes @merge_request.card_attributes
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/vue_resource.js')
= page_specific_javascript_tag('diff_notes/diff_notes_bundle.js')
= page_specific_javascript_bundle_tag('lib_vue')
= page_specific_javascript_bundle_tag('diff_notes')
.merge-request{ 'data-url' => merge_request_path(@merge_request) }
= render "projects/merge_requests/show/mr_title"
......
- page_title "Merge Conflicts", "#{@merge_request.title} (#{@merge_request.to_reference}", "Merge Requests"
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/vue_resource.js')
= page_specific_javascript_tag('merge_conflicts/merge_conflicts_bundle.js')
= page_specific_javascript_bundle_tag('lib_vue')
= page_specific_javascript_bundle_tag('merge_conflicts')
= page_specific_javascript_tag('lib/ace.js')
= render "projects/merge_requests/show/mr_title"
......
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('merge_request_widget/widget_bundle.js')
= page_specific_javascript_bundle_tag('mr_widget_ee')
#merge-request-widget-app.mr-state-widget{ 'data-endpoint'=> merge_request_path(@merge_request), 'data-approval-pending' => (!@merge_request.approved?).to_s }
= render 'projects/merge_requests/widget/heading'
......
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('merge_request_widget/ci_bundle.js')
= page_specific_javascript_bundle_tag('merge_request_widget')
- status_class = @pipeline ? " ci-#{@pipeline.status}" : nil
......
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('merge_request_widget/ci_bundle.js')
= page_specific_javascript_bundle_tag('merge_request_widget')
%strong
= icon("spinner spin")
......
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('merge_request_widget/ci_bundle.js')
= page_specific_javascript_bundle_tag('merge_request_widget')
%h4
Set by #{link_to_member(@project, @merge_request.merge_user, avatar: true)}
......
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('merge_request_widget/ci_bundle.js')
= page_specific_javascript_bundle_tag('merge_request_widget')
- if @merge_request.rebase_in_progress? || (defined?(rebase_in_progress) && rebase_in_progress)
%h4.rebase-in-progress
......
- page_title "Network", @ref
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/raphael.js')
= page_specific_javascript_tag('network/network_bundle.js')
= page_specific_javascript_bundle_tag('network')
= render "projects/commits/head"
= render "head"
%div{ class: container_class }
......
......@@ -68,4 +68,4 @@
.vue-pipelines-index
= page_specific_javascript_tag('vue_pipelines_index/index.js')
= page_specific_javascript_bundle_tag('vue_pipelines')
- page_title "Protected branches"
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('protected_branches/protected_branches_bundle.js')
= page_specific_javascript_bundle_tag('protected_branches')
.row.prepend-top-default.append-bottom-default
.col-lg-3
......
- todo = issuable_todo(issuable)
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('issuable/issuable_bundle.js')
= page_specific_javascript_bundle_tag('issuable')
%aside.right-sidebar{ class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' }
.issuable-sidebar
- can_edit_issuable = can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
......
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/ace.js')
= page_specific_javascript_tag('snippet/snippet_bundle.js')
= page_specific_javascript_bundle_tag('snippet')
.snippet-form-holder
= form_for @snippet, url: url, html: { class: "form-horizontal snippet-form js-requires-input" } do |f|
......
- page_title @user.name
- page_description @user.bio
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/d3.js')
= page_specific_javascript_tag('users/users_bundle.js')
= page_specific_javascript_bundle_tag('lib_d3')
= page_specific_javascript_bundle_tag('users')
- header_title @user.name, user_path(@user)
- @no_container = true
......
#!/usr/bin/env ruby
begin
load File.expand_path('../spring', __FILE__)
rescue LoadError => e
raise unless e.message.include?('spring')
end
require 'bundler/setup'
load Gem.bin_path('teaspoon', 'teaspoon')
---
title: use webpack to bundle frontend assets and use karma for frontend testing
merge_request: 7288
author:
......@@ -83,6 +83,14 @@ module Gitlab
# like if you have constraints or database-specific column types
# config.active_record.schema_format = :sql
# Configure webpack
config.webpack.config_file = "config/webpack.config.js"
config.webpack.output_dir = "public/assets/webpack"
config.webpack.public_path = "assets/webpack"
# Webpack dev server configuration is handled in initializers/static_files.rb
config.webpack.dev_server.enabled = false
# Enable the asset pipeline
config.assets.enabled = true
config.assets.paths << Gemojione.images_path
......@@ -91,35 +99,13 @@ module Gitlab
config.assets.precompile << "print.css"
config.assets.precompile << "notify.css"
config.assets.precompile << "mailers/*.css"
config.assets.precompile << "lib/vue_resource.js"
config.assets.precompile << "katex.css"
config.assets.precompile << "katex.js"
config.assets.precompile << "xterm/xterm.css"
config.assets.precompile << "graphs/graphs_bundle.js"
config.assets.precompile << "users/users_bundle.js"
config.assets.precompile << "network/network_bundle.js"
config.assets.precompile << "profile/profile_bundle.js"
config.assets.precompile << "protected_branches/protected_branches_bundle.js"
config.assets.precompile << "diff_notes/diff_notes_bundle.js"
config.assets.precompile << "lib/vue_resource.js"
config.assets.precompile << "merge_request_widget/widget_bundle.js"
config.assets.precompile << "merge_request_widget/ci_bundle.js"
config.assets.precompile << "issuable/issuable_bundle.js"
config.assets.precompile << "merge_request_widget/ci_bundle.js"
config.assets.precompile << "issuable/issuable_bundle.js"
config.assets.precompile << "boards/boards_bundle.js"
config.assets.precompile << "cycle_analytics/cycle_analytics_bundle.js"
config.assets.precompile << "merge_conflicts/merge_conflicts_bundle.js"
config.assets.precompile << "boards/test_utils/simulate_drag.js"
config.assets.precompile << "environments/environments_bundle.js"
config.assets.precompile << "blob_edit/blob_edit_bundle.js"
config.assets.precompile << "snippet/snippet_bundle.js"
config.assets.precompile << "terminal/terminal_bundle.js"
config.assets.precompile << "filtered_search/filtered_search_bundle.js"
config.assets.precompile << "lib/utils/*.js"
config.assets.precompile << "lib/*.js"
config.assets.precompile << "lib/ace.js"
config.assets.precompile << "lib/cropper.js"
config.assets.precompile << "lib/raphael.js"
config.assets.precompile << "u2f.js"
config.assets.precompile << "vue_pipelines_index/index.js"
config.assets.precompile << "vendor/assets/fonts/*"
# Version of your assets, change this if you want to expire all your assets
......
---
# IGNORED GROUPS AND GEMS
- - :ignore_group
- development
- :who: Connor Shea
:why: Development gems are not distributed with the final product and are therefore exempt.
:why: Development gems are not distributed with the final product and are therefore
exempt.
:versions: []
:when: 2016-04-17 21:27:01.054140000 Z
- - :ignore_group
......@@ -18,8 +18,6 @@
:why: Bundler is MIT licensed but will sometimes fail in CI.
:versions: []
:when: 2016-05-02 06:42:08.045090000 Z
# LICENSE WHITELIST
- - :whitelist
- MIT
- :who: Connor Shea
......@@ -86,9 +84,6 @@
:why: https://opensource.org/licenses/BSD-2-Clause
:versions: []
:when: 2016-07-26 21:24:07.248480000 Z
# LICENSE BLACKLIST
- - :blacklist
- GPLv2
- :who: Connor Shea
......@@ -107,9 +102,6 @@
:why: The OSL license is a copyleft license
:versions: []
:when: 2016-10-28 11:02:15.540105000 Z
# GEM LICENSES
- - :license
- raphael-rails
- MIT
......@@ -201,3 +193,112 @@
:why: https://github.com/jmcnevin/rubypants/blob/master/LICENSE.rdoc
:versions: []
:when: 2016-05-02 05:56:50.696858000 Z
- - :approve
- after
- :who: Matt Lee
:why: https://github.com/Raynos/after/blob/master/LICENCE
:versions: []
:when: 2017-01-14 20:00:32.473125000 Z
- - :approve
- amdefine
- :who: Matt Lee
:why: MIT License
:versions: []
:when: 2017-01-14 20:08:31.810633000 Z
- - :approve
- base64id
- :who: Matt Lee
:why: https://github.com/faeldt/base64id/blob/master/LICENSE
:versions: []
:when: 2017-01-14 20:08:33.174760000 Z
- - :approve
- blob
- :who: Matt Lee
:why: https://github.com/webmodules/blob/blob/master/LICENSE
:versions: []
:when: 2017-01-14 20:08:34.564048000 Z
- - :approve
- callsite
- :who: Matt Lee
:why: https://github.com/tj/callsite/blob/master/LICENSE
:versions: []
:when: 2017-01-14 20:08:35.976025000 Z
- - :approve
- component-bind
- :who: Matt Lee
:why: https://github.com/component/bind/blob/master/LICENSE
:versions: []
:when: 2017-01-14 20:08:37.291219000 Z
- - :approve
- component-inherit
- :who: Matt Lee
:why: https://github.com/component/inherit/blob/master/LICENSE
:versions: []
:when: 2017-01-14 20:10:41.804804000 Z
- - :approve
- fsevents
- :who: Matt Lee
:why: https://github.com/strongloop/fsevents/blob/master/LICENSE
:versions: []
:when: 2017-01-14 20:50:20.037775000 Z
- - :approve
- indexof
- :who: Matt Lee
:why: https://github.com/component/indexof/blob/master/LICENSE
:versions: []
:when: 2017-01-14 20:10:43.209900000 Z
- - :approve
- is-integer
- :who: Matt Lee
:why: https://github.com/parshap/js-is-integer/blob/master/LICENSE
:versions: []
:when: 2017-01-14 20:10:44.540916000 Z
- - :approve
- jsonify
- :who: Matt Lee
:why: Public Domain - no formal license on this one. probably okay as its been
the same for along time. would prefer to see CC0
:versions: []
:when: 2017-01-14 20:10:45.857261000 Z
- - :approve
- object-component
- :who: Matt Lee
:why: https://github.com/component/object/blob/master/LICENSE
:versions: []
:when: 2017-01-14 20:10:47.190148000 Z
- - :approve
- optimist
- :who: Matt Lee
:why: https://github.com/substack/node-optimist/blob/master/LICENSE
:versions: []
:when: 2017-01-14 20:10:48.563077000 Z
- - :approve
- path-is-inside
- :who: Matt Lee
:why: https://github.com/domenic/path-is-inside/blob/master/LICENSE.txt
:versions: []
:when: 2017-01-14 20:10:49.910497000 Z
- - :approve
- rc
- :who: Matt Lee
:why: https://github.com/dominictarr/rc/blob/master/LICENSE.MIT
:versions: []
:when: 2017-01-14 20:10:51.244695000 Z
- - :approve
- ripemd160
- :who: Matt Lee
:why: https://github.com/crypto-browserify/ripemd160/blob/master/LICENSE.md
:versions: []
:when: 2017-01-14 20:10:52.560282000 Z
- - :approve
- select2
- :who: Matt Lee
:why: https://github.com/select2/select2/blob/master/LICENSE.md
:versions: []
:when: 2017-01-14 20:10:53.909618000 Z
- - :approve
- tweetnacl
- :who: Matt Lee
:why: https://github.com/dchest/tweetnacl-js/blob/master/LICENSE
:versions: []
:when: 2017-01-14 20:10:57.812077000 Z
......@@ -610,6 +610,16 @@ production: &base
# Git timeout to read a commit, in seconds
timeout: 10
## Webpack settings
# If enabled, this will tell rails to serve frontend assets from the webpack-dev-server running
# on a given port instead of serving directly from /assets/webpack. This is only indended for use
# in development.
webpack:
# dev_server:
# enabled: true
# host: localhost
# port: 3808
#
# 5. Extra customization
# ==========================
......
......@@ -521,6 +521,15 @@ Settings.rack_attack.git_basic_auth['bantime'] ||= 1.hour
Settings['gitaly'] ||= Settingslogic.new({})
Settings.gitaly['socket_path'] ||= ENV['GITALY_SOCKET_PATH']
#
# Webpack settings
#
Settings['webpack'] ||= Settingslogic.new({})
Settings.webpack['dev_server'] ||= Settingslogic.new({})
Settings.webpack.dev_server['enabled'] ||= false
Settings.webpack.dev_server['host'] ||= 'localhost'
Settings.webpack.dev_server['port'] ||= 3808
#
# Testing settings
#
......
......@@ -12,4 +12,35 @@ if app.config.serve_static_files
app.paths["public"].first,
app.config.static_cache_control
)
# If webpack-dev-server is configured, proxy webpack's public directory
# instead of looking for static assets
dev_server = Gitlab.config.webpack.dev_server
if dev_server.enabled
settings = {
enabled: true,
host: dev_server.host,
port: dev_server.port,
manifest_host: dev_server.host,
manifest_port: dev_server.port,
}
if Rails.env.development?
settings.merge!(
host: Gitlab.config.gitlab.host,
port: Gitlab.config.gitlab.port,
https: Gitlab.config.gitlab.https,
)
app.config.middleware.insert_before(
Gitlab::Middleware::Static,
Gitlab::Middleware::WebpackProxy,
proxy_path: app.config.webpack.public_path,
proxy_host: dev_server.host,
proxy_port: dev_server.port,
)
end
app.config.webpack.dev_server.merge!(settings)
end
end
var path = require('path');
var webpackConfig = require('./webpack.config.js');
var ROOT_PATH = path.resolve(__dirname, '..');
// Karma configuration
module.exports = function(config) {
config.set({
basePath: ROOT_PATH,
browsers: ['PhantomJS'],
frameworks: ['jasmine'],
files: [
{ pattern: 'spec/javascripts/test_bundle.js', watched: false },
{ pattern: 'spec/javascripts/fixtures/**/*@(.json|.html|.html.raw)', included: false },
],
preprocessors: {
'spec/javascripts/**/*.js?(.es6)': ['webpack', 'sourcemap'],
},
webpack: webpackConfig,
webpackMiddleware: { stats: 'errors-only' },
});
};
'use strict';
var fs = require('fs');
var path = require('path');
var webpack = require('webpack');
var StatsPlugin = require('stats-webpack-plugin');
var CompressionPlugin = require('compression-webpack-plugin');
var ROOT_PATH = path.resolve(__dirname, '..');
var IS_PRODUCTION = process.env.NODE_ENV === 'production';
var IS_DEV_SERVER = process.argv[1].indexOf('webpack-dev-server') !== -1;
var DEV_SERVER_PORT = parseInt(process.env.DEV_SERVER_PORT, 10) || 3808;
var config = {
context: path.join(ROOT_PATH, 'app/assets/javascripts'),
entry: {
application: './application.js',
blob_edit: './blob_edit/blob_edit_bundle.js',
boards: './boards/boards_bundle.js',
boards_test: './boards/test_utils/simulate_drag.js',
cycle_analytics: './cycle_analytics/cycle_analytics_bundle.js',
diff_notes: './diff_notes/diff_notes_bundle.js',
environments: './environments/environments_bundle.js',
filtered_search: './filtered_search/filtered_search_bundle.js',
graphs: './graphs/graphs_bundle.js',
issuable: './issuable/issuable_bundle.js',
merge_conflicts: './merge_conflicts/merge_conflicts_bundle.js',
merge_request_widget: './merge_request_widget/ci_bundle.js',
mr_widget_ee: './merge_request_widget/widget_bundle.js',
network: './network/network_bundle.js',
profile: './profile/profile_bundle.js',
protected_branches: './protected_branches/protected_branches_bundle.js',
snippet: './snippet/snippet_bundle.js',
terminal: './terminal/terminal_bundle.js',
users: './users/users_bundle.js',
lib_chart: './lib/chart.js',
lib_d3: './lib/d3.js',
lib_vue: './lib/vue_resource.js',
vue_pipelines: './vue_pipelines_index/index.js',
},
output: {
path: path.join(ROOT_PATH, 'public/assets/webpack'),
publicPath: '/assets/webpack/',
filename: IS_PRODUCTION ? '[name]-[chunkhash].js' : '[name].js'
},
devtool: 'inline-source-map',
module: {
loaders: [
{
test: /\.es6$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
// 'use strict' was broken in sprockets-es6 due to sprockets concatination method.
// many es5 strict errors which were never caught ended up in our es6 assets as a result.
// this hack is necessary until they can be fixed.
blacklist: ['useStrict']
}
},
{
test: /\.(js|es6)$/,
loader: 'imports-loader',
query: 'this=>window'
},
{
test: /\.json$/,
loader: 'json-loader'
}
]
},
plugins: [
// manifest filename must match config.webpack.manifest_filename
// webpack-rails only needs assetsByChunkName to function properly
new StatsPlugin('manifest.json', {
chunkModules: false,
source: false,
chunks: false,
modules: false,
assets: true
}),
new CompressionPlugin({
asset: '[path].gz[query]',
}),
],
resolve: {
extensions: ['', '.js', '.es6', '.js.es6'],
alias: {
'~': path.join(ROOT_PATH, 'app/assets/javascripts'),
'bootstrap/js': 'bootstrap-sass/assets/javascripts/bootstrap',
'emoji-aliases$': path.join(ROOT_PATH, 'fixtures/emojis/aliases.json'),
'vendor': path.join(ROOT_PATH, 'vendor/assets/javascripts'),
'vue$': 'vue/dist/vue.js',
'vue-resource$': 'vue-resource/dist/vue-resource.js'
}
}
}
if (IS_PRODUCTION) {
config.devtool = 'source-map';
config.plugins.push(
new webpack.NoErrorsPlugin(),
new webpack.optimize.UglifyJsPlugin({
compress: { warnings: false }
}),
new webpack.DefinePlugin({
'process.env': { NODE_ENV: JSON.stringify('production') }
}),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurrenceOrderPlugin()
);
}
if (IS_DEV_SERVER) {
config.devServer = {
port: DEV_SERVER_PORT,
headers: { 'Access-Control-Allow-Origin': '*' }
};
config.output.publicPath = '//localhost:' + DEV_SERVER_PORT + config.output.publicPath;
}
module.exports = config;
# This Rack middleware is intended to proxy the webpack assets directory to the
# webpack-dev-server. It is only intended for use in development.
module Gitlab
module Middleware
class WebpackProxy < Rack::Proxy
def initialize(app = nil, opts = {})
@proxy_host = opts.fetch(:proxy_host, 'localhost')
@proxy_port = opts.fetch(:proxy_port, 3808)
@proxy_path = opts[:proxy_path] if opts[:proxy_path]
super(app, opts)
end
def perform_request(env)
unless @proxy_path && env['PATH_INFO'].start_with?("/#{@proxy_path}")
return @app.call(env)
end
env['HTTP_HOST'] = "#{@proxy_host}:#{@proxy_port}"
super(env)
end
end
end
end
......@@ -3,6 +3,7 @@ namespace :gitlab do
desc 'GitLab | Assets | Compile all frontend assets'
task :compile do
Rake::Task['assets:precompile'].invoke
Rake::Task['webpack:compile'].invoke
Rake::Task['gitlab:assets:fix_urls'].invoke
end
......
......@@ -6,7 +6,7 @@ namespace :gitlab do
%W(rake rubocop),
%W(rake spinach),
%W(rake spec),
%W(rake teaspoon)
%W(rake karma)
]
cmds.each do |cmd|
......
unless Rails.env.production?
Rake::Task['teaspoon'].clear if Rake::Task.task_defined?('teaspoon')
Rake::Task['karma'].clear if Rake::Task.task_defined?('karma')
namespace :teaspoon do
desc 'GitLab | Teaspoon | Generate fixtures for JavaScript tests'
namespace :karma do
desc 'GitLab | Karma | Generate fixtures for JavaScript tests'
RSpec::Core::RakeTask.new(:fixtures) do |t|
ENV['NO_KNAPSACK'] = 'true'
t.pattern = 'spec/javascripts/fixtures/*.rb'
t.rspec_opts = '--format documentation'
end
desc 'GitLab | Teaspoon | Run JavaScript tests'
desc 'GitLab | Karma | Run JavaScript tests'
task :tests do
require "teaspoon/console"
options = {}
abort('rake teaspoon:tests failed') if Teaspoon::Console.new(options).failures?
sh "npm run karma" do |ok, res|
abort('rake karma:tests failed') unless ok
end
end
end
desc 'GitLab | Teaspoon | Shortcut for teaspoon:fixtures and teaspoon:tests'
task :teaspoon do
Rake::Task['teaspoon:fixtures'].invoke
Rake::Task['teaspoon:tests'].invoke
desc 'GitLab | Karma | Shortcut for karma:fixtures and karma:tests'
task :karma do
Rake::Task['karma:fixtures'].invoke
Rake::Task['karma:tests'].invoke
end
end
......@@ -7,5 +7,5 @@ end
unless Rails.env.production?
desc "GitLab | Run all tests on CI with simplecov"
task test_ci: [:rubocop, :brakeman, :teaspoon, :spinach, :spec]
task test_ci: [:rubocop, :brakeman, :karma, :spinach, :spec]
end
{
"private": true,
"scripts": {
"dev-server": "node_modules/.bin/webpack-dev-server --config config/webpack.config.js",
"eslint": "eslint --max-warnings 0 --ext .js,.js.es6 .",
"eslint-fix": "npm run eslint -- --fix",
"eslint-report": "npm run eslint -- --format html --output-file ./eslint-report.html"
"eslint-report": "npm run eslint -- --format html --output-file ./eslint-report.html",
"karma": "karma start config/karma.config.js --single-run",
"karma-start": "karma start config/karma.config.js"
},
"dependencies": {
"babel": "^5.8.38",
"babel-core": "^5.8.38",
"babel-loader": "^5.4.2",
"bootstrap-sass": "3.3.6",
"compression-webpack-plugin": "^0.3.2",
"d3": "3.5.11",
"dropzone": "4.2.0",
"exports-loader": "^0.6.3",
"imports-loader": "^0.6.5",
"jquery": "2.2.1",
"jquery-ui": "github:jquery/jquery-ui#1.11.4",
"jquery-ujs": "1.2.1",
"json-loader": "^0.5.4",
"mousetrap": "1.4.6",
"select2": "3.5.2-browserify",
"stats-webpack-plugin": "^0.4.2",
"underscore": "1.8.3",
"vue": "2.0.3",
"vue-resource": "0.9.3",
"webpack": "^1.14.0",
"webpack-dev-server": "^1.16.2"
},
"devDependencies": {
"eslint": "^3.10.1",
......@@ -11,6 +37,13 @@
"eslint-plugin-filenames": "^1.1.0",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-jasmine": "^2.1.0",
"istanbul": "^0.4.5"
"istanbul": "^0.4.5",
"jasmine-core": "^2.5.2",
"jasmine-jquery": "^2.1.1",
"karma": "^1.3.0",
"karma-jasmine": "^1.1.0",
"karma-phantomjs-launcher": "^1.0.2",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^1.8.0"
}
}
......@@ -22,9 +22,10 @@
},
"plugins": ["jasmine"],
"rules": {
"prefer-arrow-callback": 0,
"func-names": 0,
"jasmine/no-suite-dupes": [1, "branch"],
"jasmine/no-spec-dupes": [1, "branch"]
"jasmine/no-spec-dupes": [1, "branch"],
"no-console": 0,
"prefer-arrow-callback": 0
}
}
/*= require lib/utils/text_utility */
/*= require abuse_reports */
require('~/lib/utils/text_utility');
require('~/abuse_reports');
((global) => {
describe('Abuse Reports', () => {
......
/* eslint-disable no-unused-expressions, no-prototype-builtins, no-new, no-shadow, max-len */
/*= require js.cookie.js */
/*= require jquery.endless-scroll.js */
/*= require pager */
/*= require activities */
require('vendor/jquery.endless-scroll.js');
require('~/pager');
require('~/activities');
(() => {
window.gon || (window.gon = {});
......
/* global Vue eslint-disable fixture */
//= require vue
//= require underscore
//= require jquery
//= require merge_request_widget/approvals/components/approvals_body
/* global Vue */
require('~/merge_request_widget/approvals/components/approvals_body');
(() => {
gl.ApprovalsStore = {
......@@ -15,7 +13,7 @@
};
function initApprovalsBodyComponent() {
fixture.set(`
setFixtures(`
<div>
<div id="mock-container"></div>
</div>
......@@ -128,4 +126,3 @@
});
});
})(window.gl || (window.gl = {}));
/* global Vue eslint-disable fixture */
//= require vue
//= require underscore
//= require jquery
//= require merge_request_widget/approvals/components/approvals_footer
/* global Vue */
require('~/merge_request_widget/approvals/components/approvals_footer');
(() => {
gl.ApprovalsStore = {
......@@ -15,7 +13,7 @@
};
function initApprovalsFooterComponent() {
fixture.set(`
setFixtures(`
<div>
<div id="mock-container"></div>
</div>
......@@ -69,4 +67,3 @@
});
});
})(window.gl || (window.gl = {}));
//= require es6-promise.auto
//= require jquery
//= require vue
//= require vue-resource
//= require merge_request_widget/approvals/approvals_store
/* eslint-disable import/newline-after-import */
window.ES6Promise = require('vendor/es6-promise.auto');
window.ES6Promise.polyfill();
require('~/merge_request_widget/approvals/approvals_store');
$.rails = {
csrfToken() {},
......
/* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, no-unused-expressions, comma-dangle, new-parens, no-unused-vars, quotes, jasmine/no-spec-dupes, prefer-template, max-len */
/* global AwardsHandler */
/*= require awards_handler */
/*= require jquery */
/*= require js.cookie */
/*= require ./fixtures/emoji_menu */
require('~/awards_handler');
require('./fixtures/emoji_menu');
(function() {
var awardsHandler, lazyAssert, urlRoot;
......
/* eslint-disable space-before-function-paren, no-var, comma-dangle, no-return-assign, max-len */
/*= require behaviors/autosize */
require('~/behaviors/autosize');
(function() {
describe('Autosize behavior', function() {
......
/* eslint-disable space-before-function-paren, no-var, no-return-assign, comma-dangle, jasmine/no-spec-dupes, new-cap, max-len */
/*= require behaviors/quick_submit */
require('~/behaviors/quick_submit');
(function() {
describe('Quick Submit behavior', function() {
......
/* eslint-disable space-before-function-paren, no-var */
/*= require behaviors/requires_input */
require('~/behaviors/requires_input');
(function() {
describe('requiresInput', function() {
......
......@@ -6,19 +6,14 @@
/* global listObj */
/* global listObjDuplicate */
//= require jquery
//= require jquery_ujs
//= require js.cookie
//= require vue
//= require vue-resource
//= require lib/utils/url_utility
//= require boards/models/issue
//= require boards/models/label
//= require boards/models/list
//= require boards/models/user
//= require boards/services/board_service
//= require boards/stores/boards_store
//= require ./mock_data
require('~/lib/utils/url_utility');
require('~/boards/models/issue');
require('~/boards/models/label');
require('~/boards/models/list');
require('~/boards/models/user');
require('~/boards/services/board_service');
require('~/boards/stores/boards_store');
require('./mock_data');
describe('Store', () => {
beforeEach(() => {
......
......@@ -2,19 +2,14 @@
/* global BoardService */
/* global ListIssue */
//= require jquery
//= require jquery_ujs
//= require js.cookie
//= require vue
//= require vue-resource
//= require lib/utils/url_utility
//= require boards/models/issue
//= require boards/models/label
//= require boards/models/list
//= require boards/models/user
//= require boards/services/board_service
//= require boards/stores/boards_store
//= require ./mock_data
require('~/lib/utils/url_utility');
require('~/boards/models/issue');
require('~/boards/models/label');
require('~/boards/models/list');
require('~/boards/models/user');
require('~/boards/services/board_service');
require('~/boards/stores/boards_store');
require('./mock_data');
describe('Issue model', () => {
let issue;
......
......@@ -5,19 +5,14 @@
/* global List */
/* global listObj */
//= require jquery
//= require jquery_ujs
//= require js.cookie
//= require vue
//= require vue-resource
//= require lib/utils/url_utility
//= require boards/models/issue
//= require boards/models/label
//= require boards/models/list
//= require boards/models/user
//= require boards/services/board_service
//= require boards/stores/boards_store
//= require ./mock_data
require('~/lib/utils/url_utility');
require('~/boards/models/issue');
require('~/boards/models/label');
require('~/boards/models/list');
require('~/boards/models/user');
require('~/boards/services/board_service');
require('~/boards/stores/boards_store');
require('./mock_data');
describe('List model', () => {
let list;
......
......@@ -56,3 +56,8 @@ const boardsMockInterceptor = (request, next) => {
status: 200
}));
};
window.listObj = listObj;
window.listObjDuplicate = listObjDuplicate;
window.BoardsMockData = BoardsMockData;
window.boardsMockInterceptor = boardsMockInterceptor;
//= require lib/utils/bootstrap_linked_tabs
require('~/lib/utils/bootstrap_linked_tabs');
(() => {
// TODO: remove this hack!
// PhantomJS causes spyOn to panic because replaceState isn't "writable"
let phantomjs;
try {
phantomjs = !Object.getOwnPropertyDescriptor(window.history, 'replaceState').writable;
} catch (err) {
phantomjs = false;
}
describe('Linked Tabs', () => {
preloadFixtures('static/linked_tabs.html.raw');
......@@ -10,7 +19,9 @@
describe('when is initialized', () => {
beforeEach(() => {
if (!phantomjs) {
spyOn(window.history, 'replaceState').and.callFake(function () {});
}
});
it('should activate the tab correspondent to the given action', () => {
......@@ -36,7 +47,7 @@
describe('on click', () => {
it('should change the url according to the clicked tab', () => {
const historySpy = spyOn(history, 'replaceState').and.callFake(() => {});
const historySpy = !phantomjs && spyOn(history, 'replaceState').and.callFake(() => {});
const linkedTabs = new window.gl.LinkedTabs({ // eslint-disable-line
action: 'show',
......@@ -49,10 +60,12 @@
secondTab.click();
if (historySpy) {
expect(historySpy).toHaveBeenCalledWith({
turbolinks: true,
url: newState,
}, document.title, newState);
}
});
});
});
......
......@@ -2,11 +2,10 @@
/* global Build */
/* global Turbolinks */
//= require lib/utils/datetime_utility
//= require build
//= require breakpoints
//= require jquery.nicescroll
//= require turbolinks
require('~/lib/utils/datetime_utility');
require('~/build');
require('~/breakpoints');
require('vendor/jquery.nicescroll');
describe('Build', () => {
const BUILD_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/builds/1`;
......
/* global CommitsList */
//= require jquery.endless-scroll
//= require pager
//= require commits
require('vendor/jquery.endless-scroll');
require('~/pager');
require('~/commits');
(() => {
// TODO: remove this hack!
// PhantomJS causes spyOn to panic because replaceState isn't "writable"
let phantomjs;
try {
phantomjs = !Object.getOwnPropertyDescriptor(window.history, 'replaceState').writable;
} catch (err) {
phantomjs = false;
}
describe('Commits List', () => {
beforeEach(() => {
setFixtures(`
......@@ -25,7 +34,10 @@
beforeEach(() => {
CommitsList.init(25);
CommitsList.searchField.val('');
if (!phantomjs) {
spyOn(history, 'replaceState').and.stub();
}
ajaxSpy = spyOn(jQuery, 'ajax').and.callFake((req) => {
req.success({
data: '<li>Result</li>',
......
/* eslint-disable no-new */
/*= require sidebar */
/*= require jquery */
/*= require js.cookie */
/*= require lib/utils/text_utility */
require('~/sidebar');
require('~/lib/utils/text_utility');
((global) => {
describe('Dashboard', () => {
......
//= require lib/utils/datetime_utility
require('~/lib/utils/datetime_utility');
(() => {
describe('Date time utils', () => {
......
/* eslint-disable jasmine/no-global-setup, dot-notation, jasmine/no-expect-in-setup-teardown, max-len */
/* global CommentsStore */
//= require vue
//= require diff_notes/models/discussion
//= require diff_notes/models/note
//= require diff_notes/stores/comments
require('~/diff_notes/models/discussion');
require('~/diff_notes/models/note');
require('~/diff_notes/stores/comments');
(() => {
function createDiscussion(noteId = 1, resolved = true) {
......
//= require vue
//= require environments/components/environment_actions
require('~/environments/components/environment_actions');
describe('Actions Component', () => {
preloadFixtures('static/environments/element.html.raw');
......
//= require vue
//= require environments/components/environment_external_url
require('~/environments/components/environment_external_url');
describe('External URL Component', () => {
preloadFixtures('static/environments/element.html.raw');
......
//= require vue
//= require timeago
//= require environments/components/environment_item
window.timeago = require('vendor/timeago');
require('~/environments/components/environment_item');
describe('Environment item', () => {
preloadFixtures('static/environments/table.html.raw');
......
//= require vue
//= require environments/components/environment_rollback
require('~/environments/components/environment_rollback');
describe('Rollback Component', () => {
preloadFixtures('static/environments/element.html.raw');
......
/* global Vue, environment */
//= require vue
//= require vue-resource
//= require flash
//= require environments/stores/environments_store
//= require environments/components/environment
//= require ./mock_data
require('~/flash');
require('~/environments/stores/environments_store');
require('~/environments/components/environment');
require('./mock_data');
describe('Environment', () => {
preloadFixtures('environments/environments');
preloadFixtures('static/environments/environments.html.raw');
let component;
beforeEach(() => {
loadFixtures('environments/environments');
loadFixtures('static/environments/environments.html.raw');
});
describe('successfull request', () => {
......
//= require vue
//= require environments/components/environment_stop
require('~/environments/components/environment_stop');
describe('Stop Component', () => {
preloadFixtures('static/environments/element.html.raw');
......
/* global environmentsList */
//= require vue
//= require environments/stores/environments_store
//= require ./mock_data
require('~/environments/stores/environments_store');
require('./mock_data');
(() => {
describe('Store', () => {
......
/* eslint-disable no-unused-vars */
const environmentsList = [
{
id: 31,
......@@ -134,6 +134,8 @@ const environmentsList = [
},
];
window.environmentsList = environmentsList;
const environment = {
id: 4,
name: 'production',
......@@ -147,3 +149,5 @@ const environment = {
created_at: '2016-12-16T11:51:04.690Z',
updated_at: '2016-12-16T12:04:51.133Z',
};
window.environment = environment;
/* eslint-disable space-before-function-paren, no-var */
/*= require extensions/array */
require('~/extensions/array');
(function() {
describe('Array extensions', function() {
......
/*= require extensions/element */
require('~/extensions/element');
(() => {
describe('Element extensions', function () {
......
/* eslint-disable space-before-function-paren, no-var */
/*= require extensions/jquery */
require('~/extensions/jquery');
(function() {
describe('jQuery extensions', function() {
......
/*= require extensions/object */
require('~/extensions/object');
describe('Object extensions', () => {
describe('assign', () => {
......
//= require extensions/array
//= require filtered_search/dropdown_utils
//= require filtered_search/filtered_search_tokenizer
//= require filtered_search/filtered_search_dropdown_manager
require('~/extensions/array');
require('~/filtered_search/dropdown_utils');
require('~/filtered_search/filtered_search_tokenizer');
require('~/filtered_search/filtered_search_dropdown_manager');
(() => {
describe('Dropdown Utils', () => {
......
//= require extensions/array
//= require filtered_search/filtered_search_tokenizer
//= require filtered_search/filtered_search_dropdown_manager
require('~/extensions/array');
require('~/filtered_search/filtered_search_tokenizer');
require('~/filtered_search/filtered_search_dropdown_manager');
(() => {
describe('Filtered Search Dropdown Manager', () => {
......
/* global Turbolinks */
//= require turbolinks
//= require lib/utils/common_utils
//= require filtered_search/filtered_search_token_keys
//= require filtered_search/filtered_search_tokenizer
//= require filtered_search/filtered_search_dropdown_manager
//= require filtered_search/filtered_search_manager
require('~/lib/utils/common_utils');
require('~/filtered_search/filtered_search_token_keys');
require('~/filtered_search/filtered_search_tokenizer');
require('~/filtered_search/filtered_search_dropdown_manager');
require('~/filtered_search/filtered_search_manager');
(() => {
describe('Filtered Search Manager', () => {
......
//= require extensions/array
//= require filtered_search/filtered_search_token_keys
require('~/extensions/array');
require('~/filtered_search/filtered_search_token_keys');
(() => {
describe('Filtered Search Token Keys', () => {
......
//= require extensions/array
//= require filtered_search/filtered_search_token_keys
//= require filtered_search/filtered_search_tokenizer
require('~/extensions/array');
require('~/filtered_search/filtered_search_token_keys');
require('~/filtered_search/filtered_search_tokenizer');
(() => {
describe('Filtered Search Tokenizer', () => {
......
//= require gfm_auto_complete
//= require jquery
//= require jquery.atwho
require('~/gfm_auto_complete');
require('vendor/jquery.caret');
require('vendor/jquery.atwho');
const global = window.gl || (window.gl = {});
const GfmAutoComplete = global.GfmAutoComplete;
......
/* eslint-disable comma-dangle, no-param-reassign, no-unused-expressions, max-len */
/* global Turbolinks */
/*= require jquery */
/*= require gl_dropdown */
/*= require turbolinks */
/*= require lib/utils/common_utils */
/*= require lib/utils/type_utility */
require('~/gl_dropdown');
require('~/lib/utils/common_utils');
require('~/lib/utils/type_utility');
(() => {
const NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-link';
......@@ -44,6 +42,7 @@
describe('Dropdown', function describeDropdown() {
preloadFixtures('static/gl_dropdown.html.raw');
loadJSONFixtures('projects.json');
function initDropDown(hasRemote, isFilterable) {
this.dropdownButtonElement = $('#js-project-dropdown', this.dropdownContainerElement).glDropdown({
......
/* eslint-disable space-before-function-paren, arrow-body-style */
//= require jquery
//= require gl_field_errors
require('~/gl_field_errors');
((global) => {
preloadFixtures('static/gl_field_errors.html.raw');
......
......@@ -3,7 +3,7 @@
/* global ContributorsGraph */
/* global ContributorsMasterGraph */
//= require graphs/stat_graph_contributors_graph
require('~/graphs/stat_graph_contributors_graph');
describe("ContributorsGraph", function () {
describe("#set_x_domain", function () {
......
/* eslint-disable quotes, no-var, camelcase, object-property-newline, comma-dangle, max-len, vars-on-top, quote-props */
/* global ContributorsStatGraphUtil */
//= require graphs/stat_graph_contributors_util
require('~/graphs/stat_graph_contributors_util');
describe("ContributorsStatGraphUtil", function () {
describe("#parse_log", function () {
......
/* eslint-disable quotes */
/* global StatGraph */
//= require graphs/stat_graph
require('~/graphs/stat_graph');
describe("StatGraph", function () {
describe("#get_log", function () {
......
/* eslint-disable space-before-function-paren, no-var */
/*= require header */
/*= require lib/utils/text_utility */
/*= require jquery */
require('~/header');
require('~/lib/utils/text_utility');
(function() {
describe('Header', function() {
......
/* eslint-disable no-unused-vars */
class ClassSpecHelper {
static itShouldBeAStaticMethod(base, method) {
return it('should be a static method', () => {
......@@ -7,3 +5,5 @@ class ClassSpecHelper {
});
}
}
window.ClassSpecHelper = ClassSpecHelper;
/* global ClassSpecHelper */
//= require ./class_spec_helper
require('./class_spec_helper');
describe('ClassSpecHelper', () => {
describe('.itShouldBeAStaticMethod', function () {
......
/* global Issuable */
/* global Turbolinks */
//= require issuable
//= require turbolinks
require('~/issuable');
(() => {
const BASE_URL = '/user/project/issues?scope=all&state=closed';
......
/* eslint-disable */
//= require jquery
//= require vue
//= require issuable/time_tracking/components/time_tracker
require('jquery');
require('vue');
require('~/issuable/time_tracking/components/time_tracker');
function initTimeTrackingComponent(opts) {
fixture.set(`
setFixtures(`
<div>
<div id="mock-container"></div>
</div>
......
/* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, no-use-before-define, comma-dangle, max-len */
/* global Issue */
/*= require lib/utils/text_utility */
/*= require issue */
require('~/lib/utils/text_utility');
require('~/issue');
(function() {
var INVALID_URL = 'http://goesnowhere.nothing/whereami';
......
......@@ -2,17 +2,15 @@
/* global IssuableContext */
/* global LabelsSelect */
//= require lib/utils/type_utility
//= require jquery
//= require bootstrap
//= require gl_dropdown
//= require select2
//= require jquery.nicescroll
//= require api
//= require create_label
//= require issuable_context
//= require users_select
//= require labels_select
require('~/lib/utils/type_utility');
require('~/gl_dropdown');
require('select2');
require('vendor/jquery.nicescroll');
require('~/api');
require('~/create_label');
require('~/issuable_context');
require('~/users_select');
require('~/labels_select');
(() => {
let saveLabelCount = 0;
......
//= require lib/utils/common_utils
require('~/lib/utils/common_utils');
(() => {
describe('common_utils', () => {
......@@ -10,9 +10,9 @@
// IE11 will return a relative pathname while other browsers will return a full pathname.
// parseUrl uses an anchor element for parsing an url. With relative urls, the anchor
// element will create an absolute url relative to the current execution context.
// The JavaScript test suite is executed at '/teaspoon' which will lead to an absolute
// url starting with '/teaspoon'.
expect(gl.utils.parseUrl('" test="asf"').pathname).toEqual('/teaspoon/%22%20test=%22asf%22');
// The JavaScript test suite is executed at '/' which will lead to an absolute url
// starting with '/'.
expect(gl.utils.parseUrl('" test="asf"').pathname).toContain('/%22%20test=%22asf%22');
});
});
......@@ -42,9 +42,13 @@
});
describe('gl.utils.getParameterByName', () => {
beforeEach(() => {
window.history.pushState({}, null, '?scope=all&p=2');
});
it('should return valid parameter', () => {
const value = gl.utils.getParameterByName('reporter');
expect(value).toBe('Console');
const value = gl.utils.getParameterByName('scope');
expect(value).toBe('all');
});
it('should return invalid parameter', () => {
......
//= require lib/utils/text_utility
require('~/lib/utils/text_utility');
(() => {
describe('text_utility', () => {
......
/* eslint-disable space-before-function-paren, no-var, no-param-reassign, quotes, prefer-template, no-else-return, new-cap, dot-notation, no-return-assign, comma-dangle, no-new, one-var, one-var-declaration-per-line, jasmine/no-spec-dupes, no-underscore-dangle, max-len */
/* global LineHighlighter */
/*= require line_highlighter */
require('~/line_highlighter');
(function() {
describe('LineHighlighter', function() {
......
/* eslint-disable space-before-function-paren, no-return-assign */
/* global MergeRequest */
/*= require merge_request */
require('~/merge_request');
(function() {
describe('MergeRequest', function() {
......
/* eslint-disable no-var, comma-dangle, object-shorthand */
/*= require merge_request_tabs */
//= require breakpoints
//= require lib/utils/common_utils
//= require jquery.scrollTo
require('~/merge_request_tabs');
require('~/breakpoints');
require('~/lib/utils/common_utils');
require('vendor/jquery.scrollTo');
(function () {
// TODO: remove this hack!
// PhantomJS causes spyOn to panic because replaceState isn't "writable"
var phantomjs;
try {
phantomjs = !Object.getOwnPropertyDescriptor(window.history, 'replaceState').writable;
} catch (err) {
phantomjs = false;
}
describe('MergeRequestTabs', function () {
var stubLocation = {};
var setLocation = function (stubs) {
......@@ -22,9 +31,11 @@
this.class = new gl.MergeRequestTabs({ stubLocation: stubLocation });
setLocation();
if (!phantomjs) {
this.spies = {
history: spyOn(window.history, 'replaceState').and.callFake(function () {})
};
}
});
describe('#activateTab', function () {
......@@ -98,10 +109,12 @@
pathname: '/foo/bar/merge_requests/1'
});
newState = this.subject('commits');
if (!phantomjs) {
expect(this.spies.history).toHaveBeenCalledWith({
turbolinks: true,
url: newState
}, document.title, newState);
}
});
it('treats "show" like "notes"', function () {
setLocation({
......
/* eslint-disable space-before-function-paren, quotes, comma-dangle, dot-notation, quote-props, no-var, max-len */
/*= require smart_interval */
/*= require merge_request_widget */
/*= require lib/utils/datetime_utility */
require('~/smart_interval');
require('~/merge_request_widget');
require('~/lib/utils/datetime_utility');
(function() {
describe('MergeRequestWidget', function() {
......
/* eslint-disable no-new */
//= require flash
//= require mini_pipeline_graph_dropdown
require('~/flash');
require('~/mini_pipeline_graph_dropdown');
(() => {
describe('Mini Pipeline Graph Dropdown', () => {
......
/* eslint-disable space-before-function-paren, one-var, no-var, one-var-declaration-per-line, no-return-assign, quotes, max-len */
/* global NewBranchForm */
/*= require jquery-ui/autocomplete */
/*= require new_branch_form */
require('jquery-ui/ui/autocomplete');
require('~/new_branch_form');
(function() {
describe('Branch', function() {
......
/* eslint-disable space-before-function-paren, no-unused-expressions, no-var, object-shorthand, comma-dangle, max-len */
/* global Notes */
/*= require notes */
/*= require autosize */
/*= require gl_form */
/*= require lib/utils/text_utility */
require('~/notes');
require('vendor/autosize');
require('~/gl_form');
require('~/lib/utils/text_utility');
(function() {
window.gon || (window.gon = {});
......
//= require pipelines
require('~/pipelines');
// Fix for phantomJS
if (!Element.prototype.matches && Element.prototype.webkitMatchesSelector) {
Element.prototype.matches = Element.prototype.webkitMatchesSelector;
}
(() => {
describe('Pipelines', () => {
......
//= require lib/utils/pretty_time
require('~/lib/utils/pretty_time');
(() => {
const prettyTime = gl.utils.prettyTime;
......
/* eslint-disable space-before-function-paren, no-unused-expressions, no-return-assign, no-param-reassign, no-var, new-cap, wrap-iife, no-unused-vars, quotes, jasmine/no-expect-in-setup-teardown, max-len */
/* global Project */
/*= require bootstrap */
/*= require select2 */
/*= require lib/utils/type_utility */
/*= require gl_dropdown */
/*= require api */
/*= require project_select */
/*= require project */
require('select2/select2.js');
require('~/lib/utils/type_utility');
require('~/gl_dropdown');
require('~/api');
require('~/project_select');
require('~/project');
(function() {
window.gon || (window.gon = {});
......@@ -17,6 +15,8 @@
describe('Project Title', function() {
preloadFixtures('static/project_title.html.raw');
loadJSONFixtures('projects.json');
beforeEach(function() {
loadFixtures('static/project_title.html.raw');
return this.project = new Project();
......
/* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, new-parens, no-return-assign, new-cap, vars-on-top, max-len */
/* global Sidebar */
/*= require right_sidebar */
/*= require jquery */
/*= require js.cookie */
/*= require extensions/jquery.js */
require('~/right_sidebar');
require('~/extensions/jquery.js');
(function() {
var $aside, $icon, $labelsIcon, $page, $toggle, assertSidebarState;
......@@ -37,6 +34,8 @@
describe('RightSidebar', function() {
var fixtureName = 'issues/open-issue.html.raw';
preloadFixtures(fixtureName);
loadJSONFixtures('todos.json');
beforeEach(function() {
loadFixtures(fixtureName);
this.sidebar = new Sidebar;
......
/* eslint-disable space-before-function-paren, max-len, no-var, one-var, one-var-declaration-per-line, no-unused-expressions, consistent-return, no-param-reassign, default-case, no-return-assign, comma-dangle, object-shorthand, prefer-template, quotes, new-parens, vars-on-top, new-cap, max-len */
/*= require gl_dropdown */
/*= require search_autocomplete */
/*= require jquery */
/*= require lib/utils/common_utils */
/*= require lib/utils/type_utility */
/*= require fuzzaldrin-plus */
/*= require turbolinks */
/*= require jquery.turbolinks */
require('~/gl_dropdown');
require('~/search_autocomplete');
require('~/lib/utils/common_utils');
require('~/lib/utils/type_utility');
require('vendor/fuzzaldrin-plus');
(function() {
var addBodyAttributes, assertLinks, dashboardIssuesPath, dashboardMRsPath, groupIssuesPath, groupMRsPath, groupName, mockDashboardOptions, mockGroupOptions, mockProjectOptions, projectIssuesPath, projectMRsPath, projectName, userId, widget;
......@@ -117,13 +114,15 @@
preloadFixtures('static/search_autocomplete.html.raw');
beforeEach(function() {
loadFixtures('static/search_autocomplete.html.raw');
return widget = new gl.SearchAutocomplete;
widget = new gl.SearchAutocomplete;
// Prevent turbolinks from triggering within gl_dropdown
spyOn(window.Turbolinks, 'visit').and.returnValue(true);
});
it('should show Dashboard specific dropdown menu', function() {
var list;
addBodyAttributes();
mockDashboardOptions();
widget.searchInput.focus();
widget.searchInput.triggerHandler('focus');
list = widget.wrap.find('.dropdown-menu').find('ul');
return assertLinks(list, dashboardIssuesPath, dashboardMRsPath);
});
......@@ -131,7 +130,7 @@
var list;
addBodyAttributes('group');
mockGroupOptions();
widget.searchInput.focus();
widget.searchInput.triggerHandler('focus');
list = widget.wrap.find('.dropdown-menu').find('ul');
return assertLinks(list, groupIssuesPath, groupMRsPath);
});
......@@ -139,7 +138,7 @@
var list;
addBodyAttributes('project');
mockProjectOptions();
widget.searchInput.focus();
widget.searchInput.triggerHandler('focus');
list = widget.wrap.find('.dropdown-menu').find('ul');
return assertLinks(list, projectIssuesPath, projectMRsPath);
});
......@@ -148,7 +147,7 @@
addBodyAttributes('project');
mockProjectOptions();
widget.searchInput.val('help');
widget.searchInput.focus();
widget.searchInput.triggerHandler('focus');
list = widget.wrap.find('.dropdown-menu').find('ul');
link = "a[href='" + projectIssuesPath + "/?assignee_id=" + userId + "']";
return expect(list.find(link).length).toBe(0);
......@@ -159,7 +158,7 @@
addBodyAttributes();
mockDashboardOptions(true);
var submitSpy = spyOnEvent('form', 'submit');
widget.searchInput.focus();
widget.searchInput.triggerHandler('focus');
widget.wrap.trigger($.Event('keydown', { which: DOWN }));
var enterKeyEvent = $.Event('keydown', { which: ENTER });
widget.searchInput.trigger(enterKeyEvent);
......
/* eslint-disable space-before-function-paren, no-return-assign, no-var, quotes */
/* global ShortcutsIssuable */
/*= require copy_as_gfm */
/*= require shortcuts_issuable */
require('~/copy_as_gfm');
require('~/shortcuts_issuable');
(function() {
describe('ShortcutsIssuable', function() {
......@@ -53,13 +53,8 @@
return expect(triggered).toBe(true);
});
return it('triggers `focus`', function() {
var focused;
focused = false;
$(this.selector).on('focus', function() {
return focused = true;
});
this.shortcut.replyWithSelectedText();
return expect(focused).toBe(true);
expect(document.activeElement).toBe(document.querySelector(this.selector));
});
});
describe('with a one-line selection', function() {
......
/*= require signin_tabs_memoizer */
require('~/signin_tabs_memoizer');
((global) => {
describe('SigninTabsMemoizer', () => {
......
//= require jquery
//= require smart_interval
require('~/smart_interval');
(() => {
const DEFAULT_MAX_INTERVAL = 100;
......
/* eslint-disable space-before-function-paren */
// PhantomJS (Teaspoons default driver) doesn't have support for
// Function.prototype.bind, which has caused confusion. Use this polyfill to
// avoid the confusion.
/*= require support/bind-poly */
// You can require your own javascript files here. By default this will include
// everything in application, however you may get better load performance if you
// require the specific files that are being used in the spec that tests them.
/*= require jquery */
/*= require jquery.turbolinks */
/*= require bootstrap */
/*= require underscore */
// Teaspoon includes some support files, but you can use anything from your own
// support path too.
// require support/jasmine-jquery-1.7.0
// require support/jasmine-jquery-2.0.0
/*= require support/jasmine-jquery-2.1.0 */
// require support/sinon
// require support/your-support-file
// Deferring execution
// If you're using CommonJS, RequireJS or some other asynchronous library you can
// defer execution. Call Teaspoon.execute() after everything has been loaded.
// Simple example of a timeout:
// Teaspoon.defer = true
// setTimeout(Teaspoon.execute, 1000)
// Matching files
// By default Teaspoon will look for files that match
// _spec.{js,js.es6}. Add a filename_spec.js file in your spec path
// and it'll be included in the default suite automatically. If you want to
// customize suites, check out the configuration in teaspoon_env.rb
// Manifest
// If you'd rather require your spec files manually (to control order for
// instance) you can disable the suite matcher in the configuration and use this
// file as a manifest.
// For more information: http://github.com/modeset/teaspoon
// set our fixtures path
jasmine.getFixtures().fixturesPath = '/teaspoon/fixtures';
jasmine.getJSONFixtures().fixturesPath = '/teaspoon/fixtures';
// defined in ActionDispatch::TestRequest
// see https://github.com/rails/rails/blob/v4.2.7.1/actionpack/lib/action_dispatch/testing/test_request.rb#L7
window.gl = window.gl || {};
window.gl.TEST_HOST = 'http://test.host';
window.gon = window.gon || {};
/* eslint-disable max-len, arrow-parens, comma-dangle */
//= vue
//= vue-resource
//= require jquery
//= require subbable_resource
require('~/subbable_resource');
/*
* Test that each rest verb calls the publish and subscribe function and passes the correct value back
......
/* eslint-disable space-before-function-paren, no-var, no-return-assign, quotes */
/*= require syntax_highlight */
require('~/syntax_highlight');
(function() {
describe('Syntax Highlighter', function() {
......
// enable test fixtures
require('jasmine-jquery');
jasmine.getFixtures().fixturesPath = 'base/spec/javascripts/fixtures';
jasmine.getJSONFixtures().fixturesPath = 'base/spec/javascripts/fixtures';
// include common libraries
window.$ = window.jQuery = require('jquery');
window._ = require('underscore');
window.Cookies = require('vendor/js.cookie');
window.Vue = require('vue');
window.Vue.use(require('vue-resource'));
require('jquery-ujs');
require('vendor/turbolinks');
require('vendor/jquery.turbolinks');
require('bootstrap/js/affix');
require('bootstrap/js/alert');
require('bootstrap/js/button');
require('bootstrap/js/collapse');
require('bootstrap/js/dropdown');
require('bootstrap/js/modal');
require('bootstrap/js/scrollspy');
require('bootstrap/js/tab');
require('bootstrap/js/transition');
require('bootstrap/js/tooltip');
require('bootstrap/js/popover');
// stub expected globals
window.gl = window.gl || {};
window.gl.TEST_HOST = 'http://test.host';
window.gon = window.gon || {};
// render all of our tests
const testsContext = require.context('.', true, /_spec$/);
testsContext.keys().forEach(function (path) {
try {
testsContext(path);
} catch (err) {
console.error('[ERROR] WITH SPEC FILE: ', path);
console.error(err);
}
});
......@@ -2,11 +2,11 @@
/* global MockU2FDevice */
/* global U2FAuthenticate */
/*= require u2f/authenticate */
/*= require u2f/util */
/*= require u2f/error */
/*= require u2f */
/*= require ./mock_u2f_device */
require('~/u2f/authenticate');
require('~/u2f/util');
require('~/u2f/error');
require('vendor/u2f');
require('./mock_u2f_device');
(function() {
describe('U2FAuthenticate', function() {
......@@ -25,19 +25,20 @@
document.querySelector('#js-login-2fa-device'),
document.querySelector('.js-2fa-form')
);
// bypass automatic form submission within renderAuthenticated
spyOn(this.component, 'renderAuthenticated').and.returnValue(true);
return this.component.start();
});
it('allows authenticating via a U2F device', function() {
var authenticatedMessage, deviceResponse, inProgressMessage;
var inProgressMessage;
inProgressMessage = this.container.find("p");
expect(inProgressMessage.text()).toContain("Trying to communicate with your device");
this.u2fDevice.respondToAuthenticateRequest({
deviceData: "this is data from the device"
});
authenticatedMessage = this.container.find("p");
deviceResponse = this.container.find('#js-device-response');
expect(authenticatedMessage.text()).toContain('We heard back from your U2F device. You have been authenticated.');
return expect(deviceResponse.val()).toBe('{"deviceData":"this is data from the device"}');
expect(this.component.renderAuthenticated).toHaveBeenCalledWith('{"deviceData":"this is data from the device"}');
});
return describe("errors", function() {
it("displays an error message", function() {
......@@ -51,7 +52,7 @@
return expect(errorMessage.text()).toContain("There was a problem communicating with your device");
});
return it("allows retrying authentication after an error", function() {
var authenticatedMessage, retryButton, setupButton;
var retryButton, setupButton;
setupButton = this.container.find("#js-login-u2f-device");
setupButton.trigger('click');
this.u2fDevice.respondToAuthenticateRequest({
......@@ -64,8 +65,7 @@
this.u2fDevice.respondToAuthenticateRequest({
deviceData: "this is data from the device"
});
authenticatedMessage = this.container.find("p");
return expect(authenticatedMessage.text()).toContain("We heard back from your U2F device. You have been authenticated.");
expect(this.component.renderAuthenticated).toHaveBeenCalledWith('{"deviceData":"this is data from the device"}');
});
});
});
......
......@@ -2,11 +2,11 @@
/* global MockU2FDevice */
/* global U2FRegister */
/*= require u2f/register */
/*= require u2f/util */
/*= require u2f/error */
/*= require u2f */
/*= require ./mock_u2f_device */
require('~/u2f/register');
require('~/u2f/util');
require('~/u2f/error');
require('vendor/u2f');
require('./mock_u2f_device');
(function() {
describe('U2FRegister', function() {
......
/*= require visibility_select */
require('~/visibility_select');
(() => {
const VisibilitySelect = gl.VisibilitySelect;
......
//= require vue_common_component/commit
require('~/vue_common_component/commit');
describe('Commit component', () => {
let props;
......
/* eslint-disable */
//= require vue
//= require jquery
//= require vue_common_component/link_to_member_avatar
/* eslint-disable guard-for-in, no-restricted-syntax */
/* global Vue */
((gl) => {
require('~/vue_common_component/link_to_member_avatar');
(() => {
function initComponent(propsData = {}) {
fixture.set(`
setFixtures(`
<div>
<div id="mock-container"></div>
</div>
......@@ -20,9 +20,9 @@
this.$document = $(document);
}
describe('Link To Members Components', function() {
describe('Initialization', function() {
beforeEach(function() {
describe('Link To Members Components', function () {
describe('Initialization', function () {
beforeEach(function () {
const propsData = this.propsData = {
avatarSize: 32,
avatarUrl: 'myavatarurl.com',
......@@ -32,16 +32,16 @@
showTooltip: true,
};
initComponent.call(this, {
propsData
propsData,
});
});
it('should return a defined Vue component', function() {
it('should return a defined Vue component', function () {
expect(this.component).toBeDefined();
expect(this.component.$data).toBeDefined();
});
it('should have <a> and <img> children', function() {
it('should have <a> and <img> children', function () {
const componentLink = this.component.$el.querySelector('a');
const componentImg = componentLink.querySelector('img');
......@@ -49,7 +49,7 @@
expect(componentImg).not.toBeNull();
});
it('should correctly compute computed values', function(done) {
it('should correctly compute computed values', function (done) {
const correctVals = {
disabledClass: '',
avatarSizeClass: 's32',
......@@ -61,7 +61,7 @@
};
Vue.nextTick(() => {
for (var computedKey in correctVals) {
for (const computedKey in correctVals) {
const expectedVal = correctVals[computedKey];
const actualComputed = this.component[computedKey];
expect(actualComputed).toBe(expectedVal);
......@@ -71,4 +71,4 @@
});
});
});
})(window.gl || (window.gl = {}));
})();
//= require vue
//= require lib/utils/common_utils
//= require vue_pagination/index
/* global fixture, gl */
require('~/lib/utils/common_utils');
require('~/vue_pagination/index');
describe('Pagination component', () => {
let component;
......@@ -17,7 +15,7 @@ describe('Pagination component', () => {
};
it('should render and start at page 1', () => {
fixture.set('<div class="test-pagination-container"></div>');
setFixtures('<div class="test-pagination-container"></div>');
component = new window.gl.VueGlPagination({
el: document.querySelector('.test-pagination-container'),
......@@ -40,7 +38,7 @@ describe('Pagination component', () => {
});
it('should go to the previous page', () => {
fixture.set('<div class="test-pagination-container"></div>');
setFixtures('<div class="test-pagination-container"></div>');
component = new window.gl.VueGlPagination({
el: document.querySelector('.test-pagination-container'),
......@@ -61,7 +59,7 @@ describe('Pagination component', () => {
});
it('should go to the next page', () => {
fixture.set('<div class="test-pagination-container"></div>');
setFixtures('<div class="test-pagination-container"></div>');
component = new window.gl.VueGlPagination({
el: document.querySelector('.test-pagination-container'),
......@@ -82,7 +80,7 @@ describe('Pagination component', () => {
});
it('should go to the last page', () => {
fixture.set('<div class="test-pagination-container"></div>');
setFixtures('<div class="test-pagination-container"></div>');
component = new window.gl.VueGlPagination({
el: document.querySelector('.test-pagination-container'),
......@@ -103,7 +101,7 @@ describe('Pagination component', () => {
});
it('should go to the first page', () => {
fixture.set('<div class="test-pagination-container"></div>');
setFixtures('<div class="test-pagination-container"></div>');
component = new window.gl.VueGlPagination({
el: document.querySelector('.test-pagination-container'),
......@@ -124,7 +122,7 @@ describe('Pagination component', () => {
});
it('should do nothing', () => {
fixture.set('<div class="test-pagination-container"></div>');
setFixtures('<div class="test-pagination-container"></div>');
component = new window.gl.VueGlPagination({
el: document.querySelector('.test-pagination-container'),
......
......@@ -3,7 +3,7 @@
/* global Mousetrap */
/* global ZenMode */
/*= require zen_mode */
require('~/zen_mode');
(function() {
var enterZen, escapeKeydown, exitZen;
......
Teaspoon.configure do |config|
# Determines where the Teaspoon routes will be mounted. Changing this to "/jasmine" would allow you to browse to
# `http://localhost:3000/jasmine` to run your tests.
config.mount_at = "/teaspoon"
# Specifies the root where Teaspoon will look for files. If you're testing an engine using a dummy application it can
# be useful to set this to your engines root (e.g. `Teaspoon::Engine.root`).
# Note: Defaults to `Rails.root` if nil.
config.root = nil
# Paths that will be appended to the Rails assets paths
# Note: Relative to `config.root`.
config.asset_paths = ["spec/javascripts", "spec/javascripts/stylesheets"]
# Fixtures are rendered through a controller, which allows using HAML, RABL/JBuilder, etc. Files in these paths will
# be rendered as fixtures.
config.fixture_paths = ["spec/javascripts/fixtures"]
# SUITES
#
# You can modify the default suite configuration and create new suites here. Suites are isolated from one another.
#
# When defining a suite you can provide a name and a block. If the name is left blank, :default is assumed. You can
# omit various directives and the ones defined in the default suite will be used.
#
# To run a specific suite
# - in the browser: http://localhost/teaspoon/[suite_name]
# - with the rake task: rake teaspoon suite=[suite_name]
# - with the cli: teaspoon --suite=[suite_name]
config.suite do |suite|
# Specify the framework you would like to use. This allows you to select versions, and will do some basic setup for
# you -- which you can override with the directives below. This should be specified first, as it can override other
# directives.
# Note: If no version is specified, the latest is assumed.
#
# Versions: 1.3.1, 2.0.3, 2.1.3, 2.2.0
suite.use_framework :jasmine, "2.2.0"
# Specify a file matcher as a regular expression and all matching files will be loaded when the suite is run. These
# files need to be within an asset path. You can add asset paths using the `config.asset_paths`.
suite.matcher = "{spec/javascripts,app/assets}/**/*_spec.{js,js.es6,es6}"
# Load additional JS files, but requiring them in your spec helper is the preferred way to do this.
# suite.javascripts = []
# You can include your own stylesheets if you want to change how Teaspoon looks.
# Note: Spec related CSS can and should be loaded using fixtures.
# suite.stylesheets = ["teaspoon"]
# This suites spec helper, which can require additional support files. This file is loaded before any of your test
# files are loaded.
suite.helper = "spec_helper"
# Partial to be rendered in the head tag of the runner. You can use the provided ones or define your own by creating
# a `_boot.html.erb` in your fixtures path, and adjust the config to `"/boot"` for instance.
#
# Available: boot, boot_require_js
suite.boot_partial = "boot"
# Partial to be rendered in the body tag of the runner. You can define your own to create a custom body structure.
suite.body_partial = "body"
# Hooks allow you to use `Teaspoon.hook("fixtures")` before, after, or during your spec run. This will make a
# synchronous Ajax request to the server that will call all of the blocks you've defined for that hook name.
# suite.hook :fixtures, &proc{}
# Determine whether specs loaded into the test harness should be embedded as individual script tags or concatenated
# into a single file. Similar to Rails' asset `debug: true` and `config.assets.debug = true` options. By default,
# Teaspoon expands all assets to provide more valuable stack traces that reference individual source files.
# suite.expand_assets = true
end
# Example suite. Since we're just filtering to files already within the root test/javascripts, these files will also
# be run in the default suite -- but can be focused into a more specific suite.
# config.suite :targeted do |suite|
# suite.matcher = "spec/javascripts/targeted/*_spec.{js,js.coffee,coffee}"
# end
# CONSOLE RUNNER SPECIFIC
#
# These configuration directives are applicable only when running via the rake task or command line interface. These
# directives can be overridden using the command line interface arguments or with ENV variables when using the rake
# task.
#
# Command Line Interface:
# teaspoon --driver=phantomjs --server-port=31337 --fail-fast=true --format=junit --suite=my_suite /spec/file_spec.js
#
# Rake:
# teaspoon DRIVER=phantomjs SERVER_PORT=31337 FAIL_FAST=true FORMATTERS=junit suite=my_suite
# Specify which headless driver to use. Supports PhantomJS and Selenium Webdriver.
#
# Available: :phantomjs, :selenium, :capybara_webkit
# PhantomJS: https://github.com/modeset/teaspoon/wiki/Using-PhantomJS
# Selenium Webdriver: https://github.com/modeset/teaspoon/wiki/Using-Selenium-WebDriver
# Capybara Webkit: https://github.com/modeset/teaspoon/wiki/Using-Capybara-Webkit
# config.driver = :phantomjs
# Specify additional options for the driver.
#
# PhantomJS: https://github.com/modeset/teaspoon/wiki/Using-PhantomJS
# Selenium Webdriver: https://github.com/modeset/teaspoon/wiki/Using-Selenium-WebDriver
# Capybara Webkit: https://github.com/modeset/teaspoon/wiki/Using-Capybara-Webkit
# config.driver_options = nil
# Specify the timeout for the driver. Specs are expected to complete within this time frame or the run will be
# considered a failure. This is to avoid issues that can arise where tests stall.
# config.driver_timeout = 180
# Specify a server to use with Rack (e.g. thin, mongrel). If nil is provided Rack::Server is used.
# config.server = nil
# Specify a port to run on a specific port, otherwise Teaspoon will use a random available port.
# config.server_port = nil
# Timeout for starting the server in seconds. If your server is slow to start you may have to bump this, or you may
# want to lower this if you know it shouldn't take long to start.
# config.server_timeout = 20
# Force Teaspoon to fail immediately after a failing suite. Can be useful to make Teaspoon fail early if you have
# several suites, but in environments like CI this may not be desirable.
# config.fail_fast = true
# Specify the formatters to use when outputting the results.
# Note: Output files can be specified by using `"junit>/path/to/output.xml"`.
#
# Available: :dot, :clean, :documentation, :json, :junit, :pride, :rspec_html, :snowday, :swayze_or_oprah, :tap, :tap_y, :teamcity
# config.formatters = [:dot]
# Specify if you want color output from the formatters.
# config.color = true
# Teaspoon pipes all console[log/debug/error] to $stdout. This is useful to catch places where you've forgotten to
# remove them, but in verbose applications this may not be desirable.
# config.suppress_log = false
# COVERAGE REPORTS / THRESHOLD ASSERTIONS
#
# Coverage reports requires Istanbul (https://github.com/gotwarlost/istanbul) to add instrumentation to your code and
# display coverage statistics.
#
# Coverage configurations are similar to suites. You can define several, and use different ones under different
# conditions.
#
# To run with a specific coverage configuration
# - with the rake task: rake teaspoon USE_COVERAGE=[coverage_name]
# - with the cli: teaspoon --coverage=[coverage_name]
# Specify that you always want a coverage configuration to be used. Otherwise, specify that you want coverage
# on the CLI.
# Set this to "true" or the name of your coverage config.
config.use_coverage = true
# You can have multiple coverage configs by passing a name to config.coverage.
# e.g. config.coverage :ci do |coverage|
# The default coverage config name is :default.
config.coverage do |coverage|
# Which coverage reports Istanbul should generate. Correlates directly to what Istanbul supports.
#
# Available: text-summary, text, html, lcov, lcovonly, cobertura, teamcity
coverage.reports = ["text-summary", "html"]
# The path that the coverage should be written to - when there's an artifact to write to disk.
# Note: Relative to `config.root`.
coverage.output_path = "coverage-javascript"
# Assets to be ignored when generating coverage reports. Accepts an array of filenames or regular expressions. The
# default excludes assets from vendor, gems and support libraries.
coverage.ignore = [%r{vendor/}, %r{spec/javascripts/(?!helpers/)}]
# Various thresholds requirements can be defined, and those thresholds will be checked at the end of a run. If any
# aren't met the run will fail with a message. Thresholds can be defined as a percentage (0-100), or nil.
# coverage.statements = nil
# coverage.functions = nil
# coverage.branches = nil
# coverage.lines = nil
end
end
......@@ -11,8 +11,12 @@
* The date defaults to the current date/time.
* The mask defaults to dateFormat.masks.default.
*/
var dateFormat = function () {
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.dateFormat = factory());
}(this, (function () { 'use strict';
var dateFormat = function () {
var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
timezoneClip = /[^-+\dA-Z]/g,
......@@ -89,10 +93,10 @@ var dateFormat = function () {
return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
});
};
}();
}();
// Some common format strings
dateFormat.masks = {
// Some common format strings
dateFormat.masks = {
"default": "ddd mmm dd yyyy HH:MM:ss",
shortDate: "m/d/yy",
mediumDate: "mmm d, yyyy",
......@@ -105,10 +109,10 @@ dateFormat.masks = {
isoTime: "HH:MM:ss",
isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
};
};
// Internationalization strings
dateFormat.i18n = {
// Internationalization strings
dateFormat.i18n = {
dayNames: [
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
......@@ -117,9 +121,12 @@ dateFormat.i18n = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
]
};
};
// For convenience...
Date.prototype.format = function (mask, utc) {
// For convenience...
Date.prototype.format = function (mask, utc) {
return dateFormat(this, mask, utc);
};
};
return dateFormat;
})));
......@@ -1154,6 +1154,3 @@ Promise.Promise = Promise;
return Promise;
})));
ES6Promise.polyfill();
//# sourceMappingURL=es6-promise.auto.map
/**
* at.js - 1.5.1
* Copyright (c) 2016 chord.luo <chord.luo@gmail.com>;
* Homepage: http://ichord.github.com/At.js
* License: MIT
*/
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module unless amdModuleId is set
define(["jquery"], function (a0) {
return (factory(a0));
});
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory(require("jquery"));
} else {
factory(jQuery);
}
}(this, function ($) {
var DEFAULT_CALLBACKS, KEY_CODE;
KEY_CODE = {
DOWN: 40,
UP: 38,
ESC: 27,
TAB: 9,
ENTER: 13,
CTRL: 17,
A: 65,
P: 80,
N: 78,
LEFT: 37,
UP: 38,
RIGHT: 39,
DOWN: 40,
BACKSPACE: 8,
SPACE: 32
};
DEFAULT_CALLBACKS = {
beforeSave: function(data) {
return Controller.arrayToDefaultHash(data);
},
matcher: function(flag, subtext, should_startWithSpace, acceptSpaceBar) {
var _a, _y, match, regexp, space;
flag = flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
if (should_startWithSpace) {
flag = '(?:^|\\s)' + flag;
}
_a = decodeURI("%C3%80");
_y = decodeURI("%C3%BF");
space = acceptSpaceBar ? "\ " : "";
regexp = new RegExp(flag + "([A-Za-z" + _a + "-" + _y + "0-9_" + space + "\'\.\+\-]*)$|" + flag + "([^\\x00-\\xff]*)$", 'gi');
match = regexp.exec(subtext);
if (match) {
return match[2] || match[1];
} else {
return null;
}
},
filter: function(query, data, searchKey) {
var _results, i, item, len;
_results = [];
for (i = 0, len = data.length; i < len; i++) {
item = data[i];
if (~new String(item[searchKey]).toLowerCase().indexOf(query.toLowerCase())) {
_results.push(item);
}
}
return _results;
},
remoteFilter: null,
sorter: function(query, items, searchKey) {
var _results, i, item, len;
if (!query) {
return items;
}
_results = [];
for (i = 0, len = items.length; i < len; i++) {
item = items[i];
item.atwho_order = new String(item[searchKey]).toLowerCase().indexOf(query.toLowerCase());
if (item.atwho_order > -1) {
_results.push(item);
}
}
return _results.sort(function(a, b) {
return a.atwho_order - b.atwho_order;
});
},
tplEval: function(tpl, map) {
var error, error1, template;
template = tpl;
try {
if (typeof tpl !== 'string') {
template = tpl(map);
}
return template.replace(/\$\{([^\}]*)\}/g, function(tag, key, pos) {
return map[key];
});
} catch (error1) {
error = error1;
return "";
}
},
highlighter: function(li, query) {
var regexp;
if (!query) {
return li;
}
regexp = new RegExp(">\\s*(\\w*?)(" + query.replace("+", "\\+") + ")(\\w*)\\s*<", 'ig');
return li.replace(regexp, function(str, $1, $2, $3) {
return '> ' + $1 + '<strong>' + $2 + '</strong>' + $3 + ' <';
});
},
beforeInsert: function(value, $li, e) {
return value;
},
beforeReposition: function(offset) {
return offset;
},
afterMatchFailed: function(at, el) {}
};
var App;
App = (function() {
function App(inputor) {
this.currentFlag = null;
this.controllers = {};
this.aliasMaps = {};
this.$inputor = $(inputor);
this.setupRootElement();
this.listen();
}
App.prototype.createContainer = function(doc) {
var ref;
if ((ref = this.$el) != null) {
ref.remove();
}
return $(doc.body).append(this.$el = $("<div class='atwho-container'></div>"));
};
App.prototype.setupRootElement = function(iframe, asRoot) {
var error, error1;
if (asRoot == null) {
asRoot = false;
}
if (iframe) {
this.window = iframe.contentWindow;
this.document = iframe.contentDocument || this.window.document;
this.iframe = iframe;
} else {
this.document = this.$inputor[0].ownerDocument;
this.window = this.document.defaultView || this.document.parentWindow;
try {
this.iframe = this.window.frameElement;
} catch (error1) {
error = error1;
this.iframe = null;
if ($.fn.atwho.debug) {
throw new Error("iframe auto-discovery is failed.\nPlease use `setIframe` to set the target iframe manually.\n" + error);
}
}
}
return this.createContainer((this.iframeAsRoot = asRoot) ? this.document : document);
};
App.prototype.controller = function(at) {
var c, current, currentFlag, ref;
if (this.aliasMaps[at]) {
current = this.controllers[this.aliasMaps[at]];
} else {
ref = this.controllers;
for (currentFlag in ref) {
c = ref[currentFlag];
if (currentFlag === at) {
current = c;
break;
}
}
}
if (current) {
return current;
} else {
return this.controllers[this.currentFlag];
}
};
App.prototype.setContextFor = function(at) {
this.currentFlag = at;
return this;
};
App.prototype.reg = function(flag, setting) {
var base, controller;
controller = (base = this.controllers)[flag] || (base[flag] = this.$inputor.is('[contentEditable]') ? new EditableController(this, flag) : new TextareaController(this, flag));
if (setting.alias) {
this.aliasMaps[setting.alias] = flag;
}
controller.init(setting);
return this;
};
App.prototype.listen = function() {
return this.$inputor.on('compositionstart', (function(_this) {
return function(e) {
var ref;
if ((ref = _this.controller()) != null) {
ref.view.hide();
}
_this.isComposing = true;
return null;
};
})(this)).on('compositionend', (function(_this) {
return function(e) {
_this.isComposing = false;
setTimeout(function(e) {
return _this.dispatch(e);
});
return null;
};
})(this)).on('keyup.atwhoInner', (function(_this) {
return function(e) {
return _this.onKeyup(e);
};
})(this)).on('keydown.atwhoInner', (function(_this) {
return function(e) {
return _this.onKeydown(e);
};
})(this)).on('blur.atwhoInner', (function(_this) {
return function(e) {
var c;
if (c = _this.controller()) {
c.expectedQueryCBId = null;
return c.view.hide(e, c.getOpt("displayTimeout"));
}
};
})(this)).on('click.atwhoInner', (function(_this) {
return function(e) {
return _this.dispatch(e);
};
})(this)).on('scroll.atwhoInner', (function(_this) {
return function() {
var lastScrollTop;
lastScrollTop = _this.$inputor.scrollTop();
return function(e) {
var currentScrollTop, ref;
currentScrollTop = e.target.scrollTop;
if (lastScrollTop !== currentScrollTop) {
if ((ref = _this.controller()) != null) {
ref.view.hide(e);
}
}
lastScrollTop = currentScrollTop;
return true;
};
};
})(this)());
};
App.prototype.shutdown = function() {
var _, c, ref;
ref = this.controllers;
for (_ in ref) {
c = ref[_];
c.destroy();
delete this.controllers[_];
}
this.$inputor.off('.atwhoInner');
return this.$el.remove();
};
App.prototype.dispatch = function(e) {
var _, c, ref, results;
ref = this.controllers;
results = [];
for (_ in ref) {
c = ref[_];
results.push(c.lookUp(e));
}
return results;
};
App.prototype.onKeyup = function(e) {
var ref;
switch (e.keyCode) {
case KEY_CODE.ESC:
e.preventDefault();
if ((ref = this.controller()) != null) {
ref.view.hide();
}
break;
case KEY_CODE.DOWN:
case KEY_CODE.UP:
case KEY_CODE.CTRL:
case KEY_CODE.ENTER:
$.noop();
break;
case KEY_CODE.P:
case KEY_CODE.N:
if (!e.ctrlKey) {
this.dispatch(e);
}
break;
default:
this.dispatch(e);
}
};
App.prototype.onKeydown = function(e) {
var ref, view;
view = (ref = this.controller()) != null ? ref.view : void 0;
if (!(view && view.visible())) {
return;
}
switch (e.keyCode) {
case KEY_CODE.ESC:
e.preventDefault();
view.hide(e);
break;
case KEY_CODE.UP:
e.preventDefault();
view.prev();
break;
case KEY_CODE.DOWN:
e.preventDefault();
view.next();
break;
case KEY_CODE.P:
if (!e.ctrlKey) {
return;
}
e.preventDefault();
view.prev();
break;
case KEY_CODE.N:
if (!e.ctrlKey) {
return;
}
e.preventDefault();
view.next();
break;
case KEY_CODE.TAB:
case KEY_CODE.ENTER:
case KEY_CODE.SPACE:
if (!view.visible()) {
return;
}
if (!this.controller().getOpt('spaceSelectsMatch') && e.keyCode === KEY_CODE.SPACE) {
return;
}
if (!this.controller().getOpt('tabSelectsMatch') && e.keyCode === KEY_CODE.TAB) {
return;
}
if (view.highlighted()) {
e.preventDefault();
view.choose(e);
} else {
view.hide(e);
}
break;
default:
$.noop();
}
};
return App;
})();
var Controller,
slice = [].slice;
Controller = (function() {
Controller.prototype.uid = function() {
return (Math.random().toString(16) + "000000000").substr(2, 8) + (new Date().getTime());
};
function Controller(app, at1) {
this.app = app;
this.at = at1;
this.$inputor = this.app.$inputor;
this.id = this.$inputor[0].id || this.uid();
this.expectedQueryCBId = null;
this.setting = null;
this.query = null;
this.pos = 0;
this.range = null;
if ((this.$el = $("#atwho-ground-" + this.id, this.app.$el)).length === 0) {
this.app.$el.append(this.$el = $("<div id='atwho-ground-" + this.id + "'></div>"));
}
this.model = new Model(this);
this.view = new View(this);
}
Controller.prototype.init = function(setting) {
this.setting = $.extend({}, this.setting || $.fn.atwho["default"], setting);
this.view.init();
return this.model.reload(this.setting.data);
};
Controller.prototype.destroy = function() {
this.trigger('beforeDestroy');
this.model.destroy();
this.view.destroy();
return this.$el.remove();
};
Controller.prototype.callDefault = function() {
var args, error, error1, funcName;
funcName = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
try {
return DEFAULT_CALLBACKS[funcName].apply(this, args);
} catch (error1) {
error = error1;
return $.error(error + " Or maybe At.js doesn't have function " + funcName);
}
};
Controller.prototype.trigger = function(name, data) {
var alias, eventName;
if (data == null) {
data = [];
}
data.push(this);
alias = this.getOpt('alias');
eventName = alias ? name + "-" + alias + ".atwho" : name + ".atwho";
return this.$inputor.trigger(eventName, data);
};
Controller.prototype.callbacks = function(funcName) {
return this.getOpt("callbacks")[funcName] || DEFAULT_CALLBACKS[funcName];
};
Controller.prototype.getOpt = function(at, default_value) {
var e, error1;
try {
return this.setting[at];
} catch (error1) {
e = error1;
return null;
}
};
Controller.prototype.insertContentFor = function($li) {
var data, tpl;
tpl = this.getOpt('insertTpl');
data = $.extend({}, $li.data('item-data'), {
'atwho-at': this.at
});
return this.callbacks("tplEval").call(this, tpl, data, "onInsert");
};
Controller.prototype.renderView = function(data) {
var searchKey;
searchKey = this.getOpt("searchKey");
data = this.callbacks("sorter").call(this, this.query.text, data.slice(0, 1001), searchKey);
return this.view.render(data.slice(0, this.getOpt('limit')));
};
Controller.arrayToDefaultHash = function(data) {
var i, item, len, results;
if (!$.isArray(data)) {
return data;
}
results = [];
for (i = 0, len = data.length; i < len; i++) {
item = data[i];
if ($.isPlainObject(item)) {
results.push(item);
} else {
results.push({
name: item
});
}
}
return results;
};
Controller.prototype.lookUp = function(e) {
var query, wait;
if (e && e.type === 'click' && !this.getOpt('lookUpOnClick')) {
return;
}
if (this.getOpt('suspendOnComposing') && this.app.isComposing) {
return;
}
query = this.catchQuery(e);
if (!query) {
this.expectedQueryCBId = null;
return query;
}
this.app.setContextFor(this.at);
if (wait = this.getOpt('delay')) {
this._delayLookUp(query, wait);
} else {
this._lookUp(query);
}
return query;
};
Controller.prototype._delayLookUp = function(query, wait) {
var now, remaining;
now = Date.now ? Date.now() : new Date().getTime();
this.previousCallTime || (this.previousCallTime = now);
remaining = wait - (now - this.previousCallTime);
if ((0 < remaining && remaining < wait)) {
this.previousCallTime = now;
this._stopDelayedCall();
return this.delayedCallTimeout = setTimeout((function(_this) {
return function() {
_this.previousCallTime = 0;
_this.delayedCallTimeout = null;
return _this._lookUp(query);
};
})(this), wait);
} else {
this._stopDelayedCall();
if (this.previousCallTime !== now) {
this.previousCallTime = 0;
}
return this._lookUp(query);
}
};
Controller.prototype._stopDelayedCall = function() {
if (this.delayedCallTimeout) {
clearTimeout(this.delayedCallTimeout);
return this.delayedCallTimeout = null;
}
};
Controller.prototype._generateQueryCBId = function() {
return {};
};
Controller.prototype._lookUp = function(query) {
var _callback;
_callback = function(queryCBId, data) {
if (queryCBId !== this.expectedQueryCBId) {
return;
}
if (data && data.length > 0) {
return this.renderView(this.constructor.arrayToDefaultHash(data));
} else {
return this.view.hide();
}
};
this.expectedQueryCBId = this._generateQueryCBId();
return this.model.query(query.text, $.proxy(_callback, this, this.expectedQueryCBId));
};
return Controller;
})();
var TextareaController,
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
TextareaController = (function(superClass) {
extend(TextareaController, superClass);
function TextareaController() {
return TextareaController.__super__.constructor.apply(this, arguments);
}
TextareaController.prototype.catchQuery = function() {
var caretPos, content, end, isString, query, start, subtext;
content = this.$inputor.val();
caretPos = this.$inputor.caret('pos', {
iframe: this.app.iframe
});
subtext = content.slice(0, caretPos);
query = this.callbacks("matcher").call(this, this.at, subtext, this.getOpt('startWithSpace'), this.getOpt("acceptSpaceBar"));
isString = typeof query === 'string';
if (isString && query.length < this.getOpt('minLen', 0)) {
return;
}
if (isString && query.length <= this.getOpt('maxLen', 20)) {
start = caretPos - query.length;
end = start + query.length;
this.pos = start;
query = {
'text': query,
'headPos': start,
'endPos': end
};
this.trigger("matched", [this.at, query.text]);
} else {
query = null;
this.view.hide();
}
return this.query = query;
};
TextareaController.prototype.rect = function() {
var c, iframeOffset, scaleBottom;
if (!(c = this.$inputor.caret('offset', this.pos - 1, {
iframe: this.app.iframe
}))) {
return;
}
if (this.app.iframe && !this.app.iframeAsRoot) {
iframeOffset = $(this.app.iframe).offset();
c.left += iframeOffset.left;
c.top += iframeOffset.top;
}
scaleBottom = this.app.document.selection ? 0 : 2;
return {
left: c.left,
top: c.top,
bottom: c.top + c.height + scaleBottom
};
};
TextareaController.prototype.insert = function(content, $li) {
var $inputor, source, startStr, suffix, text;
$inputor = this.$inputor;
source = $inputor.val();
startStr = source.slice(0, Math.max(this.query.headPos - this.at.length, 0));
suffix = (suffix = this.getOpt('suffix')) === "" ? suffix : suffix || " ";
content += suffix;
text = "" + startStr + content + (source.slice(this.query['endPos'] || 0));
$inputor.val(text);
$inputor.caret('pos', startStr.length + content.length, {
iframe: this.app.iframe
});
if (!$inputor.is(':focus')) {
$inputor.focus();
}
return $inputor.change();
};
return TextareaController;
})(Controller);
var EditableController,
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
EditableController = (function(superClass) {
extend(EditableController, superClass);
function EditableController() {
return EditableController.__super__.constructor.apply(this, arguments);
}
EditableController.prototype._getRange = function() {
var sel;
sel = this.app.window.getSelection();
if (sel.rangeCount > 0) {
return sel.getRangeAt(0);
}
};
EditableController.prototype._setRange = function(position, node, range) {
if (range == null) {
range = this._getRange();
}
if (!range) {
return;
}
node = $(node)[0];
if (position === 'after') {
range.setEndAfter(node);
range.setStartAfter(node);
} else {
range.setEndBefore(node);
range.setStartBefore(node);
}
range.collapse(false);
return this._clearRange(range);
};
EditableController.prototype._clearRange = function(range) {
var sel;
if (range == null) {
range = this._getRange();
}
sel = this.app.window.getSelection();
if (this.ctrl_a_pressed == null) {
sel.removeAllRanges();
return sel.addRange(range);
}
};
EditableController.prototype._movingEvent = function(e) {
var ref;
return e.type === 'click' || ((ref = e.which) === KEY_CODE.RIGHT || ref === KEY_CODE.LEFT || ref === KEY_CODE.UP || ref === KEY_CODE.DOWN);
};
EditableController.prototype._unwrap = function(node) {
var next;
node = $(node).unwrap().get(0);
if ((next = node.nextSibling) && next.nodeValue) {
node.nodeValue += next.nodeValue;
$(next).remove();
}
return node;
};
EditableController.prototype.catchQuery = function(e) {
var $inserted, $query, _range, index, inserted, isString, lastNode, matched, offset, query, query_content, range;
if (!(range = this._getRange())) {
return;
}
if (!range.collapsed) {
return;
}
if (e.which === KEY_CODE.ENTER) {
($query = $(range.startContainer).closest('.atwho-query')).contents().unwrap();
if ($query.is(':empty')) {
$query.remove();
}
($query = $(".atwho-query", this.app.document)).text($query.text()).contents().last().unwrap();
this._clearRange();
return;
}
if (/firefox/i.test(navigator.userAgent)) {
if ($(range.startContainer).is(this.$inputor)) {
this._clearRange();
return;
}
if (e.which === KEY_CODE.BACKSPACE && range.startContainer.nodeType === document.ELEMENT_NODE && (offset = range.startOffset - 1) >= 0) {
_range = range.cloneRange();
_range.setStart(range.startContainer, offset);
if ($(_range.cloneContents()).contents().last().is('.atwho-inserted')) {
inserted = $(range.startContainer).contents().get(offset);
this._setRange('after', $(inserted).contents().last());
}
} else if (e.which === KEY_CODE.LEFT && range.startContainer.nodeType === document.TEXT_NODE) {
$inserted = $(range.startContainer.previousSibling);
if ($inserted.is('.atwho-inserted') && range.startOffset === 0) {
this._setRange('after', $inserted.contents().last());
}
}
}
$(range.startContainer).closest('.atwho-inserted').addClass('atwho-query').siblings().removeClass('atwho-query');
if (($query = $(".atwho-query", this.app.document)).length > 0 && $query.is(':empty') && $query.text().length === 0) {
$query.remove();
}
if (!this._movingEvent(e)) {
$query.removeClass('atwho-inserted');
}
if ($query.length > 0) {
switch (e.which) {
case KEY_CODE.LEFT:
this._setRange('before', $query.get(0), range);
$query.removeClass('atwho-query');
return;
case KEY_CODE.RIGHT:
this._setRange('after', $query.get(0).nextSibling, range);
$query.removeClass('atwho-query');
return;
}
}
if ($query.length > 0 && (query_content = $query.attr('data-atwho-at-query'))) {
$query.empty().html(query_content).attr('data-atwho-at-query', null);
this._setRange('after', $query.get(0), range);
}
_range = range.cloneRange();
_range.setStart(range.startContainer, 0);
matched = this.callbacks("matcher").call(this, this.at, _range.toString(), this.getOpt('startWithSpace'), this.getOpt("acceptSpaceBar"));
isString = typeof matched === 'string';
if ($query.length === 0 && isString && (index = range.startOffset - this.at.length - matched.length) >= 0) {
range.setStart(range.startContainer, index);
$query = $('<span/>', this.app.document).attr(this.getOpt("editableAtwhoQueryAttrs")).addClass('atwho-query');
range.surroundContents($query.get(0));
lastNode = $query.contents().last().get(0);
if (/firefox/i.test(navigator.userAgent)) {
range.setStart(lastNode, lastNode.length);
range.setEnd(lastNode, lastNode.length);
this._clearRange(range);
} else {
this._setRange('after', lastNode, range);
}
}
if (isString && matched.length < this.getOpt('minLen', 0)) {
return;
}
if (isString && matched.length <= this.getOpt('maxLen', 20)) {
query = {
text: matched,
el: $query
};
this.trigger("matched", [this.at, query.text]);
return this.query = query;
} else {
this.view.hide();
this.query = {
el: $query
};
if ($query.text().indexOf(this.at) >= 0) {
if (this._movingEvent(e) && $query.hasClass('atwho-inserted')) {
$query.removeClass('atwho-query');
} else if (false !== this.callbacks('afterMatchFailed').call(this, this.at, $query)) {
this._setRange("after", this._unwrap($query.text($query.text()).contents().first()));
}
}
return null;
}
};
EditableController.prototype.rect = function() {
var $iframe, iframeOffset, rect;
rect = this.query.el.offset();
if (this.app.iframe && !this.app.iframeAsRoot) {
iframeOffset = ($iframe = $(this.app.iframe)).offset();
rect.left += iframeOffset.left - this.$inputor.scrollLeft();
rect.top += iframeOffset.top - this.$inputor.scrollTop();
}
rect.bottom = rect.top + this.query.el.height();
return rect;
};
EditableController.prototype.insert = function(content, $li) {
var data, range, suffix, suffixNode;
if (!this.$inputor.is(':focus')) {
this.$inputor.focus();
}
suffix = (suffix = this.getOpt('suffix')) === "" ? suffix : suffix || "\u00A0";
data = $li.data('item-data');
this.query.el.removeClass('atwho-query').addClass('atwho-inserted').html(content).attr('data-atwho-at-query', "" + data['atwho-at'] + this.query.text);
if (range = this._getRange()) {
range.setEndAfter(this.query.el[0]);
range.collapse(false);
range.insertNode(suffixNode = this.app.document.createTextNode("\u200D" + suffix));
this._setRange('after', suffixNode, range);
}
if (!this.$inputor.is(':focus')) {
this.$inputor.focus();
}
return this.$inputor.change();
};
return EditableController;
})(Controller);
var Model;
Model = (function() {
function Model(context) {
this.context = context;
this.at = this.context.at;
this.storage = this.context.$inputor;
}
Model.prototype.destroy = function() {
return this.storage.data(this.at, null);
};
Model.prototype.saved = function() {
return this.fetch() > 0;
};
Model.prototype.query = function(query, callback) {
var _remoteFilter, data, searchKey;
data = this.fetch();
searchKey = this.context.getOpt("searchKey");
data = this.context.callbacks('filter').call(this.context, query, data, searchKey) || [];
_remoteFilter = this.context.callbacks('remoteFilter');
if (data.length > 0 || (!_remoteFilter && data.length === 0)) {
return callback(data);
} else {
return _remoteFilter.call(this.context, query, callback);
}
};
Model.prototype.fetch = function() {
return this.storage.data(this.at) || [];
};
Model.prototype.save = function(data) {
return this.storage.data(this.at, this.context.callbacks("beforeSave").call(this.context, data || []));
};
Model.prototype.load = function(data) {
if (!(this.saved() || !data)) {
return this._load(data);
}
};
Model.prototype.reload = function(data) {
return this._load(data);
};
Model.prototype._load = function(data) {
if (typeof data === "string") {
return $.ajax(data, {
dataType: "json"
}).done((function(_this) {
return function(data) {
return _this.save(data);
};
})(this));
} else {
return this.save(data);
}
};
return Model;
})();
var View;
View = (function() {
function View(context) {
this.context = context;
this.$el = $("<div class='atwho-view'><ul class='atwho-view-ul'></ul></div>");
this.$elUl = this.$el.children();
this.timeoutID = null;
this.context.$el.append(this.$el);
this.bindEvent();
}
View.prototype.init = function() {
var header_tpl, id;
id = this.context.getOpt("alias") || this.context.at.charCodeAt(0);
header_tpl = this.context.getOpt("headerTpl");
if (header_tpl && this.$el.children().length === 1) {
this.$el.prepend(header_tpl);
}
return this.$el.attr({
'id': "at-view-" + id
});
};
View.prototype.destroy = function() {
return this.$el.remove();
};
View.prototype.bindEvent = function() {
var $menu, lastCoordX, lastCoordY;
$menu = this.$el.find('ul');
lastCoordX = 0;
lastCoordY = 0;
return $menu.on('mousemove.atwho-view', 'li', (function(_this) {
return function(e) {
var $cur;
if (lastCoordX === e.clientX && lastCoordY === e.clientY) {
return;
}
lastCoordX = e.clientX;
lastCoordY = e.clientY;
$cur = $(e.currentTarget);
if ($cur.hasClass('cur')) {
return;
}
$menu.find('.cur').removeClass('cur');
return $cur.addClass('cur');
};
})(this)).on('click.atwho-view', 'li', (function(_this) {
return function(e) {
$menu.find('.cur').removeClass('cur');
$(e.currentTarget).addClass('cur');
_this.choose(e);
return e.preventDefault();
};
})(this));
};
View.prototype.visible = function() {
return this.$el.is(":visible");
};
View.prototype.highlighted = function() {
return this.$el.find(".cur").length > 0;
};
View.prototype.choose = function(e) {
var $li, content;
if (($li = this.$el.find(".cur")).length) {
content = this.context.insertContentFor($li);
this.context._stopDelayedCall();
this.context.insert(this.context.callbacks("beforeInsert").call(this.context, content, $li, e), $li);
this.context.trigger("inserted", [$li, e]);
this.hide(e);
}
if (this.context.getOpt("hideWithoutSuffix")) {
return this.stopShowing = true;
}
};
View.prototype.reposition = function(rect) {
var _window, offset, overflowOffset, ref;
_window = this.context.app.iframeAsRoot ? this.context.app.window : window;
if (rect.bottom + this.$el.height() - $(_window).scrollTop() > $(_window).height()) {
rect.bottom = rect.top - this.$el.height();
}
if (rect.left > (overflowOffset = $(_window).width() - this.$el.width() - 5)) {
rect.left = overflowOffset;
}
offset = {
left: rect.left,
top: rect.bottom
};
if ((ref = this.context.callbacks("beforeReposition")) != null) {
ref.call(this.context, offset);
}
this.$el.offset(offset);
return this.context.trigger("reposition", [offset]);
};
View.prototype.next = function() {
var cur, next, nextEl, offset;
cur = this.$el.find('.cur').removeClass('cur');
next = cur.next();
if (!next.length) {
next = this.$el.find('li:first');
}
next.addClass('cur');
nextEl = next[0];
offset = nextEl.offsetTop + nextEl.offsetHeight + (nextEl.nextSibling ? nextEl.nextSibling.offsetHeight : 0);
return this.scrollTop(Math.max(0, offset - this.$el.height()));
};
View.prototype.prev = function() {
var cur, offset, prev, prevEl;
cur = this.$el.find('.cur').removeClass('cur');
prev = cur.prev();
if (!prev.length) {
prev = this.$el.find('li:last');
}
prev.addClass('cur');
prevEl = prev[0];
offset = prevEl.offsetTop + prevEl.offsetHeight + (prevEl.nextSibling ? prevEl.nextSibling.offsetHeight : 0);
return this.scrollTop(Math.max(0, offset - this.$el.height()));
};
View.prototype.scrollTop = function(scrollTop) {
var scrollDuration;
scrollDuration = this.context.getOpt('scrollDuration');
if (scrollDuration) {
return this.$elUl.animate({
scrollTop: scrollTop
}, scrollDuration);
} else {
return this.$elUl.scrollTop(scrollTop);
}
};
View.prototype.show = function() {
var rect;
if (this.stopShowing) {
this.stopShowing = false;
return;
}
if (!this.visible()) {
this.$el.show();
this.$el.scrollTop(0);
this.context.trigger('shown');
}
if (rect = this.context.rect()) {
return this.reposition(rect);
}
};
View.prototype.hide = function(e, time) {
var callback;
if (!this.visible()) {
return;
}
if (isNaN(time)) {
this.$el.hide();
return this.context.trigger('hidden', [e]);
} else {
callback = (function(_this) {
return function() {
return _this.hide();
};
})(this);
clearTimeout(this.timeoutID);
return this.timeoutID = setTimeout(callback, time);
}
};
View.prototype.render = function(list) {
var $li, $ul, i, item, len, li, tpl;
if (!($.isArray(list) && list.length > 0)) {
this.hide();
return;
}
this.$el.find('ul').empty();
$ul = this.$el.find('ul');
tpl = this.context.getOpt('displayTpl');
for (i = 0, len = list.length; i < len; i++) {
item = list[i];
item = $.extend({}, item, {
'atwho-at': this.context.at
});
li = this.context.callbacks("tplEval").call(this.context, tpl, item, "onDisplay");
$li = $(this.context.callbacks("highlighter").call(this.context, li, this.context.query.text));
$li.data("item-data", item);
$ul.append($li);
}
this.show();
if (this.context.getOpt('highlightFirst')) {
return $ul.find("li:first").addClass("cur");
}
};
return View;
})();
var Api;
Api = {
load: function(at, data) {
var c;
if (c = this.controller(at)) {
return c.model.load(data);
}
},
isSelecting: function() {
var ref;
return !!((ref = this.controller()) != null ? ref.view.visible() : void 0);
},
hide: function() {
var ref;
return (ref = this.controller()) != null ? ref.view.hide() : void 0;
},
reposition: function() {
var c;
if (c = this.controller()) {
return c.view.reposition(c.rect());
}
},
setIframe: function(iframe, asRoot) {
this.setupRootElement(iframe, asRoot);
return null;
},
run: function() {
return this.dispatch();
},
destroy: function() {
this.shutdown();
return this.$inputor.data('atwho', null);
}
};
$.fn.atwho = function(method) {
var _args, result;
_args = arguments;
result = null;
this.filter('textarea, input, [contenteditable=""], [contenteditable=true]').each(function() {
var $this, app;
if (!(app = ($this = $(this)).data("atwho"))) {
$this.data('atwho', (app = new App(this)));
}
if (typeof method === 'object' || !method) {
return app.reg(method.at, method);
} else if (Api[method] && app) {
return result = Api[method].apply(app, Array.prototype.slice.call(_args, 1));
} else {
return $.error("Method " + method + " does not exist on jQuery.atwho");
}
});
if (result != null) {
return result;
} else {
return this;
}
};
$.fn.atwho["default"] = {
at: void 0,
alias: void 0,
data: null,
displayTpl: "<li>${name}</li>",
insertTpl: "${atwho-at}${name}",
headerTpl: null,
callbacks: DEFAULT_CALLBACKS,
searchKey: "name",
suffix: void 0,
hideWithoutSuffix: false,
startWithSpace: true,
acceptSpaceBar: false,
highlightFirst: true,
limit: 5,
maxLen: 20,
minLen: 0,
displayTimeout: 300,
delay: null,
spaceSelectsMatch: false,
tabSelectsMatch: true,
editableAtwhoQueryAttrs: {},
scrollDuration: 150,
suspendOnComposing: true,
lookUpOnClick: true
};
$.fn.atwho.debug = false;
}));
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(["jquery"], function ($) {
return (root.returnExportsGlobal = factory($));
});
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like enviroments that support module.exports,
// like Node.
module.exports = factory(require("jquery"));
} else {
factory(jQuery);
}
}(this, function ($) {
/*
Implement Github like autocomplete mentions
http://ichord.github.com/At.js
Copyright (c) 2013 chord.luo@gmail.com
Licensed under the MIT license.
*/
/*
本插件操作 textarea 或者 input 内的插入符
只实现了获得插入符在文本框中的位置,我设置
插入符的位置.
*/
"use strict";
var EditableCaret, InputCaret, Mirror, Utils, discoveryIframeOf, methods, oDocument, oFrame, oWindow, pluginName, setContextBy;
pluginName = 'caret';
EditableCaret = (function() {
function EditableCaret($inputor) {
this.$inputor = $inputor;
this.domInputor = this.$inputor[0];
}
EditableCaret.prototype.setPos = function(pos) {
var fn, found, offset, sel;
if (sel = oWindow.getSelection()) {
offset = 0;
found = false;
(fn = function(pos, parent) {
var node, range, _i, _len, _ref, _results;
_ref = parent.childNodes;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
node = _ref[_i];
if (found) {
break;
}
if (node.nodeType === 3) {
if (offset + node.length >= pos) {
found = true;
range = oDocument.createRange();
range.setStart(node, pos - offset);
sel.removeAllRanges();
sel.addRange(range);
break;
} else {
_results.push(offset += node.length);
}
} else {
_results.push(fn(pos, node));
}
}
return _results;
})(pos, this.domInputor);
}
return this.domInputor;
};
EditableCaret.prototype.getIEPosition = function() {
return this.getPosition();
};
EditableCaret.prototype.getPosition = function() {
var inputor_offset, offset;
offset = this.getOffset();
inputor_offset = this.$inputor.offset();
offset.left -= inputor_offset.left;
offset.top -= inputor_offset.top;
return offset;
};
EditableCaret.prototype.getOldIEPos = function() {
var preCaretTextRange, textRange;
textRange = oDocument.selection.createRange();
preCaretTextRange = oDocument.body.createTextRange();
preCaretTextRange.moveToElementText(this.domInputor);
preCaretTextRange.setEndPoint("EndToEnd", textRange);
return preCaretTextRange.text.length;
};
EditableCaret.prototype.getPos = function() {
var clonedRange, pos, range;
if (range = this.range()) {
clonedRange = range.cloneRange();
clonedRange.selectNodeContents(this.domInputor);
clonedRange.setEnd(range.endContainer, range.endOffset);
pos = clonedRange.toString().length;
clonedRange.detach();
return pos;
} else if (oDocument.selection) {
return this.getOldIEPos();
}
};
EditableCaret.prototype.getOldIEOffset = function() {
var range, rect;
range = oDocument.selection.createRange().duplicate();
range.moveStart("character", -1);
rect = range.getBoundingClientRect();
return {
height: rect.bottom - rect.top,
left: rect.left,
top: rect.top
};
};
EditableCaret.prototype.getOffset = function(pos) {
var clonedRange, offset, range, rect, shadowCaret;
if (oWindow.getSelection && (range = this.range())) {
if (range.endOffset - 1 > 0 && range.endContainer !== this.domInputor) {
clonedRange = range.cloneRange();
clonedRange.setStart(range.endContainer, range.endOffset - 1);
clonedRange.setEnd(range.endContainer, range.endOffset);
rect = clonedRange.getBoundingClientRect();
offset = {
height: rect.height,
left: rect.left + rect.width,
top: rect.top
};
clonedRange.detach();
}
if (!offset || (offset != null ? offset.height : void 0) === 0) {
clonedRange = range.cloneRange();
shadowCaret = $(oDocument.createTextNode("|"));
clonedRange.insertNode(shadowCaret[0]);
clonedRange.selectNode(shadowCaret[0]);
rect = clonedRange.getBoundingClientRect();
offset = {
height: rect.height,
left: rect.left,
top: rect.top
};
shadowCaret.remove();
clonedRange.detach();
}
} else if (oDocument.selection) {
offset = this.getOldIEOffset();
}
if (offset) {
offset.top += $(oWindow).scrollTop();
offset.left += $(oWindow).scrollLeft();
}
return offset;
};
EditableCaret.prototype.range = function() {
var sel;
if (!oWindow.getSelection) {
return;
}
sel = oWindow.getSelection();
if (sel.rangeCount > 0) {
return sel.getRangeAt(0);
} else {
return null;
}
};
return EditableCaret;
})();
InputCaret = (function() {
function InputCaret($inputor) {
this.$inputor = $inputor;
this.domInputor = this.$inputor[0];
}
InputCaret.prototype.getIEPos = function() {
var endRange, inputor, len, normalizedValue, pos, range, textInputRange;
inputor = this.domInputor;
range = oDocument.selection.createRange();
pos = 0;
if (range && range.parentElement() === inputor) {
normalizedValue = inputor.value.replace(/\r\n/g, "\n");
len = normalizedValue.length;
textInputRange = inputor.createTextRange();
textInputRange.moveToBookmark(range.getBookmark());
endRange = inputor.createTextRange();
endRange.collapse(false);
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
pos = len;
} else {
pos = -textInputRange.moveStart("character", -len);
}
}
return pos;
};
InputCaret.prototype.getPos = function() {
if (oDocument.selection) {
return this.getIEPos();
} else {
return this.domInputor.selectionStart;
}
};
InputCaret.prototype.setPos = function(pos) {
var inputor, range;
inputor = this.domInputor;
if (oDocument.selection) {
range = inputor.createTextRange();
range.move("character", pos);
range.select();
} else if (inputor.setSelectionRange) {
inputor.setSelectionRange(pos, pos);
}
return inputor;
};
InputCaret.prototype.getIEOffset = function(pos) {
var h, textRange, x, y;
textRange = this.domInputor.createTextRange();
pos || (pos = this.getPos());
textRange.move('character', pos);
x = textRange.boundingLeft;
y = textRange.boundingTop;
h = textRange.boundingHeight;
return {
left: x,
top: y,
height: h
};
};
InputCaret.prototype.getOffset = function(pos) {
var $inputor, offset, position;
$inputor = this.$inputor;
if (oDocument.selection) {
offset = this.getIEOffset(pos);
offset.top += $(oWindow).scrollTop() + $inputor.scrollTop();
offset.left += $(oWindow).scrollLeft() + $inputor.scrollLeft();
return offset;
} else {
offset = $inputor.offset();
position = this.getPosition(pos);
return offset = {
left: offset.left + position.left - $inputor.scrollLeft(),
top: offset.top + position.top - $inputor.scrollTop(),
height: position.height
};
}
};
InputCaret.prototype.getPosition = function(pos) {
var $inputor, at_rect, end_range, format, html, mirror, start_range;
$inputor = this.$inputor;
format = function(value) {
value = value.replace(/<|>|`|"|&/g, '?').replace(/\r\n|\r|\n/g, "<br/>");
if (/firefox/i.test(navigator.userAgent)) {
value = value.replace(/\s/g, '&nbsp;');
}
return value;
};
if (pos === void 0) {
pos = this.getPos();
}
start_range = $inputor.val().slice(0, pos);
end_range = $inputor.val().slice(pos);
html = "<span style='position: relative; display: inline;'>" + format(start_range) + "</span>";
html += "<span id='caret' style='position: relative; display: inline;'>|</span>";
html += "<span style='position: relative; display: inline;'>" + format(end_range) + "</span>";
mirror = new Mirror($inputor);
return at_rect = mirror.create(html).rect();
};
InputCaret.prototype.getIEPosition = function(pos) {
var h, inputorOffset, offset, x, y;
offset = this.getIEOffset(pos);
inputorOffset = this.$inputor.offset();
x = offset.left - inputorOffset.left;
y = offset.top - inputorOffset.top;
h = offset.height;
return {
left: x,
top: y,
height: h
};
};
return InputCaret;
})();
Mirror = (function() {
Mirror.prototype.css_attr = ["borderBottomWidth", "borderLeftWidth", "borderRightWidth", "borderTopStyle", "borderRightStyle", "borderBottomStyle", "borderLeftStyle", "borderTopWidth", "boxSizing", "fontFamily", "fontSize", "fontWeight", "height", "letterSpacing", "lineHeight", "marginBottom", "marginLeft", "marginRight", "marginTop", "outlineWidth", "overflow", "overflowX", "overflowY", "paddingBottom", "paddingLeft", "paddingRight", "paddingTop", "textAlign", "textOverflow", "textTransform", "whiteSpace", "wordBreak", "wordWrap"];
function Mirror($inputor) {
this.$inputor = $inputor;
}
Mirror.prototype.mirrorCss = function() {
var css,
_this = this;
css = {
position: 'absolute',
left: -9999,
top: 0,
zIndex: -20000
};
if (this.$inputor.prop('tagName') === 'TEXTAREA') {
this.css_attr.push('width');
}
$.each(this.css_attr, function(i, p) {
return css[p] = _this.$inputor.css(p);
});
return css;
};
Mirror.prototype.create = function(html) {
this.$mirror = $('<div></div>');
this.$mirror.css(this.mirrorCss());
this.$mirror.html(html);
this.$inputor.after(this.$mirror);
return this;
};
Mirror.prototype.rect = function() {
var $flag, pos, rect;
$flag = this.$mirror.find("#caret");
pos = $flag.position();
rect = {
left: pos.left,
top: pos.top,
height: $flag.height()
};
this.$mirror.remove();
return rect;
};
return Mirror;
})();
Utils = {
contentEditable: function($inputor) {
return !!($inputor[0].contentEditable && $inputor[0].contentEditable === 'true');
}
};
methods = {
pos: function(pos) {
if (pos || pos === 0) {
return this.setPos(pos);
} else {
return this.getPos();
}
},
position: function(pos) {
if (oDocument.selection) {
return this.getIEPosition(pos);
} else {
return this.getPosition(pos);
}
},
offset: function(pos) {
var offset;
offset = this.getOffset(pos);
return offset;
}
};
oDocument = null;
oWindow = null;
oFrame = null;
setContextBy = function(settings) {
var iframe;
if (iframe = settings != null ? settings.iframe : void 0) {
oFrame = iframe;
oWindow = iframe.contentWindow;
return oDocument = iframe.contentDocument || oWindow.document;
} else {
oFrame = void 0;
oWindow = window;
return oDocument = document;
}
};
discoveryIframeOf = function($dom) {
var error;
oDocument = $dom[0].ownerDocument;
oWindow = oDocument.defaultView || oDocument.parentWindow;
try {
return oFrame = oWindow.frameElement;
} catch (_error) {
error = _error;
}
};
$.fn.caret = function(method, value, settings) {
var caret;
if (methods[method]) {
if ($.isPlainObject(value)) {
setContextBy(value);
value = void 0;
} else {
setContextBy(settings);
}
caret = Utils.contentEditable(this) ? new EditableCaret(this) : new InputCaret(this);
return methods[method].apply(caret, [value]);
} else {
return $.error("Method " + method + " does not exist on jQuery.caret");
}
};
$.fn.caret.EditableCaret = EditableCaret;
$.fn.caret.InputCaret = InputCaret;
$.fn.caret.Utils = Utils;
$.fn.caret.apis = methods;
}));
......@@ -8,10 +8,23 @@ The MIT License
Copyright (c) 2012-2013 Sasha Koss & Rico Sta. Cruz
*/
(function() {
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module unless amdModuleId is set
define(["jquery"], function (a0) {
return (factory(a0));
});
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory(require("jquery"));
} else {
factory(jQuery);
}
}(this, function($) {
var $, $document;
$ = window.jQuery || (typeof require === "function" ? require('jquery') : void 0);
$ = $ || window.jQuery || (typeof require === "function" ? require('jquery') : void 0);
$document = $(document);
......@@ -46,4 +59,4 @@ Copyright (c) 2012-2013 Sasha Koss & Rico Sta. Cruz
$.turbo.use('page:load', 'page:fetch');
}).call(this);
}));
// Turbolinks Classic v2.5.3 compiled from CoffeeScript
(function() {
var CSRFToken, Click, ComponentUrl, EVENTS, Link, ProgressBar, browserIsntBuggy, browserSupportsCustomEvents, browserSupportsPushState, browserSupportsTurbolinks, bypassOnLoadPopstate, cacheCurrentPage, cacheSize, changePage, clone, constrainPageCacheTo, createDocument, crossOriginRedirect, currentState, enableProgressBar, enableTransitionCache, executeScriptTags, extractTitleAndBody, fetch, fetchHistory, fetchReplacement, historyStateIsDefined, initializeTurbolinks, installDocumentReadyPageEventTriggers, installHistoryChangeHandler, installJqueryAjaxSuccessPageUpdateTrigger, loadedAssets, manuallyTriggerHashChangeForFirefox, pageCache, pageChangePrevented, pagesCached, popCookie, processResponse, progressBar, recallScrollPosition, ref, referer, reflectNewUrl, reflectRedirectedUrl, rememberCurrentState, rememberCurrentUrl, rememberReferer, removeNoscriptTags, requestMethodIsSafe, resetScrollPosition, setAutofocusElement, transitionCacheEnabled, transitionCacheFor, triggerEvent, visit, xhr,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty,
slice = [].slice,
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
pageCache = {};
cacheSize = 10;
transitionCacheEnabled = false;
progressBar = null;
currentState = null;
loadedAssets = null;
referer = null;
xhr = null;
EVENTS = {
BEFORE_CHANGE: 'page:before-change',
FETCH: 'page:fetch',
RECEIVE: 'page:receive',
CHANGE: 'page:change',
UPDATE: 'page:update',
LOAD: 'page:load',
RESTORE: 'page:restore',
BEFORE_UNLOAD: 'page:before-unload',
EXPIRE: 'page:expire'
};
fetch = function(url) {
var cachedPage;
url = new ComponentUrl(url);
rememberReferer();
cacheCurrentPage();
if (progressBar != null) {
progressBar.start();
}
if (transitionCacheEnabled && (cachedPage = transitionCacheFor(url.absolute))) {
fetchHistory(cachedPage);
return fetchReplacement(url, null, false);
} else {
return fetchReplacement(url, resetScrollPosition);
}
};
transitionCacheFor = function(url) {
var cachedPage;
cachedPage = pageCache[url];
if (cachedPage && !cachedPage.transitionCacheDisabled) {
return cachedPage;
}
};
enableTransitionCache = function(enable) {
if (enable == null) {
enable = true;
}
return transitionCacheEnabled = enable;
};
enableProgressBar = function(enable) {
if (enable == null) {
enable = true;
}
if (!browserSupportsTurbolinks) {
return;
}
if (enable) {
return progressBar != null ? progressBar : progressBar = new ProgressBar('html');
} else {
if (progressBar != null) {
progressBar.uninstall();
}
return progressBar = null;
}
};
fetchReplacement = function(url, onLoadFunction, showProgressBar) {
if (showProgressBar == null) {
showProgressBar = true;
}
triggerEvent(EVENTS.FETCH, {
url: url.absolute
});
if (xhr != null) {
xhr.abort();
}
xhr = new XMLHttpRequest;
xhr.open('GET', url.withoutHashForIE10compatibility(), true);
xhr.setRequestHeader('Accept', 'text/html, application/xhtml+xml, application/xml');
xhr.setRequestHeader('X-XHR-Referer', referer);
xhr.onload = function() {
var doc;
triggerEvent(EVENTS.RECEIVE, {
url: url.absolute
});
if (doc = processResponse()) {
reflectNewUrl(url);
reflectRedirectedUrl();
changePage.apply(null, extractTitleAndBody(doc));
manuallyTriggerHashChangeForFirefox();
if (typeof onLoadFunction === "function") {
onLoadFunction();
}
return triggerEvent(EVENTS.LOAD);
} else {
return document.location.href = crossOriginRedirect() || url.absolute;
}
};
if (progressBar && showProgressBar) {
xhr.onprogress = (function(_this) {
return function(event) {
var percent;
percent = event.lengthComputable ? event.loaded / event.total * 100 : progressBar.value + (100 - progressBar.value) / 10;
return progressBar.advanceTo(percent);
};
})(this);
}
xhr.onloadend = function() {
return xhr = null;
};
xhr.onerror = function() {
return document.location.href = url.absolute;
};
return xhr.send();
};
fetchHistory = function(cachedPage) {
if (xhr != null) {
xhr.abort();
}
changePage(cachedPage.title, cachedPage.body);
recallScrollPosition(cachedPage);
return triggerEvent(EVENTS.RESTORE);
};
cacheCurrentPage = function() {
var currentStateUrl;
currentStateUrl = new ComponentUrl(currentState.url);
pageCache[currentStateUrl.absolute] = {
url: currentStateUrl.relative,
body: document.body,
title: document.title,
positionY: window.pageYOffset,
positionX: window.pageXOffset,
cachedAt: new Date().getTime(),
transitionCacheDisabled: document.querySelector('[data-no-transition-cache]') != null
};
return constrainPageCacheTo(cacheSize);
};
pagesCached = function(size) {
if (size == null) {
size = cacheSize;
}
if (/^[\d]+$/.test(size)) {
return cacheSize = parseInt(size);
}
};
constrainPageCacheTo = function(limit) {
var cacheTimesRecentFirst, i, key, len, pageCacheKeys, results;
pageCacheKeys = Object.keys(pageCache);
cacheTimesRecentFirst = pageCacheKeys.map(function(url) {
return pageCache[url].cachedAt;
}).sort(function(a, b) {
return b - a;
});
results = [];
for (i = 0, len = pageCacheKeys.length; i < len; i++) {
key = pageCacheKeys[i];
if (!(pageCache[key].cachedAt <= cacheTimesRecentFirst[limit])) {
continue;
}
triggerEvent(EVENTS.EXPIRE, pageCache[key]);
results.push(delete pageCache[key]);
}
return results;
};
changePage = function(title, body, csrfToken, runScripts) {
triggerEvent(EVENTS.BEFORE_UNLOAD);
document.title = title;
document.documentElement.replaceChild(body, document.body);
if (csrfToken != null) {
CSRFToken.update(csrfToken);
}
setAutofocusElement();
if (runScripts) {
executeScriptTags();
}
currentState = window.history.state;
if (progressBar != null) {
progressBar.done();
}
triggerEvent(EVENTS.CHANGE);
return triggerEvent(EVENTS.UPDATE);
};
executeScriptTags = function() {
var attr, copy, i, j, len, len1, nextSibling, parentNode, ref, ref1, script, scripts;
scripts = Array.prototype.slice.call(document.body.querySelectorAll('script:not([data-turbolinks-eval="false"])'));
for (i = 0, len = scripts.length; i < len; i++) {
script = scripts[i];
if (!((ref = script.type) === '' || ref === 'text/javascript')) {
continue;
}
copy = document.createElement('script');
ref1 = script.attributes;
for (j = 0, len1 = ref1.length; j < len1; j++) {
attr = ref1[j];
copy.setAttribute(attr.name, attr.value);
}
if (!script.hasAttribute('async')) {
copy.async = false;
}
copy.appendChild(document.createTextNode(script.innerHTML));
parentNode = script.parentNode, nextSibling = script.nextSibling;
parentNode.removeChild(script);
parentNode.insertBefore(copy, nextSibling);
}
};
removeNoscriptTags = function(node) {
node.innerHTML = node.innerHTML.replace(/<noscript[\S\s]*?<\/noscript>/ig, '');
return node;
};
setAutofocusElement = function() {
var autofocusElement, list;
autofocusElement = (list = document.querySelectorAll('input[autofocus], textarea[autofocus]'))[list.length - 1];
if (autofocusElement && document.activeElement !== autofocusElement) {
return autofocusElement.focus();
}
};
reflectNewUrl = function(url) {
if ((url = new ComponentUrl(url)).absolute !== referer) {
return window.history.pushState({
turbolinks: true,
url: url.absolute
}, '', url.absolute);
}
};
reflectRedirectedUrl = function() {
var location, preservedHash;
if (location = xhr.getResponseHeader('X-XHR-Redirected-To')) {
location = new ComponentUrl(location);
preservedHash = location.hasNoHash() ? document.location.hash : '';
return window.history.replaceState(window.history.state, '', location.href + preservedHash);
}
};
crossOriginRedirect = function() {
var redirect;
if (((redirect = xhr.getResponseHeader('Location')) != null) && (new ComponentUrl(redirect)).crossOrigin()) {
return redirect;
}
};
rememberReferer = function() {
return referer = document.location.href;
};
rememberCurrentUrl = function() {
return window.history.replaceState({
turbolinks: true,
url: document.location.href
}, '', document.location.href);
};
rememberCurrentState = function() {
return currentState = window.history.state;
};
manuallyTriggerHashChangeForFirefox = function() {
var url;
if (navigator.userAgent.match(/Firefox/) && !(url = new ComponentUrl).hasNoHash()) {
window.history.replaceState(currentState, '', url.withoutHash());
return document.location.hash = url.hash;
}
};
recallScrollPosition = function(page) {
return window.scrollTo(page.positionX, page.positionY);
};
resetScrollPosition = function() {
if (document.location.hash) {
return document.location.href = document.location.href;
} else {
return window.scrollTo(0, 0);
}
};
clone = function(original) {
var copy, key, value;
if ((original == null) || typeof original !== 'object') {
return original;
}
copy = new original.constructor();
for (key in original) {
value = original[key];
copy[key] = clone(value);
}
return copy;
};
popCookie = function(name) {
var ref, value;
value = ((ref = document.cookie.match(new RegExp(name + "=(\\w+)"))) != null ? ref[1].toUpperCase() : void 0) || '';
document.cookie = name + '=; expires=Thu, 01-Jan-70 00:00:01 GMT; path=/';
return value;
};
triggerEvent = function(name, data) {
var event;
if (typeof Prototype !== 'undefined') {
Event.fire(document, name, data, true);
}
event = document.createEvent('Events');
if (data) {
event.data = data;
}
event.initEvent(name, true, true);
return document.dispatchEvent(event);
};
pageChangePrevented = function(url) {
return !triggerEvent(EVENTS.BEFORE_CHANGE, {
url: url
});
};
processResponse = function() {
var assetsChanged, clientOrServerError, doc, extractTrackAssets, intersection, validContent;
clientOrServerError = function() {
var ref;
return (400 <= (ref = xhr.status) && ref < 600);
};
validContent = function() {
var contentType;
return ((contentType = xhr.getResponseHeader('Content-Type')) != null) && contentType.match(/^(?:text\/html|application\/xhtml\+xml|application\/xml)(?:;|$)/);
};
extractTrackAssets = function(doc) {
var i, len, node, ref, results;
ref = doc.querySelector('head').childNodes;
results = [];
for (i = 0, len = ref.length; i < len; i++) {
node = ref[i];
if ((typeof node.getAttribute === "function" ? node.getAttribute('data-turbolinks-track') : void 0) != null) {
results.push(node.getAttribute('src') || node.getAttribute('href'));
}
}
return results;
};
assetsChanged = function(doc) {
var fetchedAssets;
loadedAssets || (loadedAssets = extractTrackAssets(document));
fetchedAssets = extractTrackAssets(doc);
return fetchedAssets.length !== loadedAssets.length || intersection(fetchedAssets, loadedAssets).length !== loadedAssets.length;
};
intersection = function(a, b) {
var i, len, ref, results, value;
if (a.length > b.length) {
ref = [b, a], a = ref[0], b = ref[1];
}
results = [];
for (i = 0, len = a.length; i < len; i++) {
value = a[i];
if (indexOf.call(b, value) >= 0) {
results.push(value);
}
}
return results;
};
if (!clientOrServerError() && validContent()) {
doc = createDocument(xhr.responseText);
if (doc && !assetsChanged(doc)) {
return doc;
}
}
};
extractTitleAndBody = function(doc) {
var title;
title = doc.querySelector('title');
return [title != null ? title.textContent : void 0, removeNoscriptTags(doc.querySelector('body')), CSRFToken.get(doc).token, 'runScripts'];
};
CSRFToken = {
get: function(doc) {
var tag;
if (doc == null) {
doc = document;
}
return {
node: tag = doc.querySelector('meta[name="csrf-token"]'),
token: tag != null ? typeof tag.getAttribute === "function" ? tag.getAttribute('content') : void 0 : void 0
};
},
update: function(latest) {
var current;
current = this.get();
if ((current.token != null) && (latest != null) && current.token !== latest) {
return current.node.setAttribute('content', latest);
}
}
};
createDocument = function(html) {
var doc;
doc = document.documentElement.cloneNode();
doc.innerHTML = html;
doc.head = doc.querySelector('head');
doc.body = doc.querySelector('body');
return doc;
};
ComponentUrl = (function() {
function ComponentUrl(original1) {
this.original = original1 != null ? original1 : document.location.href;
if (this.original.constructor === ComponentUrl) {
return this.original;
}
this._parse();
}
ComponentUrl.prototype.withoutHash = function() {
return this.href.replace(this.hash, '').replace('#', '');
};
ComponentUrl.prototype.withoutHashForIE10compatibility = function() {
return this.withoutHash();
};
ComponentUrl.prototype.hasNoHash = function() {
return this.hash.length === 0;
};
ComponentUrl.prototype.crossOrigin = function() {
return this.origin !== (new ComponentUrl).origin;
};
ComponentUrl.prototype._parse = function() {
var ref;
(this.link != null ? this.link : this.link = document.createElement('a')).href = this.original;
ref = this.link, this.href = ref.href, this.protocol = ref.protocol, this.host = ref.host, this.hostname = ref.hostname, this.port = ref.port, this.pathname = ref.pathname, this.search = ref.search, this.hash = ref.hash;
this.origin = [this.protocol, '//', this.hostname].join('');
if (this.port.length !== 0) {
this.origin += ":" + this.port;
}
this.relative = [this.pathname, this.search, this.hash].join('');
return this.absolute = this.href;
};
return ComponentUrl;
})();
Link = (function(superClass) {
extend(Link, superClass);
Link.HTML_EXTENSIONS = ['html'];
Link.allowExtensions = function() {
var extension, extensions, i, len;
extensions = 1 <= arguments.length ? slice.call(arguments, 0) : [];
for (i = 0, len = extensions.length; i < len; i++) {
extension = extensions[i];
Link.HTML_EXTENSIONS.push(extension);
}
return Link.HTML_EXTENSIONS;
};
function Link(link1) {
this.link = link1;
if (this.link.constructor === Link) {
return this.link;
}
this.original = this.link.href;
this.originalElement = this.link;
this.link = this.link.cloneNode(false);
Link.__super__.constructor.apply(this, arguments);
}
Link.prototype.shouldIgnore = function() {
return this.crossOrigin() || this._anchored() || this._nonHtml() || this._optOut() || this._target();
};
Link.prototype._anchored = function() {
return (this.hash.length > 0 || this.href.charAt(this.href.length - 1) === '#') && (this.withoutHash() === (new ComponentUrl).withoutHash());
};
Link.prototype._nonHtml = function() {
return this.pathname.match(/\.[a-z]+$/g) && !this.pathname.match(new RegExp("\\.(?:" + (Link.HTML_EXTENSIONS.join('|')) + ")?$", 'g'));
};
Link.prototype._optOut = function() {
var ignore, link;
link = this.originalElement;
while (!(ignore || link === document)) {
ignore = link.getAttribute('data-no-turbolink') != null;
link = link.parentNode;
}
return ignore;
};
Link.prototype._target = function() {
return this.link.target.length !== 0;
};
return Link;
})(ComponentUrl);
Click = (function() {
Click.installHandlerLast = function(event) {
if (!event.defaultPrevented) {
document.removeEventListener('click', Click.handle, false);
return document.addEventListener('click', Click.handle, false);
}
};
Click.handle = function(event) {
return new Click(event);
};
function Click(event1) {
this.event = event1;
if (this.event.defaultPrevented) {
return;
}
this._extractLink();
if (this._validForTurbolinks()) {
if (!pageChangePrevented(this.link.absolute)) {
visit(this.link.href);
}
this.event.preventDefault();
}
}
Click.prototype._extractLink = function() {
var link;
link = this.event.target;
while (!(!link.parentNode || link.nodeName === 'A')) {
link = link.parentNode;
}
if (link.nodeName === 'A' && link.href.length !== 0) {
return this.link = new Link(link);
}
};
Click.prototype._validForTurbolinks = function() {
return (this.link != null) && !(this.link.shouldIgnore() || this._nonStandardClick());
};
Click.prototype._nonStandardClick = function() {
return this.event.which > 1 || this.event.metaKey || this.event.ctrlKey || this.event.shiftKey || this.event.altKey;
};
return Click;
})();
ProgressBar = (function() {
var className;
className = 'turbolinks-progress-bar';
function ProgressBar(elementSelector) {
this.elementSelector = elementSelector;
this._trickle = bind(this._trickle, this);
this.value = 0;
this.content = '';
this.speed = 300;
this.opacity = 0.99;
this.install();
}
ProgressBar.prototype.install = function() {
this.element = document.querySelector(this.elementSelector);
this.element.classList.add(className);
this.styleElement = document.createElement('style');
document.head.appendChild(this.styleElement);
return this._updateStyle();
};
ProgressBar.prototype.uninstall = function() {
this.element.classList.remove(className);
return document.head.removeChild(this.styleElement);
};
ProgressBar.prototype.start = function() {
return this.advanceTo(5);
};
ProgressBar.prototype.advanceTo = function(value) {
var ref;
if ((value > (ref = this.value) && ref <= 100)) {
this.value = value;
this._updateStyle();
if (this.value === 100) {
return this._stopTrickle();
} else if (this.value > 0) {
return this._startTrickle();
}
}
};
ProgressBar.prototype.done = function() {
if (this.value > 0) {
this.advanceTo(100);
return this._reset();
}
};
ProgressBar.prototype._reset = function() {
var originalOpacity;
originalOpacity = this.opacity;
setTimeout((function(_this) {
return function() {
_this.opacity = 0;
return _this._updateStyle();
};
})(this), this.speed / 2);
return setTimeout((function(_this) {
return function() {
_this.value = 0;
_this.opacity = originalOpacity;
return _this._withSpeed(0, function() {
return _this._updateStyle(true);
});
};
})(this), this.speed);
};
ProgressBar.prototype._startTrickle = function() {
if (this.trickling) {
return;
}
this.trickling = true;
return setTimeout(this._trickle, this.speed);
};
ProgressBar.prototype._stopTrickle = function() {
return delete this.trickling;
};
ProgressBar.prototype._trickle = function() {
if (!this.trickling) {
return;
}
this.advanceTo(this.value + Math.random() / 2);
return setTimeout(this._trickle, this.speed);
};
ProgressBar.prototype._withSpeed = function(speed, fn) {
var originalSpeed, result;
originalSpeed = this.speed;
this.speed = speed;
result = fn();
this.speed = originalSpeed;
return result;
};
ProgressBar.prototype._updateStyle = function(forceRepaint) {
if (forceRepaint == null) {
forceRepaint = false;
}
if (forceRepaint) {
this._changeContentToForceRepaint();
}
return this.styleElement.textContent = this._createCSSRule();
};
ProgressBar.prototype._changeContentToForceRepaint = function() {
return this.content = this.content === '' ? ' ' : '';
};
ProgressBar.prototype._createCSSRule = function() {
return this.elementSelector + "." + className + "::before {\n content: '" + this.content + "';\n position: fixed;\n top: 0;\n left: 0;\n z-index: 2000;\n background-color: #0076ff;\n height: 3px;\n opacity: " + this.opacity + ";\n width: " + this.value + "%;\n transition: width " + this.speed + "ms ease-out, opacity " + (this.speed / 2) + "ms ease-in;\n transform: translate3d(0,0,0);\n}";
};
return ProgressBar;
})();
bypassOnLoadPopstate = function(fn) {
return setTimeout(fn, 500);
};
installDocumentReadyPageEventTriggers = function() {
return document.addEventListener('DOMContentLoaded', (function() {
triggerEvent(EVENTS.CHANGE);
return triggerEvent(EVENTS.UPDATE);
}), true);
};
installJqueryAjaxSuccessPageUpdateTrigger = function() {
if (typeof jQuery !== 'undefined') {
return jQuery(document).on('ajaxSuccess', function(event, xhr, settings) {
if (!jQuery.trim(xhr.responseText)) {
return;
}
return triggerEvent(EVENTS.UPDATE);
});
}
};
installHistoryChangeHandler = function(event) {
var cachedPage, ref;
if ((ref = event.state) != null ? ref.turbolinks : void 0) {
if (cachedPage = pageCache[(new ComponentUrl(event.state.url)).absolute]) {
cacheCurrentPage();
return fetchHistory(cachedPage);
} else {
return visit(event.target.location.href);
}
}
};
initializeTurbolinks = function() {
rememberCurrentUrl();
rememberCurrentState();
document.addEventListener('click', Click.installHandlerLast, true);
window.addEventListener('hashchange', function(event) {
rememberCurrentUrl();
return rememberCurrentState();
}, false);
return bypassOnLoadPopstate(function() {
return window.addEventListener('popstate', installHistoryChangeHandler, false);
});
};
historyStateIsDefined = window.history.state !== void 0 || navigator.userAgent.match(/Firefox\/2[6|7]/);
browserSupportsPushState = window.history && window.history.pushState && window.history.replaceState && historyStateIsDefined;
browserIsntBuggy = !navigator.userAgent.match(/CriOS\//);
requestMethodIsSafe = (ref = popCookie('request_method')) === 'GET' || ref === '';
browserSupportsTurbolinks = browserSupportsPushState && browserIsntBuggy && requestMethodIsSafe;
browserSupportsCustomEvents = document.addEventListener && document.createEvent;
if (browserSupportsCustomEvents) {
installDocumentReadyPageEventTriggers();
installJqueryAjaxSuccessPageUpdateTrigger();
}
if (browserSupportsTurbolinks) {
visit = fetch;
initializeTurbolinks();
} else {
visit = function(url) {
return document.location.href = url;
};
}
this.Turbolinks = {
visit: visit,
pagesCached: pagesCached,
enableTransitionCache: enableTransitionCache,
enableProgressBar: enableProgressBar,
allowLinkExtensions: Link.allowExtensions,
supported: browserSupportsTurbolinks,
EVENTS: clone(EVENTS)
};
}).call(this);
......@@ -746,3 +746,5 @@ u2f.getApiVersion = function(callback, opt_timeoutSeconds) {
port.postMessage(req);
});
};
window.u2f || (window.u2f = u2f);
......@@ -16,12 +16,12 @@
/*
* CommonJS environment
*/
module.exports = fit(require('../../xterm'));
module.exports = fit(require('./xterm'));
} else if (typeof define == 'function') {
/*
* Require.js is available
*/
define(['../../xterm'], fit);
define(['./xterm'], fit);
} else {
/*
* Plain browser environment
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment